From eea1e780a1c2c6952af7b9e00129f5aaefb7207e Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Thu, 5 Mar 2020 15:40:48 +0000 Subject: [PATCH] Add provider awareness of EVP_DigestSign() and EVP_DigestVerify() These "one-shot" functions are the only ones supported by Ed25519 and Ed448, so we need to ensure that libcrypto can handle provider based implementations of these functions. Reviewed-by: Shane Lontis (Merged from https://github.com/openssl/openssl/pull/11261) --- crypto/evp/m_sigver.c | 62 ++++++++++++++++++++++++++++++---- crypto/evp/signature.c | 32 ++++++++++++++---- include/openssl/core_numbers.h | 34 ++++++++++++------- 3 files changed, 103 insertions(+), 25 deletions(-) diff --git a/crypto/evp/m_sigver.c b/crypto/evp/m_sigver.c index b6c66722ec..225017b509 100644 --- a/crypto/evp/m_sigver.c +++ b/crypto/evp/m_sigver.c @@ -24,6 +24,18 @@ static int update(EVP_MD_CTX *ctx, const void *data, size_t datalen) return 0; } +/* + * If we get the "NULL" md then the name comes back as "UNDEF". We want to use + * NULL for this. + */ +static const char *canon_mdname(const char *mdname) +{ + if (mdname != NULL && strcmp(mdname, "UNDEF") == 0) + return NULL; + + return mdname; +} + static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, const EVP_MD *type, const char *mdname, const char *props, ENGINE *e, EVP_PKEY *pkey, @@ -134,12 +146,12 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, if (type != NULL) { ctx->reqdigest = type; if (mdname == NULL) - mdname = EVP_MD_name(type); + mdname = canon_mdname(EVP_MD_name(type)); } else { if (mdname == NULL && EVP_PKEY_get_default_digest_name(locpctx->pkey, locmdname, sizeof(locmdname))) - mdname = locmdname; + mdname = canon_mdname(locmdname); if (mdname != NULL) { /* @@ -280,6 +292,11 @@ int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize) || pctx->op.sig.signature == NULL) goto legacy; + if (pctx->op.sig.signature->digest_sign_update == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + return pctx->op.sig.signature->digest_sign_update(pctx->op.sig.sigprovctx, data, dsize); @@ -297,6 +314,11 @@ int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize) || pctx->op.sig.signature == NULL) goto legacy; + if (pctx->op.sig.signature->digest_verify_update == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + return pctx->op.sig.signature->digest_verify_update(pctx->op.sig.sigprovctx, data, dsize); @@ -391,8 +413,22 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen, const unsigned char *tbs, size_t tbslen) { - if (ctx->pctx->pmeth != NULL && ctx->pctx->pmeth->digestsign != NULL) - return ctx->pctx->pmeth->digestsign(ctx, sigret, siglen, tbs, tbslen); + EVP_PKEY_CTX *pctx = ctx->pctx; + + if (pctx != NULL + && pctx->operation == EVP_PKEY_OP_SIGNCTX + && pctx->op.sig.sigprovctx != NULL + && pctx->op.sig.signature != NULL) { + if (pctx->op.sig.signature->digest_sign != NULL) + return pctx->op.sig.signature->digest_sign(pctx->op.sig.sigprovctx, + sigret, siglen, SIZE_MAX, + tbs, tbslen); + } else { + /* legacy */ + if (ctx->pctx->pmeth != NULL && ctx->pctx->pmeth->digestsign != NULL) + return ctx->pctx->pmeth->digestsign(ctx, sigret, siglen, tbs, tbslen); + } + if (sigret != NULL && EVP_DigestSignUpdate(ctx, tbs, tbslen) <= 0) return 0; return EVP_DigestSignFinal(ctx, sigret, siglen); @@ -454,8 +490,22 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig, int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret, size_t siglen, const unsigned char *tbs, size_t tbslen) { - if (ctx->pctx->pmeth != NULL && ctx->pctx->pmeth->digestverify != NULL) - return ctx->pctx->pmeth->digestverify(ctx, sigret, siglen, tbs, tbslen); + EVP_PKEY_CTX *pctx = ctx->pctx; + + if (pctx != NULL + && pctx->operation == EVP_PKEY_OP_VERIFYCTX + && pctx->op.sig.sigprovctx != NULL + && pctx->op.sig.signature != NULL) { + if (pctx->op.sig.signature->digest_verify != NULL) + return pctx->op.sig.signature->digest_verify(pctx->op.sig.sigprovctx, + sigret, siglen, + tbs, tbslen); + } else { + /* legacy */ + if (ctx->pctx->pmeth != NULL && ctx->pctx->pmeth->digestverify != NULL) + return ctx->pctx->pmeth->digestverify(ctx, sigret, siglen, tbs, tbslen); + } + if (EVP_DigestVerifyUpdate(ctx, tbs, tbslen) <= 0) return -1; return EVP_DigestVerifyFinal(ctx, sigret, siglen); diff --git a/crypto/evp/signature.c b/crypto/evp/signature.c index 3dfd4041e7..c01f076609 100644 --- a/crypto/evp/signature.c +++ b/crypto/evp/signature.c @@ -105,7 +105,6 @@ static void *evp_signature_from_dispatch(int name_id, break; signature->digest_sign_init = OSSL_get_OP_signature_digest_sign_init(fns); - digsignfncnt++; break; case OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE: if (signature->digest_sign_update != NULL) @@ -121,12 +120,17 @@ static void *evp_signature_from_dispatch(int name_id, = OSSL_get_OP_signature_digest_sign_final(fns); digsignfncnt++; break; + case OSSL_FUNC_SIGNATURE_DIGEST_SIGN: + if (signature->digest_sign != NULL) + break; + signature->digest_sign + = OSSL_get_OP_signature_digest_sign(fns); + break; case OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT: if (signature->digest_verify_init != NULL) break; signature->digest_verify_init = OSSL_get_OP_signature_digest_verify_init(fns); - digverifyfncnt++; break; case OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE: if (signature->digest_verify_update != NULL) @@ -142,6 +146,12 @@ static void *evp_signature_from_dispatch(int name_id, = OSSL_get_OP_signature_digest_verify_final(fns); digverifyfncnt++; break; + case OSSL_FUNC_SIGNATURE_DIGEST_VERIFY: + if (signature->digest_verify != NULL) + break; + signature->digest_verify + = OSSL_get_OP_signature_digest_verify(fns); + break; case OSSL_FUNC_SIGNATURE_FREECTX: if (signature->freectx != NULL) break; @@ -216,12 +226,20 @@ static void *evp_signature_from_dispatch(int name_id, && verifyfncnt == 0 && verifyrecfncnt == 0 && digsignfncnt == 0 - && digverifyfncnt == 0) + && digverifyfncnt == 0 + && signature->digest_sign == NULL + && signature->digest_verify == NULL) || (signfncnt != 0 && signfncnt != 2) || (verifyfncnt != 0 && verifyfncnt != 2) || (verifyrecfncnt != 0 && verifyrecfncnt != 2) - || (digsignfncnt != 0 && digsignfncnt != 3) - || (digverifyfncnt != 0 && digverifyfncnt != 3) + || (digsignfncnt != 0 && digsignfncnt != 2) + || (digsignfncnt == 2 && signature->digest_sign_init == NULL) + || (digverifyfncnt != 0 && digverifyfncnt != 2) + || (digverifyfncnt == 2 && signature->digest_verify_init == NULL) + || (signature->digest_sign != NULL + && signature->digest_sign_init == NULL) + || (signature->digest_verify != NULL + && signature->digest_verify_init == NULL) || (gparamfncnt != 0 && gparamfncnt != 2) || (sparamfncnt != 0 && sparamfncnt != 2) || (gmdparamfncnt != 0 && gmdparamfncnt != 2) @@ -234,7 +252,9 @@ static void *evp_signature_from_dispatch(int name_id, * (verify_init verify) or * (verify_recover_init, verify_recover) or * (digest_sign_init, digest_sign_update, digest_sign_final) or - * (digest_verify_init, digest_verify_update, digest_verify_final). + * (digest_verify_init, digest_verify_update, digest_verify_final) or + * (digest_sign_init, digest_sign) or + * (digest_verify_init, digest_verify). * * set_ctx_params and settable_ctx_params are optional, but if one of * them is present then the other one must also be present. The same diff --git a/include/openssl/core_numbers.h b/include/openssl/core_numbers.h index 3314a0f665..c65041894a 100644 --- a/include/openssl/core_numbers.h +++ b/include/openssl/core_numbers.h @@ -480,19 +480,21 @@ OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, OP_keyexch_gettable_ctx_params, # define OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT 8 # define OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE 9 # define OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL 10 -# define OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT 11 -# define OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE 12 -# define OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL 13 -# define OSSL_FUNC_SIGNATURE_FREECTX 14 -# define OSSL_FUNC_SIGNATURE_DUPCTX 15 -# define OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS 16 -# define OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS 17 -# define OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS 18 -# define OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS 19 -# define OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS 20 -# define OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS 21 -# define OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS 22 -# define OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS 23 +# define OSSL_FUNC_SIGNATURE_DIGEST_SIGN 11 +# define OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT 12 +# define OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE 13 +# define OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL 14 +# define OSSL_FUNC_SIGNATURE_DIGEST_VERIFY 15 +# define OSSL_FUNC_SIGNATURE_FREECTX 16 +# define OSSL_FUNC_SIGNATURE_DUPCTX 17 +# define OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS 18 +# define OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS 19 +# define OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS 20 +# define OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS 21 +# define OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS 22 +# define OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS 23 +# define OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS 24 +# define OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS 25 OSSL_CORE_MAKE_FUNC(void *, OP_signature_newctx, (void *provctx)) OSSL_CORE_MAKE_FUNC(int, OP_signature_sign_init, (void *ctx, void *provkey)) @@ -522,6 +524,9 @@ OSSL_CORE_MAKE_FUNC(int, OP_signature_digest_sign_update, OSSL_CORE_MAKE_FUNC(int, OP_signature_digest_sign_final, (void *ctx, unsigned char *sig, size_t *siglen, size_t sigsize)) +OSSL_CORE_MAKE_FUNC(int, OP_signature_digest_sign, + (void *ctx, unsigned char *sigret, size_t *siglen, + size_t sigsize, const unsigned char *tbs, size_t tbslen)) OSSL_CORE_MAKE_FUNC(int, OP_signature_digest_verify_init, (void *ctx, const char *mdname, const char *props, void *provkey)) @@ -529,6 +534,9 @@ OSSL_CORE_MAKE_FUNC(int, OP_signature_digest_verify_update, (void *ctx, const unsigned char *data, size_t datalen)) OSSL_CORE_MAKE_FUNC(int, OP_signature_digest_verify_final, (void *ctx, const unsigned char *sig, size_t siglen)) +OSSL_CORE_MAKE_FUNC(int, OP_signature_digest_verify, + (void *ctx, const unsigned char *sig, size_t siglen, + const unsigned char *tbs, size_t tbslen)) OSSL_CORE_MAKE_FUNC(void, OP_signature_freectx, (void *ctx)) OSSL_CORE_MAKE_FUNC(void *, OP_signature_dupctx, (void *ctx)) OSSL_CORE_MAKE_FUNC(int, OP_signature_get_ctx_params, -- 2.34.1