| #!/usr/bin/env bash |
| |
| # For the license, see the LICENSE file in the root directory. |
| #set -x |
| |
| TOPBUILD=${abs_top_builddir:-$(dirname "$0")/..} |
| TESTDIR=${abs_top_testdir:-$(dirname "$0")} |
| |
| SWTPM_LOCALCA=${TOPBUILD}/src/swtpm_localca/swtpm_localca |
| |
| workdir="$(mktemp -d)" || exit 1 |
| |
| # Have softhsm_setup use 'workdir'. |
| export SOFTHSM_SETUP_CONFIGDIR="${workdir}" |
| |
| # Since we will be using the pkcs11 module as well via certtool |
| # we have to set the environment variable to point to its config file. |
| # This has to be the same as for swtpm_setup sets it. |
| export SOFTHSM2_CONF="${workdir}"/softhsm2.conf |
| |
| ek="80" # 2048 bit key must have highest bit set |
| for ((i = 1; i < 256; i++)); do |
| ek="${ek}$(printf "%02x" "$i")" |
| done |
| |
| ISSUERCERT="${workdir}/issuercert.pem" |
| CERTSERIAL="${workdir}/certserial" |
| |
| PATH="${TOPBUILD}/src/swtpm_cert:$PATH" |
| |
| source "${TESTDIR}/common" |
| |
| if ${CERTTOOL} --help | grep -q -E "\-\-verify-profile"; then |
| verify_profile="--verify-profile=medium" |
| fi |
| |
| trap "cleanup" SIGTERM EXIT |
| |
| function cleanup() |
| { |
| rm -rf "${workdir}" |
| "${TESTDIR}/softhsm_setup" teardown |
| } |
| |
| skip_test_linked_with_asan "${SWTPM_LOCALCA}" |
| |
| unset GNUTLS_PIN |
| export PIN="abcdef" |
| |
| # Generate the PKCS11 token and key; it uses env. variable 'PIN' |
| if ! msg=$("${TESTDIR}/softhsm_setup" setup 2>&1); then |
| echo -e "Could not setup softhsm:\n${msg}" |
| echo "softhsm needs to be v2.3.0 or greater and pkcs11 correctly configured" |
| exit 77 |
| fi |
| pkcs11uri=$(echo "${msg}" | sed -n 's|^keyuri: \(.*\)|\1|p') |
| |
| # Now we need to create the root CA ... |
| template="${workdir}/template" |
| |
| cakey="${workdir}/swtpm-localca-rootca-privkey.pem" |
| cacert="${workdir}/swtpm-localca-rootca-cert.pem" |
| |
| # first the private key |
| if ! msg=$(${CERTTOOL} \ |
| --generate-privkey \ |
| --outfile "${cakey}" \ |
| 2>&1); then |
| echo "Could not create root-CA key ${cakey}." |
| echo "${msg}" |
| exit 1 |
| fi |
| chmod 640 "${cakey}" |
| |
| # now the self-signed certificate |
| cat <<_EOF_ > "${template}" |
| cn=swtpm-localca-rootca |
| ca |
| cert_signing_key |
| expiration_days = 3650 |
| _EOF_ |
| |
| if ! msg=$(${CERTTOOL} \ |
| --generate-self-signed \ |
| --template "${template}" \ |
| --outfile "${cacert}" \ |
| --load-privkey "${cakey}" \ |
| 2>&1); then |
| echo "Could not create root CA." |
| echo "${msg}" |
| exit 1 |
| fi |
| |
| # And now create the intermediate CA with the pkcs11 URI key |
| |
| pubkey="${workdir}/swtpm-localca-interm-pubkey.pem" |
| |
| if ! msg=$(GNUTLS_PIN=${PIN} ${CERTTOOL} \ |
| --load-privkey "${pkcs11uri}" \ |
| --pubkey-info \ |
| --outfile "${pubkey}"); then |
| echo "Could not get public key for pkcs11 uri key ($pkcs11uri}." |
| echo "${msg}" |
| exit 1 |
| fi |
| |
| cat <<_EOF_ > "${template}" |
| cn=swtpm-localca |
| ca |
| cert_signing_key |
| expiration_days = 3650 |
| _EOF_ |
| |
| if ! msg=$(GNUTLS_PIN=${PIN} ${CERTTOOL} \ |
| --generate-certificate \ |
| --template "${template}" \ |
| --outfile "${ISSUERCERT}" \ |
| --load-ca-privkey "${cakey}" \ |
| --load-ca-certificate "${cacert}" \ |
| --load-privkey "${pkcs11uri}" \ |
| --load-pubkey "${pubkey}" \ |
| 2>&1); then |
| echo "Could not create intermediate CA" |
| echo "${msg}" |
| exit 1 |
| fi |
| |
| echo -n 1 > "${CERTSERIAL}" |
| |
| # Now we can create the config files |
| cat <<_EOF_ > "${workdir}/swtpm-localca.conf" |
| statedir = ${workdir} |
| signingkey = ${pkcs11uri//;/\\;} |
| issuercert = ${ISSUERCERT} |
| certserial = ${CERTSERIAL} |
| SWTPM_PKCS11_PIN = ${PIN} |
| _EOF_ |
| |
| cat <<_EOF_ > "${workdir}/swtpm-localca.options" |
| --tpm-manufacturer IBM |
| --tpm-model swtpm-libtpms |
| --tpm-version 2 |
| --platform-manufacturer Fedora |
| --platform-version 2.1 |
| --platform-model QEMU |
| _EOF_ |
| |
| # the following contains the test parameters and |
| # expected key usage |
| for testparams in \ |
| "--allow-signing|Digital signature" \ |
| "--allow-signing --decryption|Digital signature,Key encipherment" \ |
| "--decryption|Key encipherment" \ |
| "|Key encipherment"; |
| do |
| params=$(echo "${testparams}" | cut -d"|" -f1) |
| usage=$(echo "${testparams}" | cut -d"|" -f2) |
| |
| if ! msg=$(${SWTPM_LOCALCA} \ |
| --type ek \ |
| --ek "${ek}" \ |
| --dir "${workdir}" \ |
| --vmid test \ |
| --tpm2 \ |
| --configfile "${workdir}/swtpm-localca.conf" \ |
| --optsfile "${workdir}/swtpm-localca.options" \ |
| --tpm-spec-family 2.0 --tpm-spec-revision 146 --tpm-spec-level 0 \ |
| ${params:+${params}} 2>&1); then |
| echo "Error: Test with parameters '$params' failed." |
| echo "${msg}" |
| if [[ "${msg}" =~ The\ requested\ PKCS\ #11\ object\ is\ not\ available ]]; then |
| # could be related to i386 executables on x86_64 host and |
| # libsofthsm.so only available for x86_64... |
| exit 77 |
| fi |
| exit 1 |
| fi |
| |
| if [ ! -r "${workdir}/ek.cert" ]; then |
| echo "${msg}" |
| echo "Error: ${workdir}/ek.cert was not created." |
| exit 1 |
| fi |
| |
| OIFS="$IFS" |
| IFS="," |
| |
| for u in $usage; do |
| if ! ${CERTTOOL} -i \ |
| --inder --infile "${workdir}/ek.cert" | \ |
| grep "Key Usage" -A2 | \ |
| grep -q "$u"; then |
| echo "Error: Could not find key usage $u in key created " \ |
| "with $params." |
| else |
| echo "Found '$u'" |
| fi |
| done |
| |
| IFS="$OIFS" |
| |
| ${CERTTOOL} \ |
| -i \ |
| --inder --infile "${workdir}/ek.cert" \ |
| --outfile "${workdir}/ek.pem" |
| |
| if ! GNUTLS_PIN=${PIN} ${CERTTOOL} \ |
| --verify \ |
| ${verify_profile:+${verify_profile}} \ |
| --load-ca-certificate "${ISSUERCERT}" \ |
| --infile "${workdir}/ek.pem"; then |
| echo "Error: Could not verify certificate chain." |
| exit 1 |
| fi |
| done |
| |
| exit 0 |