Simple demo of signing a container image usng cosign where the private key is embedded inside a Trusted Platform Module (TPM)
We will achieve that through cosign’s PKCS-11
integration which is enabled when its compiled with a specific flag.
Also see
Anyway,
gcloud compute instances create cosign-test \
--zone=us-central1-a --machine-type=e2-medium --no-service-account --no-scopes \
--image=debian-11-bullseye-v20211105 --image-project=debian-cloud \
--shielded-secure-boot --shielded-vtpm --shielded-integrity-monitoring
gcloud compute ssh cosign-test
sudo su -
apt-get update
We’re only installing docker here to pull the public image
apt -y install apt-transport-https ca-certificates curl gnupg2 software-properties-common wget jq
curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list
apt-get update
apt-get install docker-ce docker-ce-cli containerd.io
wget https://go.dev/dl/go1.19.2.linux-amd64.tar.gz
rm -rf /usr/local/go && tar -C /usr/local -xzf go1.19.2.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin/
Now install the PKCS-11 library provided through libtpm2-pkcs11-1
apt-get update && apt-get install libtpm2-pkcs11-1 tpm2-tools libengine-pkcs11-openssl opensc -y
Initialize the TPM with an RSA KeyPair
pkcs11-tool --module /usr/lib/x86_64-linux-gnu/libtpm2_pkcs11.so.1 --slot-index= --init-token --label="token1" --so-pin="mysopin"
pkcs11-tool --module /usr/lib/x86_64-linux-gnu/libtpm2_pkcs11.so.1 --label="token1" --init-pin --so-pin mysopin --pin mynewpin
pkcs11-tool --module /usr/lib/x86_64-linux-gnu/libtpm2_pkcs11.so.1 --list-token-slots
pkcs11-tool --module /usr/lib/x86_64-linux-gnu/libtpm2_pkcs11.so.1 --list-mechanisms --slot-index 0
pkcs11-tool --module /usr/lib/x86_64-linux-gnu/libtpm2_pkcs11.so.1 --label="keylabel1" --login --pin=mynewpin --id 0 --keypairgen --key-type rsa:2048
pkcs11-tool --module /usr/lib/x86_64-linux-gnu/libtpm2_pkcs11.so.1 --label="keylabel1" --pin mynewpin --generate-random 50 | xxd -p
Now install cosign with the pkcs-11 support (see cosign pkcs-11)
apt-get install gcc git
git clone https://github.com/sigstore/cosign.git
cd cosign
go build -tags=pkcs11key ./cmd/cosign
export PATH=$PATH:`pwd`
Pull the image
export IMAGE=docker.io/salrashid123/myimage:server
export IMAGE_DIGEST=$IMAGE@sha256:83ab2ba6689713f2d68104cd208feadfebdd6bc881c455dcb55d2b45ac3a0753
docker pull $IMAGE_DIGEST
Set the PKCS URI values specific to the slot,key,id we setup earlier
export COSIGN_PKCS11_MODULE_PATH="/usr/lib/x86_64-linux-gnu/libtpm2_pkcs11.so.1"
export COSIGN_PKCS11_PIN="mynewpin"
export PKCS11_PUBLIC_KEY="pkcs11:model=vTPM;manufacturer=GOOG;serial=0000000000000000;token=token1;type=public;object=keylabel1?pin-value=mynewpin"
export PKCS11_PRIVATE_KEY="pkcs11:model=vTPM;manufacturer=GOOG;serial=0000000000000000;token=token1;type=private;object=keylabel1?pin-value=mynewpin"
Make sure cosign integration is working and the pkcs-11 module is up
$ cosign pkcs11-tool list-tokens --module-path /usr/lib/x86_64-linux-gnu/libtpm2_pkcs11.so.1
Listing tokens of PKCS11 module '/usr/lib/x86_64-linux-gnu/libtpm2_pkcs11.so.1'
Token in slot 1
Label: token1
Manufacturer: GOOG
Model: vTPM
S/N: 0000000000000000
Token in slot 2
Label:
Manufacturer: GOOG
Model: vTPM
S/N: 0000000000000000
Finally sign
$ cosign sign --key "$PKCS11_PRIVATE_KEY" --upload=false $IMAGE_DIGEST --no-tlog-upload=true --output-signature sig.txt
# your signature value will clearly be different
$ cat sig.txt
HHLheqKOy/ra6KAs3018Pmb4idl3BqIn/haosST6dDSafHJqd8NHycC7cQyK6ua6g5wGjx9ktr59aDt875Usfpn0x1RCXqeAnmx3vyxVv1FSGZO2xrt1p/aT3JctIAn0ys+VCESpvQ4Ag+qDNvh0/gnNVxTXXoQ0g4ffOwEwAv9+bFNUMB4AeL7ngz6MgLo0Ll8MI41ee2xDen+M8ttUpRLWMLo63jFb9hftAxFNiJI8ls83jlTtbnPsr9fQUHHHdJgE50TdngtPBAaL5Gvpxvyy32oKcCBGFrz+6jLjIT1zbdT5Xxmg5kKV83WEwvG4XbOcL0WFDrhEYmJeD27FxA==
export public key to file and verify
pkcs11-tool --module /usr/lib/x86_64-linux-gnu/libtpm2_pkcs11.so.1 --slot 1 --read-object --type pubkey --id 0 -o rsa01pub.key
openssl rsa -pubin -inform DER -in rsa01pub.key -outform PEM -out rsa01pub.pem
cosign verify --key rsa01pub.pem $IMAGE --signature sig.txt | jq '.'
Alternatively, use pkcs-11 public key reference
cosign verify --key "$PKCS11_PUBLIC_KEY" $IMAGE --signature sig.txt | jq '.'
Either way, you’ll see verification completed
Verification for index.docker.io/salrashid123/myimage:server --
The following checks were performed on each of these signatures:
- The cosign claims were validated
- The signatures were verified against the specified public key
[
{
"critical": {
"identity": {
"docker-reference": "index.docker.io/salrashid123/myimage"
},
"image": {
"docker-manifest-digest": "sha256:83ab2ba6689713f2d68104cd208feadfebdd6bc881c455dcb55d2b45ac3a0753"
},
"type": "cosign container image signature"
},
"optional": null
}
]
THats it
The following is just references showing details of the embedded device
$ pkcs11-tool --module /usr/lib/x86_64-linux-gnu/libtpm2_pkcs11.so.1 --list-mechanisms --slot-index 0
Using slot with index 0 (0x1)
Supported mechanisms:
RSA-PKCS-KEY-PAIR-GEN, keySize={1024,2048}, hw, generate_key_pair
RSA-X-509, keySize={1024,2048}, hw, encrypt, decrypt, sign, verify
RSA-PKCS, keySize={1024,2048}, hw, encrypt, decrypt, sign, verify
RSA-PKCS-OAEP, keySize={1024,2048}, hw, encrypt, decrypt
SHA1-RSA-PKCS, keySize={1024,2048}, hw, sign, verify
SHA256-RSA-PKCS, keySize={1024,2048}, hw, sign, verify
SHA384-RSA-PKCS, keySize={1024,2048}, hw, sign, verify
ECDSA-KEY-PAIR-GEN, keySize={224,521}, hw, generate_key_pair
ECDSA, keySize={224,521}, hw, sign, verify
ECDSA-SHA1, keySize={224,521}, hw, sign, verify
AES-KEY-GEN, keySize={16,32}, hw, generate
AES-CBC, keySize={16,32}, hw, encrypt, decrypt
mechtype-0x2107, keySize={16,32}, hw, encrypt, decrypt
AES-ECB, keySize={16,32}, hw, encrypt, decrypt
SHA-1, digest
SHA256, digest
SHA384, digest
SHA512, digest
$ pkcs11-tool --module /usr/lib/x86_64-linux-gnu/libtpm2_pkcs11.so.1 --list-token-slots
Available slots:
Slot 0 (0x1): token1 GOOG
token label : token1
token manufacturer : GOOG
token model : vTPM
token flags : login required, rng, token initialized, PIN initialized
hardware version : 1.42
firmware version : 22.17
serial num : 0000000000000000
pin min/max : 0/128
Slot 1 (0x2): GOOG
token state: uninitialized
$ pkcs11-tool --module /usr/lib/x86_64-linux-gnu/libtpm2_pkcs11.so.1 --list-objects
Using slot 0 with a present token (0x1)
Public Key Object; RSA 2048 bits
label: keylabel1
ID: 00
Usage: encrypt, verify
Access: local
$ pkcs11-tool --module /usr/lib/x86_64-linux-gnu/libtpm2_pkcs11.so.1 --slot-index= --init-token --label="token1" --so-pin="mysopin"
Using slot with index 0 (0x1)
Token successfully initialized
$ pkcs11-tool --module /usr/lib/x86_64-linux-gnu/libtpm2_pkcs11.so.1 --label="token1" --init-pin --so-pin mysopin --pin mynewpin
Using slot 0 with a present token (0x1)
User PIN successfully initialized
$ pkcs11-tool --module /usr/lib/x86_64-linux-gnu/libtpm2_pkcs11.so.1 --list-token-slots
Available slots:
Slot 0 (0x1): token1 GOOG
token label : token1
token manufacturer : GOOG
token model : vTPM
token flags : login required, rng, token initialized, PIN initialized
hardware version : 1.42
firmware version : 22.17
serial num : 0000000000000000
pin min/max : 0/128
Slot 1 (0x2): GOOG
token state: uninitialized
$ pkcs11-tool --module /usr/lib/x86_64-linux-gnu/libtpm2_pkcs11.so.1 --label="keylabel1" --login --pin=mynewpin --id 0 --keypairgen --key-type rsa:2048
Using slot 0 with a present token (0x1)
Key pair generated:
Private Key Object; RSA
label: keylabel1
ID: 00
Usage: decrypt, sign
Access: sensitive, always sensitive, never extractable, local
Allowed mechanisms: RSA-X-509,RSA-PKCS-OAEP,RSA-PKCS,SHA1-RSA-PKCS,SHA256-RSA-PKCS,SHA384-RSA-PKCS,SHA512-RSA-PKCS,RSA-PKCS-PSS,SHA1-RSA-PKCS-PSS,SHA256-RSA-PKCS-PSS,SHA384-RSA-PKCS-PSS,SHA512-RSA-PKCS-PSS
Public Key Object; RSA 2048 bits
label: keylabel1
ID: 00
Usage: encrypt, verify
Access: local
$ pkcs11-tool --module /usr/lib/x86_64-linux-gnu/libtpm2_pkcs11.so.1 --label="keylabel1" --pin mynewpin --generate-random 50 | xxd -p
Using slot 0 with a present token (0x1)
2f3fe08ffdb6c65dbc24dbccec277ae9614005b63ed586ba0f813814ae08
18db453c29db67867bcdc2e51ecd2f568f312a9f
This site supports webmentions. Send me a mention via this form.