#!/bin/bash # vim: dict+=/usr/share/beakerlib/dictionary.vim cpt=.,w,b,u,t,i,k # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # runtest.sh of /CoreOS/opensc/Sanity/pkcs11-tool # Description: This is a sanity test for pkcs11-tool # Author: Jakub Jelen # # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # Copyright (c) 2018 Red Hat, Inc. # # This program is free software: you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation, either version 2 of # the License, or (at your option) any later version. # # This program is distributed in the hope that it will be # useful, but WITHOUT ANY WARRANTY; without even the implied # warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR # PURPOSE. See the GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see http://www.gnu.org/licenses/. # # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Include Beaker environment . /usr/share/beakerlib/beakerlib.sh || exit 1 PACKAGE="opensc" ## from OpenSC/src/tests/p11test/runtest.sh SOPIN="12345678" PIN="123456" export GNUTLS_PIN=$PIN GENERATE_KEYS=1 PKCS11_TOOL="pkcs11-tool" NSSDB=db function generate_cert() { TYPE="$1" ID="$2" LABEL="$3" # Generate key pair $PKCS11_TOOL --keypairgen --key-type="$TYPE" --login --pin=$PIN \ --module="$P11LIB" --label="$LABEL" --id=$ID if [[ "$?" -ne "0" ]]; then echo "Couldn't generate $TYPE key pair" return 1 fi # check type value for the PKCS#11 URI (RHEL7 is using old "object-type") TYPE_KEY="type" p11tool --list-all --provider="$P11LIB" --login | grep "object-type" && \ TYPE_KEY="object-type" # Generate certificate certtool --generate-self-signed --outfile="$ID.cert" --template=cert.cfg \ --provider="$P11LIB" --load-privkey "pkcs11:object=$LABEL;$TYPE_KEY=private" \ --load-pubkey "pkcs11:object=$LABEL;$TYPE_KEY=public" # convert to DER: openssl x509 -inform PEM -outform DER -in "$ID.cert" -out "$ID.cert.der" # Write certificate #p11tool --login --write --load-certificate="$ID.cert" --label="$LABEL" \ # --provider="$P11LIB" $PKCS11_TOOL --write-object "$ID.cert.der" --type=cert --id=$ID \ --label="$LABEL" --module="$P11LIB" rm "$ID.cert.der" # Extract public key, which is more digestible by some of the tools openssl x509 -inform PEM -in $ID.cert -pubkey > $ID.pub p11tool --login --provider="$P11LIB" --list-all } function card_setup() { case $1 in "softhsm") P11LIB="/usr/lib64/pkcs11/libsofthsm2.so" echo "directories.tokendir = .tokens/" > .softhsm2.conf echo "slots.removable = true" >> .softhsm2.conf echo "objectstore.backend = file" >> .softhsm2.conf echo "log.level = INFO" >> .softhsm2.conf mkdir ".tokens" export SOFTHSM2_CONF=".softhsm2.conf" # Init token softhsm2-util --init-token --slot 0 --label "SC test" --so-pin="$SOPIN" --pin="$PIN" ;; "opencryptoki") # Supports only RSA mechanisms P11LIB="/usr/lib64/pkcs11/libopencryptoki.so" SO_PIN=87654321 SLOT_ID=3 # swtok slot rlServiceStart "pkcsslotd" echo "test_swtok" | /usr/sbin/pkcsconf -I -c $SLOT_ID -S $SO_PIN /usr/sbin/pkcsconf -u -c $SLOT_ID -S $SO_PIN -n $PIN ;; "libcacard") # Remove OpenSC from p11-kit so we do not recurse rlRun "rlFileBackup /usr/share/p11-kit/modules/" rlRun "rm /usr/share/p11-kit/modules/opensc.module" # we use softhsm internally rlRun "card_setup softhsm" # Setup NSS DB rlRun "mkdir $NSSDB" # Do not add a softhsm2 to the nssdb if there is already p11-kit-proxy rlRun "modutil -create -dbdir sql:$NSSDB -force" rlRun "modutil -list -dbdir sql:$NSSDB | grep 'library name: p11-kit-proxy.so'" 0,1 if [ "$?" = "1" ]; then rlRun "modutil -force -add 'SoftHSM PKCS#11' -dbdir sql:$NSSDB -libfile $P11LIB" fi # Download and Install vsmartcard and virt_cacard rlRun "yes | dnf copr enable jjelen/vsmartcard" rlRun "dnf install -y virt_cacard virtualsmartcard" # Install the temporary SELinux policy rlRun "semodule -i virtcacard.cil" # Restart pcscd rlRun "systemctl restart pcscd" # Start virtcacard #rlRun "G_MESSAGES_DEBUG=libcacard LIBCACARD_DEBUG=1 ./virt_cacard/virt_cacard 2> virt_cacard.debug &" rlRun "/usr/bin/virt_cacard 2> virt_cacard.debug &" rlRun "sleep 5" # We will use OpenSC directly from here P11LIB="/usr/lib64/pkcs11/opensc-pkcs11.so" rlRun "$PKCS11_TOOL -O" # The keys are already generated in softhsm return 0 ;; *) echo "Error: Missing argument." exit 1; ;; esac if [[ $GENERATE_KEYS -eq 1 ]]; then # Generate 1024b RSA Key pair generate_cert "RSA:1024" "0001" "RSA1024" # Generate 2048b RSA Key pair generate_cert "RSA:2048" "0002" "RSA2048" # Generate 3092b RSA Key pair generate_cert "RSA:2048" "0003" "RSA3" fi } function card_cleanup() { case $1 in "softhsm") rm .softhsm2.conf rm -rf ".tokens" ;; "libcacard") rlRun "pkill virt_cacard" 0,1 rlFileSubmit virt_cacard.debug rlRun "rm -rf $NSSDB" card_cleanup softhsm rlRun "rlFileRestore" ;; esac if [[ $GENERATE_KEYS -eq 1 ]]; then rm "0{1,2,3,4}.{cert,pub}" fi } rlJournalStart rlPhaseStartSetup "General setup" rlAssertRpm $PACKAGE rlPhaseEnd for BACKEND in "softhsm" "opencryptoki" "libcacard"; do rlPhaseStartSetup "Set up $BACKEND" rlAssertRpm $BACKEND rlRun "TmpDir=\$(mktemp -d)" 0 "Creating tmp directory" rlRun "cp cert.cfg virtcacard.cil $TmpDir" rlRun "pushd $TmpDir" rlRun "card_setup $BACKEND" rlRun 'echo "data to sign (max 100 bytes)" > data' # Read the certificates from the module (the IDs might get mixed up in libcacard) for ID in "0001" "0002" "0003"; do rlRun ">$ID.cert" rlRun "$PKCS11_TOOL --read-object --id $ID --type cert --output-file $ID.cert --module $P11LIB" rlRun "openssl x509 -inform DER -in $ID.cert -pubkey > $ID.pub" done rlPhaseEnd for HASH in "" "SHA1" "SHA224" "SHA256" "SHA384" "SHA512"; do for SIGN_KEY in "0001" "0002" "0003"; do METHOD="RSA-PKCS" if [[ ! -z $HASH ]]; then METHOD="$HASH-$METHOD" fi # OpenCryptoki does not work with hashed mechanisms if [[ "$BACKEND" != "opencryptoki" ]]; then rlPhaseStartTest "$BACKEND: $METHOD: Sign & Verify (KEY $SIGN_KEY)" rlRun "$PKCS11_TOOL --id $SIGN_KEY -s -p $PIN -m $METHOD --module $P11LIB \ --input-file data --output-file data.sig" # OpenSSL verification if [[ -z $HASH ]]; then rlRun "openssl rsautl -verify -pubin -inkey $SIGN_KEY.pub -in data.sig" else rlRun "openssl dgst -verify $SIGN_KEY.pub -${HASH,,*} \ -signature data.sig data" fi # pkcs11-tool verification rlRun "$PKCS11_TOOL --id $SIGN_KEY --verify -m $METHOD --module $P11LIB \ --input-file data --signature-file data.sig" rlRun "rm data.sig" rlPhaseEnd fi METHOD="$METHOD-PSS" if [[ "$HASH" == "SHA512" ]]; then continue; # This one is broken fi rlPhaseStartTest "$BACKEND: $METHOD: Sign & Verify (KEY $SIGN_KEY)" if [[ -z $HASH ]]; then # hashing is done outside of the module. We chose here SHA256 rlRun "openssl dgst -binary -sha256 data > data.hash" HASH_ALGORITM="--hash-algorithm=SHA256" VERIFY_DGEST="-sha256" VERIFY_OPTS="-sigopt rsa_mgf1_md:sha256" else # hashing is done inside of the module rlRun "cp data data.hash" HASH_ALGORITM="" VERIFY_DGEST="-${HASH,,*}" VERIFY_OPTS="-sigopt rsa_mgf1_md:${HASH,,*}" fi rlRun "$PKCS11_TOOL --id $SIGN_KEY -s -p $PIN -m $METHOD --module $P11LIB \ $HASH_ALGORITM --salt-len=-1 \ --input-file data.hash --output-file data.sig" # OpenSSL verification rlRun "openssl dgst -verify $SIGN_KEY.pub $VERIFY_DGEST \ -sigopt rsa_padding_mode:pss $VERIFY_OPTS -sigopt rsa_pss_saltlen:-1 \ -signature data.sig data" # pkcs11-tool verification rlRun "$PKCS11_TOOL --id $SIGN_KEY --verify -m $METHOD --module $P11LIB \ $HASH_ALGORITM --salt-len=-1 \ --input-file data.hash --signature-file data.sig" rlRun "rm data.{sig,hash}" rlPhaseEnd done # Skip hashed algorithms (do not support encryption & decryption) if [[ ! -z "$HASH" ]]; then continue; fi METHOD="RSA-PKCS" for ENC_KEY in "0001" "0002" "0003"; do rlPhaseStartTest "$BACKEND: $METHOD: Encrypt & Decrypt (KEY $ENC_KEY)" # OpenSSL Encryption rlRun "openssl rsautl -encrypt -pubin -inkey $ENC_KEY.pub -in data \ -out data.crypt" rlRun "$PKCS11_TOOL --id $ENC_KEY --decrypt -p $PIN -m $METHOD \ --module $P11LIB --input-file data.crypt > data.decrypted" rlRun "diff data{,.decrypted}" rlRun "rm data.{crypt,decrypted}" # TODO pkcs11-tool encryption rlPhaseEnd done done rlPhaseStartCleanup "Cleanup $BACKEND" card_cleanup $BACKEND rlRun "popd" rlRun "rm -r $TmpDir" 0 "Removing tmp directory" rlPhaseEnd done rlJournalPrintText rlJournalEnd