From 66966827740a04249300b0b25735e9d4c9bcab26 Mon Sep 17 00:00:00 2001 From: Richard Levitte Date: Wed, 24 Jul 2024 07:25:57 +0200 Subject: Add ED25519 and ED448 support for EVP_PKEY_{sign,verify}_init_ex2() In this mode, only the ph instances are supported, and must be set explicitly through a parameter. The caller is assumed to pass a prehash to EVP_PKEY_{sign,verify}(). Reviewed-by: Matt Caswell Reviewed-by: Tomas Mraz Reviewed-by: Viktor Dukhovni (Merged from https://github.com/openssl/openssl/pull/24975) --- crypto/err/openssl.txt | 2 + include/openssl/proverr.h | 1 + providers/common/provider_err.c | 2 + providers/implementations/signature/eddsa_sig.c | 81 ++++++++++++++++++++-- .../30-test_evp_data/evppkey_ecx_sigalg.txt | 51 ++++++++++++++ 5 files changed, 132 insertions(+), 5 deletions(-) diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 2aea0d2186..9b24e77a01 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -1072,6 +1072,8 @@ PROV_R_INVALID_DATA:115:invalid data PROV_R_INVALID_DIGEST:122:invalid digest PROV_R_INVALID_DIGEST_LENGTH:166:invalid digest length PROV_R_INVALID_DIGEST_SIZE:218:invalid digest size +PROV_R_INVALID_EDDSA_INSTANCE_FOR_ATTEMPTED_OPERATION:243:\ + invalid eddsa instance for attempted operation PROV_R_INVALID_INPUT_LENGTH:230:invalid input length PROV_R_INVALID_ITERATION_COUNT:123:invalid iteration count PROV_R_INVALID_IV_LENGTH:109:invalid iv length diff --git a/include/openssl/proverr.h b/include/openssl/proverr.h index 20e9c39c8f..c5ce438b06 100644 --- a/include/openssl/proverr.h +++ b/include/openssl/proverr.h @@ -64,6 +64,7 @@ # define PROV_R_INVALID_DIGEST 122 # define PROV_R_INVALID_DIGEST_LENGTH 166 # define PROV_R_INVALID_DIGEST_SIZE 218 +# define PROV_R_INVALID_EDDSA_INSTANCE_FOR_ATTEMPTED_OPERATION 243 # define PROV_R_INVALID_INPUT_LENGTH 230 # define PROV_R_INVALID_ITERATION_COUNT 123 # define PROV_R_INVALID_IV_LENGTH 109 diff --git a/providers/common/provider_err.c b/providers/common/provider_err.c index dc72e1ae72..8a4f7b1db0 100644 --- a/providers/common/provider_err.c +++ b/providers/common/provider_err.c @@ -87,6 +87,8 @@ static const ERR_STRING_DATA PROV_str_reasons[] = { "invalid digest length"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_DIGEST_SIZE), "invalid digest size"}, + {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_EDDSA_INSTANCE_FOR_ATTEMPTED_OPERATION), + "invalid eddsa instance for attempted operation"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_INPUT_LENGTH), "invalid input length"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_ITERATION_COUNT), diff --git a/providers/implementations/signature/eddsa_sig.c b/providers/implementations/signature/eddsa_sig.c index 0d64146acf..c3473a8927 100644 --- a/providers/implementations/signature/eddsa_sig.c +++ b/providers/implementations/signature/eddsa_sig.c @@ -312,6 +312,20 @@ static int ed25519ph_signverify_init(void *vpeddsactx, void *vedkey, && eddsa_set_ctx_params(vpeddsactx, params); } +/* + * This supports using ED25519 with EVP_PKEY_{sign,verify}_init_ex() and + * EVP_PKEY_{sign,verify}_init_ex2(), under the condition that the caller + * explicitly sets the Ed25519ph instance (this is verified by ed25519_sign() + * and ed25519_verify()) + */ +static int ed25519_signverify_init(void *vpeddsactx, void *vedkey, + const OSSL_PARAM params[]) +{ + return eddsa_signverify_init(vpeddsactx, vedkey) + && eddsa_setup_instance(vpeddsactx, ID_Ed25519, 0, 1) + && eddsa_set_ctx_params(vpeddsactx, params); +} + static int ed25519ctx_signverify_message_init(void *vpeddsactx, void *vedkey, const OSSL_PARAM params[]) { @@ -344,6 +358,20 @@ static int ed448ph_signverify_init(void *vpeddsactx, void *vedkey, && eddsa_set_ctx_params(vpeddsactx, params); } +/* + * This supports using ED448 with EVP_PKEY_{sign,verify}_init_ex() and + * EVP_PKEY_{sign,verify}_init_ex2(), under the condition that the caller + * explicitly sets the Ed448ph instance (this is verified by ed448_sign() + * and ed448_verify()) + */ +static int ed448_signverify_init(void *vpeddsactx, void *vedkey, + const OSSL_PARAM params[]) +{ + return eddsa_signverify_init(vpeddsactx, vedkey) + && eddsa_setup_instance(vpeddsactx, ID_Ed448, 0, 1) + && eddsa_set_ctx_params(vpeddsactx, params); +} + /* * This is used directly for OSSL_FUNC_SIGNATURE_SIGN and indirectly * for OSSL_FUNC_SIGNATURE_DIGEST_SIGN @@ -402,6 +430,11 @@ static int ed25519_sign(void *vpeddsactx, ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH); return 0; } + } else if (peddsactx->prehash_by_caller_flag) { + /* The caller is supposed to set up a ph instance! */ + ERR_raise(ERR_LIB_PROV, + PROV_R_INVALID_EDDSA_INSTANCE_FOR_ATTEMPTED_OPERATION); + return 0; } if (ossl_ed25519_sign(sigret, tbs, tbslen, edkey->pubkey, edkey->privkey, @@ -495,6 +528,11 @@ static int ed448_sign(void *vpeddsactx, ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH); return 0; } + } else if (peddsactx->prehash_by_caller_flag) { + /* The caller is supposed to set up a ph instance! */ + ERR_raise(ERR_LIB_PROV, + PROV_R_INVALID_EDDSA_INSTANCE_FOR_ATTEMPTED_OPERATION); + return 0; } if (ossl_ed448_sign(peddsactx->libctx, sigret, tbs, tbslen, @@ -549,6 +587,11 @@ static int ed25519_verify(void *vpeddsactx, ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH); return 0; } + } else if (peddsactx->prehash_by_caller_flag) { + /* The caller is supposed to set up a ph instance! */ + ERR_raise(ERR_LIB_PROV, + PROV_R_INVALID_EDDSA_INSTANCE_FOR_ATTEMPTED_OPERATION); + return 0; } return ossl_ed25519_verify(tbs, tbslen, sig, edkey->pubkey, @@ -593,6 +636,11 @@ static int ed448_verify(void *vpeddsactx, ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH); return 0; } + } else if (peddsactx->prehash_by_caller_flag) { + /* The caller is supposed to set up a ph instance! */ + ERR_raise(ERR_LIB_PROV, + PROV_R_INVALID_EDDSA_INSTANCE_FOR_ATTEMPTED_OPERATION); + return 0; } return ossl_ed448_verify(peddsactx->libctx, tbs, tbslen, sig, edkey->pubkey, @@ -777,16 +825,27 @@ static int eddsa_set_ctx_params(void *vpeddsactx, const OSSL_PARAM params[]) if (!OSSL_PARAM_get_utf8_string(p, &pinstance_name, sizeof(instance_name))) return 0; + /* + * When setting the new instance, we're careful not to change the + * prehash_by_caller flag, as that's always preset by the init + * functions. The sign functions will determine if the instance + * matches this flag. + */ if (OPENSSL_strcasecmp(pinstance_name, SN_Ed25519) == 0) { - eddsa_setup_instance(peddsactx, ID_Ed25519, 0, 0); + eddsa_setup_instance(peddsactx, ID_Ed25519, 0, + peddsactx->prehash_by_caller_flag); } else if (OPENSSL_strcasecmp(pinstance_name, SN_Ed25519ctx) == 0) { - eddsa_setup_instance(peddsactx, ID_Ed25519ctx, 0, 0); + eddsa_setup_instance(peddsactx, ID_Ed25519ctx, 0, + peddsactx->prehash_by_caller_flag); } else if (OPENSSL_strcasecmp(pinstance_name, SN_Ed25519ph) == 0) { - eddsa_setup_instance(peddsactx, ID_Ed25519ph, 0, 0); + eddsa_setup_instance(peddsactx, ID_Ed25519ph, 0, + peddsactx->prehash_by_caller_flag); } else if (OPENSSL_strcasecmp(pinstance_name, SN_Ed448) == 0) { - eddsa_setup_instance(peddsactx, ID_Ed448, 0, 0); + eddsa_setup_instance(peddsactx, ID_Ed448, 0, + peddsactx->prehash_by_caller_flag); } else if (OPENSSL_strcasecmp(pinstance_name, SN_Ed448ph) == 0) { - eddsa_setup_instance(peddsactx, ID_Ed448ph, 0, 0); + eddsa_setup_instance(peddsactx, ID_Ed448ph, 0, + peddsactx->prehash_by_caller_flag); } else { /* we did not recognize the instance */ return 0; @@ -833,6 +892,8 @@ eddsa_settable_variant_ctx_params(ossl_unused void *vpeddsactx, /* * Ed25519 can be used with: + * - EVP_PKEY_sign_init_ex2() [ instance and prehash assumed done by caller ] + * - EVP_PKEY_verify_init_ex2() [ instance and prehash assumed done by caller ] * - EVP_PKEY_sign_message_init() * - EVP_PKEY_verify_message_init() * - EVP_DigestSignInit_ex() @@ -846,6 +907,8 @@ eddsa_settable_variant_ctx_params(ossl_unused void *vpeddsactx, * - EVP_PKEY_sign_message_init() * - EVP_PKEY_verify_message_init() * Ed448 can be used with: + * - EVP_PKEY_sign_init_ex2() [ instance and prehash assumed done by caller ] + * - EVP_PKEY_verify_init_ex2() [ instance and prehash assumed done by caller ] * - EVP_PKEY_sign_message_init() * - EVP_PKEY_verify_message_init() * - EVP_DigestSignInit_ex() @@ -858,6 +921,10 @@ eddsa_settable_variant_ctx_params(ossl_unused void *vpeddsactx, */ #define ed25519_DISPATCH_END \ + { OSSL_FUNC_SIGNATURE_SIGN_INIT, \ + (void (*)(void))ed25519_signverify_init }, \ + { OSSL_FUNC_SIGNATURE_VERIFY_INIT, \ + (void (*)(void))ed25519_signverify_init }, \ { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT, \ (void (*)(void))ed25519_digest_signverify_init }, \ { OSSL_FUNC_SIGNATURE_DIGEST_SIGN, \ @@ -901,6 +968,10 @@ eddsa_settable_variant_ctx_params(ossl_unused void *vpeddsactx, #define ed25519ctx_DISPATCH_END eddsa_variant_DISPATCH_END(ed25519ctx) #define ed448_DISPATCH_END \ + { OSSL_FUNC_SIGNATURE_SIGN_INIT, \ + (void (*)(void))ed448_signverify_init }, \ + { OSSL_FUNC_SIGNATURE_VERIFY_INIT, \ + (void (*)(void))ed448_signverify_init }, \ { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT, \ (void (*)(void))ed448_digest_signverify_init }, \ { OSSL_FUNC_SIGNATURE_DIGEST_SIGN, \ diff --git a/test/recipes/30-test_evp_data/evppkey_ecx_sigalg.txt b/test/recipes/30-test_evp_data/evppkey_ecx_sigalg.txt index e3197db2de..cb3e6249ce 100644 --- a/test/recipes/30-test_evp_data/evppkey_ecx_sigalg.txt +++ b/test/recipes/30-test_evp_data/evppkey_ecx_sigalg.txt @@ -501,6 +501,23 @@ Input = ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a Ctrl = hexcontext-string: Output = 98a70222f0b8121aa9d30f813d683f809e462b469c7ff87639499bb94e6dae4131f85042463c2a355a2003d062adf5aaa10b8c61e636062aaad11c2a26083406 +# Same as the Sign above, but using the plain ED25519 with an instance set +# through controls +FIPSversion = >=3.4.0 +Sign = Ed25519:EDDSA-TV-10-Raw +Ctrl = instance:Ed25519ph +Input = ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f +Ctrl = hexcontext-string: +Output = 98a70222f0b8121aa9d30f813d683f809e462b469c7ff87639499bb94e6dae4131f85042463c2a355a2003d062adf5aaa10b8c61e636062aaad11c2a26083406 + +# Same as the Sign above, but forgetting to set an instance, should lead to +# an error +FIPSversion = >=3.4.0 +Sign = Ed25519:EDDSA-TV-10-Raw +Input = ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f +Ctrl = hexcontext-string: +Result = KEYOP_ERROR + # Test Vector 11 # Ed448 PrivateKeyRaw = EDDSA-TV-11-Raw:ED448:6c82a562cb808d10d632be89c8513ebf6c929f34ddfa8c9f63c9960ef6e348a3528c8a3fcc2f044e39a3fc5b94492f8f032e7549a20098f95b @@ -650,6 +667,23 @@ Input = 483366601360a8771c6863080cc4114d8db44530f8f1e1ee4f94ea37e78b5739d5a15bef Ctrl = hexcontext-string: Output = 822f6901f7480f3d5f562c592994d9693602875614483256505600bbc281ae381f54d6bce2ea911574932f52a4e6cadd78769375ec3ffd1b801a0d9b3f4030cd433964b6457ea39476511214f97469b57dd32dbc560a9a94d00bff07620464a3ad203df7dc7ce360c3cd3696d9d9fab90f00 +# Same as the Sign above, but using the plain ED25519 with an instance set +# through controls +FIPSversion = >=3.4.0 +Sign = Ed448:EDDSA-TV-20-Raw +Ctrl = instance:Ed448ph +Input = 483366601360a8771c6863080cc4114d8db44530f8f1e1ee4f94ea37e78b5739d5a15bef186a5386c75744c0527e1faa9f8726e462a12a4feb06bd8801e751e4 +Ctrl = hexcontext-string: +Output = 822f6901f7480f3d5f562c592994d9693602875614483256505600bbc281ae381f54d6bce2ea911574932f52a4e6cadd78769375ec3ffd1b801a0d9b3f4030cd433964b6457ea39476511214f97469b57dd32dbc560a9a94d00bff07620464a3ad203df7dc7ce360c3cd3696d9d9fab90f00 + +# Same as the Sign above, but forgetting to set an instance, should lead to +# an error +FIPSversion = >=3.4.0 +Sign = Ed448:EDDSA-TV-20-Raw +Input = 483366601360a8771c6863080cc4114d8db44530f8f1e1ee4f94ea37e78b5739d5a15bef186a5386c75744c0527e1faa9f8726e462a12a4feb06bd8801e751e4 +Ctrl = hexcontext-string: +Result = KEYOP_ERROR + # Test Vector 21 # Ed448ph PrivateKeyRaw = EDDSA-TV-21-Raw:ED448:833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42ef7822e0d5104127dc05d6dbefde69e3ab2cec7c867c6e2c49 @@ -672,3 +706,20 @@ Sign = Ed448ph:EDDSA-TV-21-Raw Input = 483366601360a8771c6863080cc4114d8db44530f8f1e1ee4f94ea37e78b5739d5a15bef186a5386c75744c0527e1faa9f8726e462a12a4feb06bd8801e751e4 Ctrl = hexcontext-string:666f6f Output = c32299d46ec8ff02b54540982814dce9a05812f81962b649d528095916a2aa481065b1580423ef927ecf0af5888f90da0f6a9a85ad5dc3f280d91224ba9911a3653d00e484e2ce232521481c8658df304bb7745a73514cdb9bf3e15784ab71284f8d0704a608c54a6b62d97beb511d132100 + +# Same as the Sign above, but using the plain ED25519 with an instance set +# through controls +FIPSversion = >=3.4.0 +Sign = Ed448:EDDSA-TV-21-Raw +Ctrl = instance:Ed448ph +Input = 483366601360a8771c6863080cc4114d8db44530f8f1e1ee4f94ea37e78b5739d5a15bef186a5386c75744c0527e1faa9f8726e462a12a4feb06bd8801e751e4 +Ctrl = hexcontext-string:666f6f +Output = c32299d46ec8ff02b54540982814dce9a05812f81962b649d528095916a2aa481065b1580423ef927ecf0af5888f90da0f6a9a85ad5dc3f280d91224ba9911a3653d00e484e2ce232521481c8658df304bb7745a73514cdb9bf3e15784ab71284f8d0704a608c54a6b62d97beb511d132100 + +# Same as the Sign above, but forgetting to set an instance, should lead to +# an error +FIPSversion = >=3.4.0 +Sign = Ed448:EDDSA-TV-21-Raw +Input = 483366601360a8771c6863080cc4114d8db44530f8f1e1ee4f94ea37e78b5739d5a15bef186a5386c75744c0527e1faa9f8726e462a12a4feb06bd8801e751e4 +Ctrl = hexcontext-string:666f6f +Result = KEYOP_ERROR -- cgit v1.2.3