123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- # SPDX-License-Identifier: BSD-3-Clause
- source helpers.sh
- file_primary_key_ctx=context.p_B1
- file_signing_key_pub=opuB1_B8
- file_signing_key_priv=oprB1_B8
- file_signing_key_ctx=context_load_out_B1_B8
- file_signing_key_name=name.load.B1_B8
- file_signing_key_pub_pem=oppB1_B8
- file_input_data=secret.data
- file_input_digest=secret.digest
- file_output_data=sig.4
- file_output_ticket=secret.ticket
- file_output_hash=secret.hash
- rsa_key_type=rsa2048
- ecc_key_type=ecc256
- handle_signing_key=0x81010005
- alg_hash=sha256
- alg_primary_key=rsa
- cleanup() {
- rm -f $file_input_data $file_primary_key_ctx $file_signing_key_pub \
- $file_signing_key_priv $file_signing_key_ctx $file_signing_key_name \
- $file_output_data $file_input_digest $file_output_ticket \
- $file_output_hash $file_signing_key_pub_pem
- tpm2 evictcontrol -Q -Co -c $handle_signing_key 2>/dev/null || true
- if [ "$1" != "no-shut-down" ]; then
- shut_down
- fi
- }
- trap cleanup EXIT
- test_symmetric() {
- local alg_signing_key=$1
- echo "12345678" > $file_input_data
- tpm2 clear
- tpm2 createprimary -Q -C e -g $alg_hash -G $alg_primary_key \
- -c $file_primary_key_ctx
- tpm2 create -Q -g $alg_hash -G $alg_signing_key -u $file_signing_key_pub \
- -r $file_signing_key_priv -C $file_primary_key_ctx
- tpm2 load -Q -C $file_primary_key_ctx -u $file_signing_key_pub \
- -r $file_signing_key_priv -n $file_signing_key_name -c $file_signing_key_ctx
- tpm2 sign -Q -c $file_signing_key_ctx -g $alg_hash \
- -o $file_output_data $file_input_data
- rm -f $file_output_data
- tpm2 evictcontrol -Q -C o -c $file_signing_key_ctx $handle_signing_key
- tpm2 sign -Q -c $handle_signing_key -g $alg_hash -o $file_output_data \
- $file_input_data
- rm -f $file_output_data
- # generate hash and test validation
- tpm2 hash -Q -C e -g $alg_hash -o $file_output_hash -t $file_output_ticket \
- $file_input_data
- tpm2 sign -Q -c $handle_signing_key -g $alg_hash -o $file_output_data \
- -t $file_output_ticket $file_input_data
- rm -f $file_output_data
- # test with digest, no validation
- shasum -a 256 $file_input_data | awk '{ print "000000 " $1 }' | xxd -r -c 32 > \
- $file_input_digest
- tpm2 sign -Q -c $handle_signing_key -g $alg_hash -d -o $file_output_data \
- $file_input_digest
- rm -f $file_output_data
- }
- create_signature() {
- local sign_scheme=$1
- if [ "$sign_scheme" = "" ]; then
- tpm2 sign -Q -c $file_signing_key_ctx -g $alg_hash -f plain \
- -o $file_output_data $file_input_data
- else
- tpm2 sign -Q -c $file_signing_key_ctx -g $alg_hash -s $sign_scheme \
- -f plain -o $file_output_data $file_input_data
- fi
- }
- get_openssl_version_number() {
- # Ubuntu 14.04, 16.04, 18.04 and 19.04:
- # "OpenSSL 1.0.1f 6 Jan 2014"
- # "OpenSSL 1.0.2g 1 Mar 2016"
- # "OpenSSL 1.1.0g 2 Nov 2017"
- # "OpenSSL 1.1.1b 26 Feb 2019"
- if [ -z "$1" ]; then
- local openssl_version=$(openssl version -v)
- else
- local openssl_version="$1"
- fi
- local openssl_version_parsed=$(echo "$openssl_version" | sed -r 's/^OpenSSL ([0-9]+)\.([0-9]+)\.([0-9]+).*$/\1 \2 \3/')
- local openssl_v1=$(echo $openssl_version_parsed | cut -d ' ' -f 1)
- local openssl_v2=$(echo $openssl_version_parsed | cut -d ' ' -f 2)
- local openssl_v3=$(echo $openssl_version_parsed | cut -d ' ' -f 3)
- local openssl_version_num=$(("$openssl_v1"<<16 + "$openssl_v2"<<8 + "$openssl_v3"))
- echo "$openssl_version_num"
- }
- verify_signature() {
- local sign_scheme=$1
- if [ "$sign_scheme" = "rsapss" ] ; then
- # Explanation:
- # RSA-PSS has a parameter called salt length.
- # You need to know what value of salt length was used to create the
- # signature in order to verify the signature.
- # OpenSSL can actually automatically determine the correct value, so
- # strictly speaking we could just let it and simplify this test a lot.
- # But, if you want to verify the signature using some other API,
- # you might need to know the salt length used by the TPM to produce the
- # signature.
- # It can be either "digest" or "max". You can use openssl the check
- # whether it's "digest", and if it's not then it's "max".
- # From TCG TPM 2.0, Part 1: Architecture, Appendix B.7
- # "... the random salt length will be the largest size allowed by the
- # key size and message digest size."
- # From NIST FIPS PUB 186-4, Section 5.5
- # "... the length (in bytes) of the salt (sLen) shall satisfy
- # 0 <= sLen <= hLen, where hLen is the length of the hash function
- # output block (in bytes)."
- # From TCG FIPS 140-2 Guidance for TPM 2.0, Section 5.2.1.3
- # "If the TPM implementation is required to be compliant with FIPS 186-4,
- # then the random salt length will be the largest size allowed by that
- # specification."
- # Thus, if the TPM is in "FIPS mode", PSS salt length is "digest",
- # otherwise PSS salt length is "max".
- # Either one is accepted by this test.
- # The IBM TPM software emulator (at least the version in ibmtpm1332.tar.gz)
- # uses "digest".
- local openssl_current_version_num=$(get_openssl_version_number)
- local openssl_1_1_1_version_num=$(get_openssl_version_number "OpenSSL 1.1.1")
- # Explanation:
- # In version 1.1.1, openssl switched from "-1","-2" (meaning "digest" and
- # "auto" correspondingly) to "digest", "max" and "auto".
- # See section "rsa_pss_saltlen:len" in
- # https://github.com/openssl/openssl/blob/OpenSSL_1_1_1-stable/doc/man1/pkeyutl.pod
- # and same section in
- # https://github.com/openssl/openssl/blob/OpenSSL_1_1_0-stable/doc/apps/pkeyutl.pod
- if [ "$openssl_current_version_num" -ge "$openssl_1_1_1_version_num" ] ; then
- local pss_salt_len_arg_digest="digest"
- local pss_salt_len_arg_max="max"
- local pss_salt_len_arg_auto="auto"
- else
- local pss_salt_len_arg_digest="-1"
- local pss_salt_len_arg_auto="-2"
- fi
- openssl pkeyutl -verify \
- -in $file_input_digest \
- -sigfile $file_output_data \
- -pubin \
- -inkey $file_signing_key_pub_pem \
- -keyform pem \
- -pkeyopt digest:$alg_hash \
- -pkeyopt rsa_padding_mode:pss \
- -pkeyopt rsa_pss_saltlen:$pss_salt_len_arg_digest \
- |& grep -q '^Signature Verified Successfully' \
- || \
- openssl pkeyutl -verify \
- -in $file_input_digest \
- -sigfile $file_output_data \
- -pubin \
- -inkey $file_signing_key_pub_pem \
- -keyform pem \
- -pkeyopt digest:$alg_hash \
- -pkeyopt rsa_padding_mode:pss \
- -pkeyopt rsa_pss_saltlen:$pss_salt_len_arg_auto \
- |& grep -q '^Signature Verified Successfully'
- else
- openssl pkeyutl -verify \
- -in $file_input_digest \
- -sigfile $file_output_data \
- -pubin \
- -inkey $file_signing_key_pub_pem \
- -keyform pem \
- -pkeyopt digest:$alg_hash \
- |& grep -q '^Signature Verified Successfully'
- fi
- }
- test_asymmetric() {
- local alg_signing_key=$1
- head -c30 /dev/urandom > $file_input_data
- shasum -a 256 $file_input_data | awk '{ print "000000 " $1 }' | \
- xxd -r -c 32 > $file_input_digest
- tpm2 clear
- tpm2 createprimary -Q -C e -g $alg_hash -G $alg_primary_key \
- -c $file_primary_key_ctx
- tpm2 create -Q -g $alg_hash -G $alg_signing_key -u $file_signing_key_pub \
- -r $file_signing_key_priv -C $file_primary_key_ctx
- tpm2 load -Q -C $file_primary_key_ctx -u $file_signing_key_pub \
- -r $file_signing_key_priv -n $file_signing_key_name -c $file_signing_key_ctx
- tpm2 readpublic -Q -c $file_signing_key_ctx --format=pem \
- -o $file_signing_key_pub_pem
- local sign_scheme
- if [ "$alg_signing_key" = "$rsa_key_type" ] ; then
- for sign_scheme in "" "rsassa" "rsapss"
- do
- create_signature $sign_scheme
- verify_signature $sign_scheme
- rm -f $file_output_data
- done
- fi
- if [ "$alg_signing_key" = "$ecc_key_type" ]; then
- for sign_scheme in "" "ecdsa"
- do
- create_signature $sign_scheme
- verify_signature $sign_scheme
- rm -f $file_output_data
- done
- fi
- }
- start_up
- cleanup "no-shut-down"
- # make sure commands failing inside the function will cause the script to fail!
- (
- set -e
- test_symmetric "hmac"
- cleanup "no-shut-down"
- )
- for key_type in $rsa_key_type $ecc_key_type
- do
- # make sure commands failing inside the function will cause the script
- # to fail!
- (
- set -e
- test_asymmetric $key_type
- cleanup "no-shut-down"
- )
- done
- # Test signing with ecdaa scheme
- head -c30 /dev/urandom | openssl dgst -sha256 -binary > test.rnd
- tpm2 clear
- tpm2 createprimary -Q -C o -c prim.ctx -g sha256 -G rsa
- tpm2 create -Q -g sha256 -G ecc256:ecdaa -u key.pub -r key.priv -C prim.ctx
- tpm2 load -C prim.ctx -u key.pub -r key.priv -n key.name -c key.ctx
- tpm2 readpublic -c key.ctx --format=pem -o key.pem
- tpm2 commit -c key.ctx -t commit.ctr --eccpoint-K K.bin --eccpoint-L L.bin -u E.bin
- tpm2 commit -c key.ctx -t commit.ctr --eccpoint-K K.bin --eccpoint-L L.bin -u E.bin
- tpm2 sign -c key.ctx -g sha256 -o test.sig test.rnd -s ecdaa --commit-index 1
- tpm2 sign -c key.ctx -g sha256 -o test.sig test.rnd -s ecdaa
- # Test that invalid password returns the proper code
- cleanup "no-shut-down"
- echo "12345678" > $file_input_data
- tpm2 createprimary -Q -c $file_primary_key_ctx
- tpm2 create -Q -C $file_primary_key_ctx -u $file_signing_key_pub \
- -r $file_signing_key_priv -p "mypassword"
- tpm2 load -Q -C $file_primary_key_ctx -u $file_signing_key_pub \
- -r $file_signing_key_priv -n $file_signing_key_name -c $file_signing_key_ctx
- # Negative test, remove error handler
- trap - ERR
- tpm2 sign -Q -p "badpassword" -c $file_signing_key_ctx -g $alg_hash \
- -o $file_output_data $file_input_data
- if [ $? != 3]; then
- echo "Expected RC 3, got: $?" 1>&2
- fi
- trap onerror ERR
- exit 0
|