#!/usr/bin/env sh # Copyright 2021 Contributors to the Parsec project. # SPDX-License-Identifier: Apache-2.0 # Run simple end-two-end Parsec tests using parsec-tool and openssl ping_parsec() { echo "Checking Parsec service... " $PARSEC_TOOL ping } run_cmd() { "$@" EXIT_CODE=$(($EXIT_CODE+$?)) } debug() { if [ -n "$PARSEC_TOOL_DEBUG" ]; then "$@" fi } MY_TMP=$(mktemp -d) cleanup () { if [ -n "$MY_TMP" ]; then rm -rf -- "$MY_TMP" fi } trap cleanup EXIT delete_key() { # $1 - key type # $2 - key name KEY="$2" echo echo "- Deleting the $1 key" run_cmd $PARSEC_TOOL_CMD delete-key --key-name $KEY rm -f ${MY_TMP}/${KEY}.* } create_key() { # $1 - key type ("RSA" or "ECC") # $2 - key name # $3 - key usage ("SIGN" or "OAEP"), only consulted if $1 == "RSA" KEY="$2" if [ "$3" = "SIGN" -a "$1" = "RSA" ]; then EXTRA_CREATE_KEY_ARGS="--for-signing" elif [ "$3" = "OAEP" -a "$1" = "RSA" ]; then EXTRA_CREATE_KEY_ARGS="--oaep" else EXTRA_CREATE_KEY_ARGS="" fi echo echo "- Creating an $1 key and exporting its public part" type_lower=$(echo $1 | tr '[:upper:]' '[:lower:]') run_cmd $PARSEC_TOOL_CMD create-${type_lower}-key --key-name $KEY $EXTRA_CREATE_KEY_ARGS if ! run_cmd $PARSEC_TOOL_CMD list-keys | tee /dev/stderr | grep -q "$KEY"; then echo "Error: $KEY is not listed" EXIT_CODE=$(($EXIT_CODE+1)) fi run_cmd $PARSEC_TOOL_CMD export-public-key --key-name $KEY >${MY_TMP}/${KEY}.pem } test_crypto_provider() { # $1 - provider ID PARSEC_TOOL_CMD="$PARSEC_TOOL -p $1" echo echo "- Test random number generation" if run_cmd $PARSEC_TOOL_CMD list-opcodes 2>/dev/null | grep -q "PsaGenerateRandom"; then run_cmd $PARSEC_TOOL_CMD generate-random --nbytes 10 else echo "This provider doesn't support random number generation" fi if [ -z "$NO_PKCS1_V15" ]; then test_encryption "PKCS#1 v1.5" test_decryption "PKCS#1 v1.5" fi if [ -z "$NO_OAEP" ]; then test_encryption "OAEP" test_decryption "OAEP" fi test_signing "RSA" test_signing "ECC" test_csr "RSA" test_csr "ECC" test_rsa_key_bits test_rsa_key_bits 1024 } test_encryption() { # $1 - algorithm KEY="anta-key-rsa-encrypt" TEST_STR="$(date) Parsec public key encryption test" ALG="$1" create_key "RSA" "$KEY" "$ALG" # If the key was successfully created and exported if [ -s ${MY_TMP}/${KEY}.pem ]; then debug cat ${MY_TMP}/${KEY}.pem echo echo "- Encrypting \"$TEST_STR\" string using Parsec public key RSA $ALG encryption" # Encrypt TEST_STR with the public key using Parsec rather than openssl # (No need to base64 encode this, because parsec-tool already does it) run_cmd $PARSEC_TOOL_CMD encrypt --key-name $KEY "$TEST_STR" > ${MY_TMP}/${KEY}.enc echo echo "- Using Parsec to decrypt the result (with the private key):" run_cmd $PARSEC_TOOL_CMD decrypt $(cat ${MY_TMP}/${KEY}.enc) --key-name $KEY \ >${MY_TMP}/${KEY}.enc_str cat ${MY_TMP}/${KEY}.enc_str if [ "$(cat ${MY_TMP}/${KEY}.enc_str)" != "$TEST_STR" ]; then echo "Error: The result is different from the initial string" EXIT_CODE=$(($EXIT_CODE+1)) fi fi delete_key "RSA" $KEY } test_decryption() { # $1 - algorithm KEY="anta-key-rsa-crypt" TEST_STR="$(date) Parsec decryption test" ALG="$1" create_key "RSA" "$KEY" "$ALG" # If the key was successfully created and exported if [ -s ${MY_TMP}/${KEY}.pem ]; then debug cat ${MY_TMP}/${KEY}.pem echo echo "- Encrypting \"$TEST_STR\" string using openssl with RSA $ALG algorithm and the exported public key" # Encrypt TEST_STR with the public key and base64-encode the result printf "$TEST_STR" >${MY_TMP}/${KEY}.test_str if [ "$ALG" = "OAEP" ]; then pkeyopt="-pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256" else pkeyopt="" fi run_cmd $OPENSSL pkeyutl -encrypt $pkeyopt -pubin -inkey ${MY_TMP}/${KEY}.pem \ -in ${MY_TMP}/${KEY}.test_str -out ${MY_TMP}/${KEY}.bin run_cmd $OPENSSL base64 -A -in ${MY_TMP}/${KEY}.bin -out ${MY_TMP}/${KEY}.enc debug cat ${MY_TMP}/${KEY}.enc echo echo "- Using Parsec to decrypt the result:" run_cmd $PARSEC_TOOL_CMD decrypt $(cat ${MY_TMP}/${KEY}.enc) --key-name $KEY \ >${MY_TMP}/${KEY}.enc_str cat ${MY_TMP}/${KEY}.enc_str if [ "$(cat ${MY_TMP}/${KEY}.enc_str)" != "$TEST_STR" ]; then echo "Error: The result is different from the initial string" EXIT_CODE=$(($EXIT_CODE+1)) fi fi delete_key "RSA" $KEY } test_signing() { # $1 - key type ("RSA" or "ECC") KEY="anta-key-sign" TEST_STR="$(date) Parsec signature test" create_key $1 $KEY "SIGN" # If the key was successfully created and exported if [ -s ${MY_TMP}/${KEY}.pem ]; then debug cat ${MY_TMP}/${KEY}.pem echo echo "- Signing \"$TEST_STR\" string using the created $1 key" run_cmd $PARSEC_TOOL_CMD sign "$TEST_STR" --key-name $KEY >${MY_TMP}/${KEY}.sign debug cat ${MY_TMP}/${KEY}.sign echo echo "- Using openssl and the exported public $1 key to verify the signature" # Parsec-tool produces base64-encoded signatures. Let's decode it before verifing. run_cmd $OPENSSL base64 -d -a -A -in ${MY_TMP}/${KEY}.sign -out ${MY_TMP}/${KEY}.bin printf "$TEST_STR" >${MY_TMP}/${KEY}.test_str run_cmd $OPENSSL dgst -sha256 -verify ${MY_TMP}/${KEY}.pem \ -signature ${MY_TMP}/${KEY}.bin ${MY_TMP}/${KEY}.test_str fi delete_key $1 $KEY } test_csr() { # $1 - key type ("RSA" or "ECC") KEY="anta-key-csr" TEST_CN="parallaxsecond.com" TEST_SAN="localhost" TEST_SERIAL="EZ4U2CIXL" # CSR creation needs a signing key. create_key $1 $KEY "SIGN" # If the key was successfully created and exported if [ -s ${MY_TMP}/${KEY}.pem ]; then debug cat ${MY_TMP}/${KEY}.pem echo echo "- Creating a certificate signing request (CSR) from the test key." run_cmd $PARSEC_TOOL_CMD create-csr --cn ${TEST_CN} --san ${TEST_SAN} --serialNumber ${TEST_SERIAL} --key-name $KEY >${MY_TMP}/${KEY}.csr debug cat ${MY_TMP}/${KEY}.csr echo echo "- Using openssl to inspect the CSR content and verify the public key." run_cmd $OPENSSL req -text -noout -verify -in ${MY_TMP}/${KEY}.csr >${MY_TMP}/${KEY}.txt debug cat ${MY_TMP}/${KEY}.txt if ! cat ${MY_TMP}/${KEY}.txt | grep "Subject:" | grep "serialNumber = ${TEST_SERIAL}"; then echo "Error: The CSR does not contain the serialNumber field of the Distinguished Name" EXIT_CODE=$(($EXIT_CODE+1)) fi fi delete_key $1 $KEY } test_rsa_key_bits() { KEY="anta-key-rsa-bits" DEFAULT_SIZE=2048 if [ -n "$1" ]; then key_size=$1 key_param="--bits $1" else key_size=${DEFAULT_SIZE} key_param="" fi run_cmd $PARSEC_TOOL_CMD create-rsa-key --key-name $KEY $key_param run_cmd $PARSEC_TOOL_CMD export-public-key --key-name $KEY >${MY_TMP}/checksize-${KEY}.pem if ! run_cmd $OPENSSL rsa -pubin -text -noout -in ${MY_TMP}/checksize-${KEY}.pem | grep -q "Public-Key: (${key_size} bit)"; then echo "Error: create-rsa-key should have produced a ${key_size}-bit RSA key." EXIT_CODE=$(($EXIT_CODE+1)) fi delete_key "RSA" $KEY } PARSEC_TOOL_DEBUG= PROVIDER= # Test both RSA PKCS#1 v1.5 (default) and RSA OAEP encryption algorithms NO_OAEP= NO_PKCS1_V15= while [ "$#" -gt 0 ]; do case "$1" in -[0-9]* ) PROVIDER=${1#-} ;; -d ) PARSEC_TOOL_DEBUG="True" RUST_LOG="${RUST_LOG:-trace}" set -x ;; --no-oaep ) NO_OAEP="true" ;; --no-v1.5 ) NO_PKCS1_V15="true" ;; *) cat </dev/null | grep "^ID:" | grep -v "0x00" \ >${MY_TMP}/providers.lst exec < ${MY_TMP}/providers.lst while IFS= read -r prv; do # Format of list-providers output: #ID: 0x01 (Mbed Crypto provider) #ID: 0x03 (TPM provider) prv_id=$(echo $prv | cut -f 2 -d ' ') prv_id=$(echo $(($prv_id))) # Hex -> decimal if [ -z "$PROVIDER" ] || [ "$PROVIDER" -eq "$prv_id" ]; then prv_name=${prv##*(} prv_name=${prv_name%)*} echo echo "Testing $prv_name" test_crypto_provider $prv_id fi done exit $EXIT_CODE