From 4544cd573753ce2211808acaca8bf0d4dbc7011a Mon Sep 17 00:00:00 2001 From: Florian Wernli Date: Fri, 23 Feb 2024 11:39:39 +0100 Subject: [PATCH] encoder/decoder for Edwards curves Add the encoder and decoder methods for the ED25519 and Ed448 curves. Signed-off-by: Florian Wernli --- src/decoder.c | 48 ++++++++----------------------------- src/decoder.h | 35 +++++++++++++++++---------- src/encoder.c | 52 ++++++++++++++++++++++++---------------- src/encoder.h | 2 ++ src/provider.c | 12 ++++++++++ tests/tpem_encoder | 60 ++++++++++++++++++++++++++++++++++++++-------- 6 files changed, 128 insertions(+), 81 deletions(-) diff --git a/src/decoder.c b/src/decoder.c index a60299bb..08b19127 100644 --- a/src/decoder.c +++ b/src/decoder.c @@ -149,38 +149,6 @@ static int p11prov_der_decoder_p11prov_obj_decode( return ret; } -static int p11prov_der_decoder_p11prov_rsa_decode( - void *inctx, OSSL_CORE_BIO *cin, int selection, OSSL_CALLBACK *object_cb, - void *object_cbarg, OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) -{ - return p11prov_der_decoder_p11prov_obj_decode( - P11PROV_NAME_RSA, inctx, cin, selection, object_cb, object_cbarg, pw_cb, - pw_cbarg); -} - -const OSSL_DISPATCH p11prov_der_decoder_p11prov_rsa_functions[] = { - DISPATCH_BASE_DECODER_ELEM(NEWCTX, newctx), - DISPATCH_BASE_DECODER_ELEM(FREECTX, freectx), - DISPATCH_DECODER_ELEM(DECODE, der, p11prov, rsa, decode), - { 0, NULL } -}; - -static int p11prov_der_decoder_p11prov_ec_decode( - void *inctx, OSSL_CORE_BIO *cin, int selection, OSSL_CALLBACK *object_cb, - void *object_cbarg, OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) -{ - return p11prov_der_decoder_p11prov_obj_decode( - P11PROV_NAME_EC, inctx, cin, selection, object_cb, object_cbarg, pw_cb, - pw_cbarg); -} - -const OSSL_DISPATCH p11prov_der_decoder_p11prov_ec_functions[] = { - DISPATCH_BASE_DECODER_ELEM(NEWCTX, newctx), - DISPATCH_BASE_DECODER_ELEM(FREECTX, freectx), - DISPATCH_DECODER_ELEM(DECODE, der, p11prov, ec, decode), - { 0, NULL } -}; - static int p11prov_pem_decoder_p11prov_der_decode( void *inctx, OSSL_CORE_BIO *cin, int selection, OSSL_CALLBACK *object_cb, void *object_cbarg, OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) @@ -231,9 +199,13 @@ static int p11prov_pem_decoder_p11prov_der_decode( return ret; } -const OSSL_DISPATCH p11prov_pem_decoder_p11prov_der_functions[] = { - DISPATCH_BASE_DECODER_ELEM(NEWCTX, newctx), - DISPATCH_BASE_DECODER_ELEM(FREECTX, freectx), - DISPATCH_DECODER_ELEM(DECODE, pem, p11prov, der, decode), - { 0, NULL } -}; +P11PROV_DER_COMMON_DECODE_FN(P11PROV_NAME_RSA, rsa) +P11PROV_DER_COMMON_DECODE_FN(P11PROV_NAME_EC, ec) +P11PROV_DER_COMMON_DECODE_FN(P11PROV_NAME_ED25519, ed25519) +P11PROV_DER_COMMON_DECODE_FN(P11PROV_NAME_ED448, ed448) + +DISPATCH_DECODER_FN_LIST(pem, p11prov, der); +DISPATCH_DECODER_FN_LIST(der, p11prov, rsa); +DISPATCH_DECODER_FN_LIST(der, p11prov, ec); +DISPATCH_DECODER_FN_LIST(der, p11prov, ed25519); +DISPATCH_DECODER_FN_LIST(der, p11prov, ed448); diff --git a/src/decoder.h b/src/decoder.h index e3cd4f10..21fa92f4 100644 --- a/src/decoder.h +++ b/src/decoder.h @@ -10,30 +10,39 @@ #define RET_OSSL_STOP_DECODING 0 /* DECODERs */ -#define DISPATCH_TEXT_DECODER_FN(type, name) \ - static OSSL_FUNC_DECODER_##name##_fn p11prov_##type##_DECODER_##name##_text -#define DISPATCH_TEXT_DECODER_ELEM(NAME, type, name) \ - { \ - OSSL_FUNC_DECODER_##NAME, \ - (void (*)(void))p11prov_##type##_DECODER_##name \ - } -#define DISPATCH_BASE_DECODER_FN(name) \ - DECL_DISPATCH_FUNC(DECODER, p11prov_decoder_, name) #define DISPATCH_BASE_DECODER_ELEM(NAME, name) \ { \ OSSL_FUNC_DECODER_##NAME, (void (*)(void))p11prov_decoder_##name \ } -#define DISPATCH_DECODER_FN(type, structure, format, name) \ - DECL_DISPATCH_FUNC(DECODER, \ - p11prov_##type##_decoder_##structure##_##format, name) #define DISPATCH_DECODER_ELEM(NAME, type, structure, format, name) \ { \ OSSL_FUNC_DECODER_##NAME, \ (void (*)( \ void))p11prov_##type##_decoder_##structure##_##format##_##name \ } +#define DISPATCH_DECODER_FN_LIST(type, structure, format) \ + const OSSL_DISPATCH \ + p11prov_##type##_decoder_##structure##_##format##_functions[] = { \ + DISPATCH_BASE_DECODER_ELEM(NEWCTX, newctx), \ + DISPATCH_BASE_DECODER_ELEM(FREECTX, freectx), \ + DISPATCH_DECODER_ELEM(DECODE, type, structure, format, decode), \ + { 0, NULL } \ + }; +#define P11PROV_DER_COMMON_DECODE_FN(FORMAT_NAME, format) \ + static int p11prov_der_decoder_p11prov_##format##_decode( \ + void *inctx, OSSL_CORE_BIO *cin, int selection, \ + OSSL_CALLBACK *object_cb, void *object_cbarg, \ + OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) \ + { \ + return p11prov_der_decoder_p11prov_obj_decode( \ + FORMAT_NAME, inctx, cin, selection, object_cb, object_cbarg, \ + pw_cb, pw_cbarg); \ + } + +extern const OSSL_DISPATCH p11prov_pem_decoder_p11prov_der_functions[]; extern const OSSL_DISPATCH p11prov_der_decoder_p11prov_rsa_functions[]; extern const OSSL_DISPATCH p11prov_der_decoder_p11prov_ec_functions[]; -extern const OSSL_DISPATCH p11prov_pem_decoder_p11prov_der_functions[]; +extern const OSSL_DISPATCH p11prov_der_decoder_p11prov_ed25519_functions[]; +extern const OSSL_DISPATCH p11prov_der_decoder_p11prov_ed448_functions[]; #endif /* _DECODER_H */ diff --git a/src/encoder.c b/src/encoder.c index 389456f0..5e209cdf 100644 --- a/src/encoder.c +++ b/src/encoder.c @@ -38,6 +38,8 @@ static int p11prov_print_buf(BIO *out, const OSSL_PARAM *p, const char *str, DISPATCH_BASE_ENCODER_FN(newctx); DISPATCH_BASE_ENCODER_FN(freectx); +DISPATCH_ENCODER_FN(common, priv_key_info, pem, does_selection); + struct p11prov_encoder_ctx { P11PROV_CTX *provctx; }; @@ -552,15 +554,6 @@ static int p11prov_encoder_private_key_write_pem( return ret; } -static int p11prov_rsa_encoder_priv_key_info_pem_does_selection(void *inctx, - int selection) -{ - if (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) { - return RET_OSSL_OK; - } - return RET_OSSL_ERR; -} - static int p11prov_rsa_encoder_priv_key_info_pem_encode( void *inctx, OSSL_CORE_BIO *cbio, const void *inkey, const OSSL_PARAM key_abstract[], int selection, @@ -573,7 +566,7 @@ static int p11prov_rsa_encoder_priv_key_info_pem_encode( const OSSL_DISPATCH p11prov_rsa_encoder_priv_key_info_pem_functions[] = { DISPATCH_BASE_ENCODER_ELEM(NEWCTX, newctx), DISPATCH_BASE_ENCODER_ELEM(FREECTX, freectx), - DISPATCH_ENCODER_ELEM(DOES_SELECTION, rsa, priv_key_info, pem, + DISPATCH_ENCODER_ELEM(DOES_SELECTION, common, priv_key_info, pem, does_selection), DISPATCH_ENCODER_ELEM(ENCODE, rsa, priv_key_info, pem, encode), { 0, NULL }, @@ -919,15 +912,6 @@ const OSSL_DISPATCH p11prov_ec_encoder_text_functions[] = { { 0, NULL }, }; -static int p11prov_ec_encoder_priv_key_info_pem_does_selection(void *inctx, - int selection) -{ - if (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) { - return RET_OSSL_OK; - } - return RET_OSSL_ERR; -} - static int p11prov_ec_encoder_priv_key_info_pem_encode( void *inctx, OSSL_CORE_BIO *cbio, const void *inkey, const OSSL_PARAM key_abstract[], int selection, @@ -940,8 +924,36 @@ static int p11prov_ec_encoder_priv_key_info_pem_encode( const OSSL_DISPATCH p11prov_ec_encoder_priv_key_info_pem_functions[] = { DISPATCH_BASE_ENCODER_ELEM(NEWCTX, newctx), DISPATCH_BASE_ENCODER_ELEM(FREECTX, freectx), - DISPATCH_ENCODER_ELEM(DOES_SELECTION, ec, priv_key_info, pem, + DISPATCH_ENCODER_ELEM(DOES_SELECTION, common, priv_key_info, pem, does_selection), DISPATCH_ENCODER_ELEM(ENCODE, ec, priv_key_info, pem, encode), { 0, NULL }, }; + +static int p11prov_ec_edwards_encoder_priv_key_info_pem_encode( + void *inctx, OSSL_CORE_BIO *cbio, const void *inkey, + const OSSL_PARAM key_abstract[], int selection, + OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg) +{ + return p11prov_encoder_private_key_write_pem( + CKK_EC_EDWARDS, inctx, cbio, inkey, key_abstract, selection, cb, cbarg); +} + +const OSSL_DISPATCH p11prov_ec_edwards_encoder_priv_key_info_pem_functions[] = { + DISPATCH_BASE_ENCODER_ELEM(NEWCTX, newctx), + DISPATCH_BASE_ENCODER_ELEM(FREECTX, freectx), + DISPATCH_ENCODER_ELEM(DOES_SELECTION, common, priv_key_info, pem, + does_selection), + DISPATCH_ENCODER_ELEM(ENCODE, ec_edwards, priv_key_info, pem, encode), + { 0, NULL }, +}; + +static int +p11prov_common_encoder_priv_key_info_pem_does_selection(void *inctx, + int selection) +{ + if (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) { + return RET_OSSL_OK; + } + return RET_OSSL_ERR; +} diff --git a/src/encoder.h b/src/encoder.h index 02684441..c55f18b3 100644 --- a/src/encoder.h +++ b/src/encoder.h @@ -38,5 +38,7 @@ extern const OSSL_DISPATCH p11prov_ec_encoder_pkcs1_der_functions[]; extern const OSSL_DISPATCH p11prov_ec_encoder_pkcs1_pem_functions[]; extern const OSSL_DISPATCH p11prov_ec_encoder_spki_der_functions[]; extern const OSSL_DISPATCH p11prov_ec_encoder_priv_key_info_pem_functions[]; +extern const OSSL_DISPATCH + p11prov_ec_edwards_encoder_priv_key_info_pem_functions[]; #endif /* _ENCODER_H */ diff --git a/src/provider.c b/src/provider.c index 086f9b41..bf334e0f 100644 --- a/src/provider.c +++ b/src/provider.c @@ -1090,6 +1090,12 @@ static CK_RV operations_init(P11PROV_CTX *ctx) ADD_ALGO_EXT(EC, encoder, "provider=pkcs11,output=pem,structure=PrivateKeyInfo", p11prov_ec_encoder_priv_key_info_pem_functions); + ADD_ALGO_EXT(ED25519, encoder, + "provider=pkcs11,output=pem,structure=PrivateKeyInfo", + p11prov_ec_edwards_encoder_priv_key_info_pem_functions); + ADD_ALGO_EXT(ED448, encoder, + "provider=pkcs11,output=pem,structure=PrivateKeyInfo", + p11prov_ec_edwards_encoder_priv_key_info_pem_functions); } TERM_ALGO(encoder); @@ -1139,6 +1145,12 @@ static const OSSL_ALGORITHM p11prov_decoders[] = { { P11PROV_NAMES_EC, "provider=pkcs11,input=der,structure=" P11PROV_DER_STRUCTURE, p11prov_der_decoder_p11prov_ec_functions }, + { P11PROV_NAMES_ED25519, + "provider=pkcs11,input=der,structure=" P11PROV_DER_STRUCTURE, + p11prov_der_decoder_p11prov_ed25519_functions }, + { P11PROV_NAMES_ED448, + "provider=pkcs11,input=der,structure=" P11PROV_DER_STRUCTURE, + p11prov_der_decoder_p11prov_ed448_functions }, { NULL, NULL, NULL } }; diff --git a/tests/tpem_encoder b/tests/tpem_encoder index 988e113a..a06dd73c 100755 --- a/tests/tpem_encoder +++ b/tests/tpem_encoder @@ -4,6 +4,10 @@ source "${TESTSSRCDIR}/helpers.sh" +# Forward declaration to avoid shellcheck's SC2153 did you mean ... +: "${PRIURI:?}" "${ECPRIURI:?}" "${EDPRIURI:=}" +: "${PUBURI:?}" "${ECPUBURI:?}" "${EDPUBURI:=}" + # We need to configure early loading otherwise no digests are loaded, # and all checks are skipped sed -e "s/#pkcs11-module-encode-provider-uri-to-pem/pkcs11-module-encode-provider-uri-to-pem = true/" \ @@ -39,20 +43,34 @@ sign-verify() { PRIV_KEY=$1 PUB_KEY=$2 FILE=$3 + NO_DIGEST=$4 RANDOM_HEX=$(od -A n -N 15 -t x1 /dev/random) TMP_FILE="${TMPPDIR}/sign-verify-pem-encoder-${RANDOM_HEX// /}.bin" - $CHECKER openssl pkeyutl -sign -rawin -digest sha256 \ - -inkey "${PRIV_KEY}" \ - -in "${FILE}" \ - -out "${TMP_FILE}" - - $CHECKER openssl pkeyutl -verify -rawin -digest sha256 \ - -inkey "${PUB_KEY}" \ - -pubin \ - -in "${FILE}" \ - -sigfile "${TMP_FILE}" + if [[ -z "${NO_DIGEST}" ]]; then + $CHECKER openssl pkeyutl -sign -rawin -digest sha256 \ + -inkey "${PRIV_KEY}" \ + -in "${FILE}" \ + -out "${TMP_FILE}" + + $CHECKER openssl pkeyutl -verify -rawin -digest sha256 \ + -inkey "${PUB_KEY}" \ + -pubin \ + -in "${FILE}" \ + -sigfile "${TMP_FILE}" + else + $CHECKER openssl pkeyutl -sign -rawin \ + -inkey "${PRIV_KEY}" \ + -in "${FILE}" \ + -out "${TMP_FILE}" + + $CHECKER openssl pkeyutl -verify -rawin \ + -inkey "${PUB_KEY}" \ + -pubin \ + -in "${FILE}" \ + -sigfile "${TMP_FILE}" + fi; rm "${TMP_FILE}" } @@ -98,6 +116,28 @@ sign-verify "${TMPPDIR}/ec-pkey-uri.pem" \ "pkcs11:object=Test-PEM-Encode-EC-${LABEL_SUFFIX_URI}" \ "${TMPPDIR}/64krandom.bin" +# Only run ED test if setup created ed key +if [[ -n "${EDPRIURI}" ]]; then + title PARA "Test PEM Encoding ED support" + + make-uri-pem "${EDPRIURI}" "${TMPPDIR}/ed25519priuri-pkey.pem" + sign-verify "${TMPPDIR}/ed25519priuri-pkey.pem" "${EDPUBURI}" "${TMPPDIR}/64krandom.bin" "no-digest" + + export ALGORITHM=ED25519 + ossl ' + genpkey -propquery "provider=pkcs11" + -algorithm "${ALGORITHM}" + -pkeyopt "pkcs11_uri:pkcs11:object=Test-PEM-Encode-ED25519-${LABEL_SUFFIX_URI}" + -out "${TMPPDIR}/ed25519-pkey-uri.pem"' + + grep -e "-----BEGIN PKCS#11 PROVIDER URI-----" "${TMPPDIR}/ed25519-pkey-uri.pem" + + sign-verify "${TMPPDIR}/ed25519-pkey-uri.pem" \ + "pkcs11:object=Test-PEM-Encode-ED25519-${LABEL_SUFFIX_URI}" \ + "${TMPPDIR}/64krandom.bin" "no-digest" +else + title PARA "Skipping Test PEM Encoding ED support" +fi; title PARA "Test visible string has to match" make-uri-pem "${PRIURI}" "${TMPPDIR}/priuri-wrong-version-key.pem" "PKCS#11 Provider URI v2.0"