When using TPM 2.0 with a Alpine Linux based host in order to generate certificates, specifically certificate sign requests (CSR’s), one will inevitably stumple upon tpm2-tss and its tpm2-tss engine for OpenSSL to generate a private key which resides in the TPM 2.0 module and a CSR that can be used to generate a signed certificate by any certificate authority.
Preface
An example could be
openssl req -new \
-engine tpm2tss \
-keyform engine \
-key 0x81000010 \
-sha256 \
-subj "/CN=$(hostname)/" \
-out device.csr
Which will emit a CSR. However when signing this very CSR, OpenSSL will return:
Certificate request self-signature did not match the contents
40B77A6FD27F0000:error:02000068:rsa routines:ossl_rsa_verify:bad signature:../crypto/rsa/rsa_sign.c:430:
40B77A6FD27F0000:error:1C880004:Provider routines:rsa_verify:RSA lib:../providers/implementations/signature/rsa_sig.c:774:
40B77A6FD27F0000:error:06880006:asn1 encoding routines:ASN1_item_verify_ctx:EVP lib:../crypto/asn1/a_verify.c:217:
This is due to a bug which is described here. And a possible solution is to, instead of using tpm2-tss, use tpm2-openssl.
However, Alpine Linux as of now, has no precompiled tpm2-openssl package. A quick solution can be to compile it manually, which I will demonstrate now.
Compiling
The following snippet already contains the required dependencies for convenience, as the tpm2-openssl installation instruction does not reference ready-to-use Alpine package names:
apk add tpm2-tools tpm2-tss tpm2-tss-tcti-device tpm2-tss-engine autoconf automake autoconf-archive gcc build-base pkgconf openssl-dev tpm2-tss-esys tpm2-tss-dev
git clone https://github.com/tpm2-software/tpm2-openssl.git && cd tpm2-openssl
# This is needed until https://github.com/tpm2-software/tpm2-openssl/pull/151 is merged
sed -i 's/sem_close(/sem_destroy(/g' src/tpm2-provider-semaphore.c
./bootstrap
./configure
make
make install
Packaging
Now, for easier distribution it may be useful to have an apk file at hand. We can in fact generate our own apk as shown:
# as root
apk add alpine-sdk
adduser builder
addgroup builder abuild
# as builder
su - builder
abuild-keygen -a
# as root
cp /home/builder/.abuild/*.pub /etc/apk/keys/
# as builder
mkdir -p ~/packages/tpm2-openssl
cd ~/packages/tpm2-openssl
nano APKBUILD
Our APKBUILD file could look like this:
# Maintainer: Your Name <you@example.com>
pkgname=tpm2-openssl
pkgver=1.3.0 # update to the version you want
pkgrel=0
pkgdesc="TPM2 provider for OpenSSL"
url="https://github.com/tpm2-software/tpm2-openssl"
arch="all"
license="BSD-2-Clause"
options="git !check" # repository has no stable test suite
source="$pkgname-$pkgver.tar.gz::https://github.com/tpm2-software/tpm2-openssl/archive/refs/tags/v1.3.0.tar.gz"
builddir="$srcdir/$pkgname-$pkgver"
# Build dependencies
makedepends="
tpm2-tools
tpm2-tss
tpm2-tss-tcti-device
tpm2-tss-engine
autoconf
automake
autoconf-archive
gcc
build-base
pkgconf
openssl-dev
tpm2-tss-esys
tpm2-tss-dev
"
prepare() {
default_prepare
# Temporary patch required until PR #151 is merged
sed -i 's/sem_close(/sem_destroy(/g' \
src/tpm2-provider-semaphore.c
}
build() {
sed -i '/git describe --tags --always --dirty > VERSION/s/^/# /' ./bootstrap
echo "$pkgver-experimental" > VERSION
./bootstrap
./configure --prefix=/usr
make
}
package() {
make DESTDIR="$pkgdir" install
}
sha512sums="
eed1d26817661ae8be7224bf1d4b295ae5ab9f4c7872bb305d57af28b18fd6cb0b0381f5c8239aec8f15a219bb90dc2d8d91852c7f3cbb5dd68bf4c42e1027f6 tpm2-openssl-1.3.0.tar.gz
"
Then we make the package:
abuild checksum
abuild -r
The resulting apk wil be placed in ~/packages/packages/x86_64 in my case:
$ tree
.
└── packages
├── packages
│ └── x86_64
│ ├── APKINDEX.tar.gz
│ └── tpm2-openssl-1.3.0-r0.apk
└── tpm2-openssl
└── APKBUILD
Installation
The direct installation can be forced with:
apk add --force-non-repository /home/builder/packages/packages/x86_64/tpm2-openssl-1.3.0-r0.apk
Usage
Once the OpenSSL provider is correctly installed, one usage example could be:
openssl req -new \
-provider tpm2 -provider default \
-propquery '?provider=tpm2' \
-subj "/CN=$(hostname)/" \
-key handle:0x81000010 \
-out device.csr