From ba01accd593697e56938907a1bf0cd5d8e25674f Mon Sep 17 00:00:00 2001 From: Maxwell Moyer-McKee Date: Tue, 14 Apr 2026 23:05:57 +0000 Subject: [PATCH 01/12] Add composite functions --- SymCryptProvider/src/p_scossl_base.c | 44 +++++++++++++++++++++++++-- SymCryptProvider/src/p_scossl_names.h | 24 +++++++++++++++ 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/SymCryptProvider/src/p_scossl_base.c b/SymCryptProvider/src/p_scossl_base.c index e092410a..ca5efef9 100644 --- a/SymCryptProvider/src/p_scossl_base.c +++ b/SymCryptProvider/src/p_scossl_base.c @@ -465,12 +465,52 @@ static const OSSL_ALGORITHM p_scossl_keyexch[] = { ALG_TABLE_END}; // Signature -extern const OSSL_DISPATCH p_scossl_ecdsa_signature_functions[]; extern const OSSL_DISPATCH p_scossl_rsa_signature_functions[]; +extern const OSSL_DISPATCH p_scossl_rsa_sha1_signature_functions[]; +extern const OSSL_DISPATCH p_scossl_rsa_sha224_signature_functions[]; +extern const OSSL_DISPATCH p_scossl_rsa_sha256_signature_functions[]; +extern const OSSL_DISPATCH p_scossl_rsa_sha384_signature_functions[]; +extern const OSSL_DISPATCH p_scossl_rsa_sha512_signature_functions[]; +extern const OSSL_DISPATCH p_scossl_rsa_sha512_224_signature_functions[]; +extern const OSSL_DISPATCH p_scossl_rsa_sha512_256_signature_functions[]; +extern const OSSL_DISPATCH p_scossl_rsa_sha3_224_signature_functions[]; +extern const OSSL_DISPATCH p_scossl_rsa_sha3_256_signature_functions[]; +extern const OSSL_DISPATCH p_scossl_rsa_sha3_384_signature_functions[]; +extern const OSSL_DISPATCH p_scossl_rsa_sha3_512_signature_functions[]; +extern const OSSL_DISPATCH p_scossl_ecdsa_signature_functions[]; +extern const OSSL_DISPATCH p_scossl_ecdsa_sha1_signature_functions[]; +extern const OSSL_DISPATCH p_scossl_ecdsa_sha224_signature_functions[]; +extern const OSSL_DISPATCH p_scossl_ecdsa_sha256_signature_functions[]; +extern const OSSL_DISPATCH p_scossl_ecdsa_sha384_signature_functions[]; +extern const OSSL_DISPATCH p_scossl_ecdsa_sha512_signature_functions[]; +extern const OSSL_DISPATCH p_scossl_ecdsa_sha3_224_signature_functions[]; +extern const OSSL_DISPATCH p_scossl_ecdsa_sha3_256_signature_functions[]; +extern const OSSL_DISPATCH p_scossl_ecdsa_sha3_384_signature_functions[]; +extern const OSSL_DISPATCH p_scossl_ecdsa_sha3_512_signature_functions[]; static const OSSL_ALGORITHM p_scossl_signature[] = { - ALG(SCOSSL_ALG_NAME_ECDSA, p_scossl_ecdsa_signature_functions), ALG(SCOSSL_ALG_NAME_RSA, p_scossl_rsa_signature_functions), + ALG(SCOSSL_ALG_NAME_RSA_SHA1, p_scossl_rsa_sha1_signature_functions), + ALG(SCOSSL_ALG_NAME_RSA_SHA256, p_scossl_rsa_sha256_signature_functions), + ALG(SCOSSL_ALG_NAME_RSA_SHA384, p_scossl_rsa_sha384_signature_functions), + ALG(SCOSSL_ALG_NAME_RSA_SHA512, p_scossl_rsa_sha512_signature_functions), + ALG(SCOSSL_ALG_NAME_RSA_SHA224, p_scossl_rsa_sha224_signature_functions), + ALG(SCOSSL_ALG_NAME_RSA_SHA512_224, p_scossl_rsa_sha512_224_signature_functions), + ALG(SCOSSL_ALG_NAME_RSA_SHA512_256, p_scossl_rsa_sha512_256_signature_functions), + ALG(SCOSSL_ALG_NAME_RSA_SHA3_224, p_scossl_rsa_sha3_224_signature_functions), + ALG(SCOSSL_ALG_NAME_RSA_SHA3_256, p_scossl_rsa_sha3_256_signature_functions), + ALG(SCOSSL_ALG_NAME_RSA_SHA3_384, p_scossl_rsa_sha3_384_signature_functions), + ALG(SCOSSL_ALG_NAME_RSA_SHA3_512, p_scossl_rsa_sha3_512_signature_functions), + ALG(SCOSSL_ALG_NAME_ECDSA, p_scossl_ecdsa_signature_functions), + ALG(SCOSSL_ALG_NAME_ECDSA_SHA1, p_scossl_ecdsa_sha1_signature_functions), + ALG(SCOSSL_ALG_NAME_ECDSA_SHA224, p_scossl_ecdsa_sha224_signature_functions), + ALG(SCOSSL_ALG_NAME_ECDSA_SHA256, p_scossl_ecdsa_sha256_signature_functions), + ALG(SCOSSL_ALG_NAME_ECDSA_SHA384, p_scossl_ecdsa_sha384_signature_functions), + ALG(SCOSSL_ALG_NAME_ECDSA_SHA512, p_scossl_ecdsa_sha512_signature_functions), + ALG(SCOSSL_ALG_NAME_ECDSA_SHA3_224, p_scossl_ecdsa_sha3_224_signature_functions), + ALG(SCOSSL_ALG_NAME_ECDSA_SHA3_256, p_scossl_ecdsa_sha3_256_signature_functions), + ALG(SCOSSL_ALG_NAME_ECDSA_SHA3_384, p_scossl_ecdsa_sha3_384_signature_functions), + ALG(SCOSSL_ALG_NAME_ECDSA_SHA3_512, p_scossl_ecdsa_sha3_512_signature_functions), ALG_TABLE_END}; // Asymmetric Cipher diff --git a/SymCryptProvider/src/p_scossl_names.h b/SymCryptProvider/src/p_scossl_names.h index 33ce0e94..43aa51fc 100644 --- a/SymCryptProvider/src/p_scossl_names.h +++ b/SymCryptProvider/src/p_scossl_names.h @@ -85,6 +85,30 @@ extern "C" { #define SCOSSL_ALG_NAME_RSA SN_rsa":"LN_rsaEncryption":1.2.840.113549.1.1.1" #define SCOSSL_ALG_NAME_ECDSA "ECDSA" +// Composite RSA signature algorithms (sigalgs) +#define SCOSSL_ALG_NAME_RSA_SHA1 "RSA-SHA1:RSA-SHA-1:sha1WithRSAEncryption:1.2.840.113549.1.1.5" +#define SCOSSL_ALG_NAME_RSA_SHA256 "RSA-SHA2-256:RSA-SHA256:sha256WithRSAEncryption:1.2.840.113549.1.1.11" +#define SCOSSL_ALG_NAME_RSA_SHA384 "RSA-SHA2-384:RSA-SHA384:sha384WithRSAEncryption:1.2.840.113549.1.1.12" +#define SCOSSL_ALG_NAME_RSA_SHA512 "RSA-SHA2-512:RSA-SHA512:sha512WithRSAEncryption:1.2.840.113549.1.1.13" +#define SCOSSL_ALG_NAME_RSA_SHA224 "RSA-SHA2-224:RSA-SHA224:sha224WithRSAEncryption:1.2.840.113549.1.1.14" +#define SCOSSL_ALG_NAME_RSA_SHA512_224 "RSA-SHA2-512/224:RSA-SHA512-224:sha512-224WithRSAEncryption:1.2.840.113549.1.1.15" +#define SCOSSL_ALG_NAME_RSA_SHA512_256 "RSA-SHA2-512/256:RSA-SHA512-256:sha512-256WithRSAEncryption:1.2.840.113549.1.1.16" +#define SCOSSL_ALG_NAME_RSA_SHA3_224 "RSA-SHA3-224:id-rsassa-pkcs1-v1_5-with-sha3-224:2.16.840.1.101.3.4.3.13" +#define SCOSSL_ALG_NAME_RSA_SHA3_256 "RSA-SHA3-256:id-rsassa-pkcs1-v1_5-with-sha3-256:2.16.840.1.101.3.4.3.14" +#define SCOSSL_ALG_NAME_RSA_SHA3_384 "RSA-SHA3-384:id-rsassa-pkcs1-v1_5-with-sha3-384:2.16.840.1.101.3.4.3.15" +#define SCOSSL_ALG_NAME_RSA_SHA3_512 "RSA-SHA3-512:id-rsassa-pkcs1-v1_5-with-sha3-512:2.16.840.1.101.3.4.3.16" + +// Composite ECDSA signature algorithms (sigalgs) +#define SCOSSL_ALG_NAME_ECDSA_SHA1 "ECDSA-SHA1:ECDSA-SHA-1:ecdsa-with-SHA1:1.2.840.10045.4.1" +#define SCOSSL_ALG_NAME_ECDSA_SHA224 "ECDSA-SHA2-224:ECDSA-SHA224:ecdsa-with-SHA224:1.2.840.10045.4.3.1" +#define SCOSSL_ALG_NAME_ECDSA_SHA256 "ECDSA-SHA2-256:ECDSA-SHA256:ecdsa-with-SHA256:1.2.840.10045.4.3.2" +#define SCOSSL_ALG_NAME_ECDSA_SHA384 "ECDSA-SHA2-384:ECDSA-SHA384:ecdsa-with-SHA384:1.2.840.10045.4.3.3" +#define SCOSSL_ALG_NAME_ECDSA_SHA512 "ECDSA-SHA2-512:ECDSA-SHA512:ecdsa-with-SHA512:1.2.840.10045.4.3.4" +#define SCOSSL_ALG_NAME_ECDSA_SHA3_224 "ECDSA-SHA3-224:ecdsa_with_SHA3-224:id-ecdsa-with-sha3-224:2.16.840.1.101.3.4.3.9" +#define SCOSSL_ALG_NAME_ECDSA_SHA3_256 "ECDSA-SHA3-256:ecdsa_with_SHA3-256:id-ecdsa-with-sha3-256:2.16.840.1.101.3.4.3.10" +#define SCOSSL_ALG_NAME_ECDSA_SHA3_384 "ECDSA-SHA3-384:ecdsa_with_SHA3-384:id-ecdsa-with-sha3-384:2.16.840.1.101.3.4.3.11" +#define SCOSSL_ALG_NAME_ECDSA_SHA3_512 "ECDSA-SHA3-512:ecdsa_with_SHA3-512:id-ecdsa-with-sha3-512:2.16.840.1.101.3.4.3.12" + // Key encapsulation #define SCOSSL_ALG_NAME_MLKEM512 SCOSSL_LN_MLKEM512":MLKEM512:"SCOSSL_SN_MLKEM512":"SCOSSL_OID_MLKEM512 #define SCOSSL_ALG_NAME_MLKEM768 SCOSSL_LN_MLKEM768":MLKEM768:"SCOSSL_SN_MLKEM768":"SCOSSL_OID_MLKEM768 From afa2499fcd5b983748b7a30dfa190e710c719e7f Mon Sep 17 00:00:00 2001 From: Maxwell Moyer-McKee Date: Mon, 20 Apr 2026 19:03:20 +0000 Subject: [PATCH 02/12] Add RSA sigalg interface --- .../src/signature/p_scossl_rsa_signature.c | 296 ++++++++++++++++-- 1 file changed, 277 insertions(+), 19 deletions(-) diff --git a/SymCryptProvider/src/signature/p_scossl_rsa_signature.c b/SymCryptProvider/src/signature/p_scossl_rsa_signature.c index 43d0783f..bed45b03 100644 --- a/SymCryptProvider/src/signature/p_scossl_rsa_signature.c +++ b/SymCryptProvider/src/signature/p_scossl_rsa_signature.c @@ -35,6 +35,16 @@ typedef struct const OSSL_ITEM *mgf1MdInfo; // Informational, must match md if set int cbSalt; int cbSaltMin; + + // Sigalg state tracking + BOOL isSigalg; + BOOL allowUpdate; + BOOL allowFinal; + BOOL allowOneshot; + + // Sigalg verify message support + PBYTE pbSignature; + SIZE_T cbSignature; } SCOSSL_RSA_SIGN_CTX; #define SCOSSL_RSA_SIGNATURE_GETTABLE_PARAMS \ @@ -60,6 +70,10 @@ static const OSSL_PARAM p_scossl_rsa_pss_sig_ctx_gettable_param_types[] = { SCOSSL_RSA_PSS_SIGNATURE_GETTABLE_PARAMS OSSL_PARAM_END}; +static const OSSL_PARAM p_scossl_rsa_sigalg_ctx_settable_param_types[] = { + OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_SIGNATURE, NULL, 0), + OSSL_PARAM_END}; + // Padding may not be set at the time of querying settable params, so PSS params // are always accepted. The provider will check the padding before attempting // to set the PSS parameters @@ -112,6 +126,7 @@ static void p_scossl_rsa_freectx(SCOSSL_RSA_SIGN_CTX *ctx) EVP_MD_CTX_free(ctx->mdctx); EVP_MD_free(ctx->md); OPENSSL_free(ctx->propq); + OPENSSL_free(ctx->pbSignature); OPENSSL_free(ctx); } @@ -152,12 +167,12 @@ static SCOSSL_STATUS p_scossl_rsa_signverify_init(_Inout_ SCOSSL_RSA_SIGN_CTX *c return SCOSSL_FAILURE; } -#ifdef RSA_PSS_SALTLEN_AUTO_DIGEST_MAX ctx->cbSalt = RSA_PSS_SALTLEN_AUTO_DIGEST_MAX; -#else - ctx->cbSalt = RSA_PSS_SALTLEN_AUTO; -#endif ctx->operation = operation; + ctx->allowUpdate = TRUE; + ctx->allowFinal = TRUE; + ctx->allowOneshot = TRUE; + if (keyCtx != NULL) { if (!keyCtx->initialized) @@ -402,7 +417,7 @@ static SCOSSL_STATUS p_scossl_rsa_digest_sign_final(_In_ SCOSSL_RSA_SIGN_CTX *ct } // If sig is NULL, this is a size fetch, and the digest does not need to be computed - if (sig == NULL || EVP_DigestFinal(ctx->mdctx, digest, &cbDigest)) + if (sig == NULL || EVP_DigestFinal_ex(ctx->mdctx, digest, &cbDigest)) { ctx->allowMdUpdates = sig != NULL; ret = p_scossl_rsa_sign(ctx, sig, siglen, sigsize, digest, cbDigest); @@ -424,14 +439,19 @@ static SCOSSL_STATUS p_scossl_rsa_digest_verify_final(_In_ SCOSSL_RSA_SIGN_CTX * ctx->allowMdUpdates = TRUE; - return EVP_DigestFinal(ctx->mdctx, digest, &cbDigest) && + return EVP_DigestFinal_ex(ctx->mdctx, digest, &cbDigest) && p_scossl_rsa_verify(ctx, sig, siglen, digest, cbDigest); } static const OSSL_PARAM *p_scossl_rsa_settable_ctx_params(_In_ SCOSSL_RSA_SIGN_CTX *ctx, ossl_unused void *provctx) { - return ctx->allowMdUpdates ? p_scossl_rsa_sig_ctx_settable_param_types : p_scossl_rsa_sig_ctx_settable_param_types_no_digest; + if (ctx != NULL && !ctx->allowMdUpdates) + { + return p_scossl_rsa_sig_ctx_settable_param_types_no_digest; + } + + return p_scossl_rsa_sig_ctx_settable_param_types; } static SCOSSL_STATUS p_scossl_rsa_set_ctx_params(_Inout_ SCOSSL_RSA_SIGN_CTX *ctx, _In_ const OSSL_PARAM params[]) @@ -581,14 +601,12 @@ static SCOSSL_STATUS p_scossl_rsa_set_ctx_params(_Inout_ SCOSSL_RSA_SIGN_CTX *ct { cbSalt = RSA_PSS_SALTLEN_MAX; } -#ifdef RSA_PSS_SALTLEN_AUTO_DIGEST_MAX else if (strcmp(p->data, OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO_DIGEST_MAX) == 0) { // Sign: Smaller of digest length or maximized salt length // Verify: Autorecovered salt length cbSalt = RSA_PSS_SALTLEN_AUTO_DIGEST_MAX; } -#endif else { cbSalt = atoi(p->data); @@ -598,11 +616,7 @@ static SCOSSL_STATUS p_scossl_rsa_set_ctx_params(_Inout_ SCOSSL_RSA_SIGN_CTX *ct ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); return SCOSSL_FAILURE; } -#ifdef RSA_PSS_SALTLEN_AUTO_DIGEST_MAX if (cbSalt < RSA_PSS_SALTLEN_AUTO_DIGEST_MAX) -#else - if (cbSalt < RSA_PSS_SALTLEN_MAX) -#endif { ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH); return SCOSSL_FAILURE; @@ -613,9 +627,7 @@ static SCOSSL_STATUS p_scossl_rsa_set_ctx_params(_Inout_ SCOSSL_RSA_SIGN_CTX *ct switch (cbSalt) { case RSA_PSS_SALTLEN_AUTO: -#ifdef RSA_PSS_SALTLEN_AUTO_DIGEST_MAX case RSA_PSS_SALTLEN_AUTO_DIGEST_MAX: -#endif if (ctx->operation == EVP_PKEY_OP_VERIFY) { ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH); @@ -699,6 +711,40 @@ static SCOSSL_STATUS p_scossl_rsa_set_ctx_params(_Inout_ SCOSSL_RSA_SIGN_CTX *ct return SCOSSL_SUCCESS; } +static const OSSL_PARAM *p_scossl_rsa_sigalg_settable_ctx_params(_In_ SCOSSL_RSA_SIGN_CTX *ctx, ossl_unused void *provctx) +{ + if (ctx != NULL && ctx->operation != EVP_PKEY_OP_VERIFYMSG) + { + return p_scossl_rsa_sigalg_ctx_settable_param_types; + } + + return NULL; +} + +static SCOSSL_STATUS p_scossl_rsa_sigalg_set_ctx_params(_Inout_ SCOSSL_RSA_SIGN_CTX *ctx, _In_ const OSSL_PARAM params[]) +{ + const OSSL_PARAM *p; + + if (ctx == NULL) + return SCOSSL_FAILURE; + + if (ctx->operation == EVP_PKEY_OP_VERIFYMSG) + { + if ((p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_SIGNATURE)) != NULL) + { + OPENSSL_free(ctx->pbSignature); + ctx->pbSignature = NULL; + ctx->cbSignature = 0; + if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->pbSignature, 0, &ctx->cbSignature)) + { + return SCOSSL_FAILURE; + } + } + } + + return SCOSSL_SUCCESS; +} + static const OSSL_PARAM *p_scossl_rsa_gettable_ctx_params(_In_ SCOSSL_RSA_SIGN_CTX *ctx, ossl_unused void *provctx) { @@ -768,11 +814,9 @@ static ASN1_STRING *p_scossl_rsa_pss_params_to_asn1_sequence(_In_ SCOSSL_RSA_SIG case RSA_PSS_SALTLEN_AUTO: cbSalt = cbSaltMax; break; -#ifdef RSA_PSS_SALTLEN_AUTO_DIGEST_MAX case RSA_PSS_SALTLEN_AUTO_DIGEST_MAX: cbSalt = cbSaltMax < (int)cbHash ? cbSaltMax : (int)cbHash; break; -#endif } if (cbSalt < 0) @@ -981,11 +1025,9 @@ static SCOSSL_STATUS p_scossl_rsa_get_ctx_params(_In_ SCOSSL_RSA_SIGN_CTX *ctx, case RSA_PSS_SALTLEN_MAX: saltLenText = OSSL_PKEY_RSA_PSS_SALT_LEN_MAX; break; -#ifdef RSA_PSS_SALTLEN_AUTO_DIGEST_MAX case RSA_PSS_SALTLEN_AUTO_DIGEST_MAX: saltLenText = OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO_DIGEST_MAX; break; -#endif default: len = BIO_snprintf(p->data, p->data_size, "%d", ctx->cbSalt); @@ -1088,6 +1130,222 @@ const OSSL_DISPATCH p_scossl_rsa_signature_functions[] = { {OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS, (void (*)(void))p_scossl_rsa_settable_ctx_md_params}, {0, NULL}}; +static SCOSSL_STATUS p_scossl_rsa_sigalg_signverify_init(_Inout_ SCOSSL_RSA_SIGN_CTX *ctx, _In_ SCOSSL_PROV_RSA_KEY_CTX *keyCtx, + _In_ const OSSL_PARAM params[], int operation, + _In_ const char *mdname) +{ + EVP_MD *md = NULL; + + if (!p_scossl_rsa_signverify_init(ctx, keyCtx, params, operation)) + { + return SCOSSL_FAILURE; + } + + // Sigalgs are not supported for PSS keys + if (ctx->padding == RSA_PKCS1_PSS_PADDING) + { + ERR_raise(ERR_LIB_PROV, PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return SCOSSL_FAILURE; + } + + const OSSL_ITEM *mdInfo = p_scossl_rsa_get_supported_md(ctx->libctx, RSA_PKCS1_PADDING, mdname, NULL, &md); + if (mdInfo == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST); + return SCOSSL_FAILURE; + } + + EVP_MD_free(ctx->md); + ctx->md = md; + ctx->mdInfo = mdInfo; + ctx->padding = RSA_PKCS1_PADDING; + ctx->allowMdUpdates = FALSE; + ctx->isSigalg = TRUE; + + return SCOSSL_SUCCESS; +} + +static SCOSSL_STATUS p_scossl_rsa_sigalg_message_signverify_init(_Inout_ SCOSSL_RSA_SIGN_CTX *ctx, _In_ SCOSSL_PROV_RSA_KEY_CTX *keyCtx, + _In_ const OSSL_PARAM params[], int operation, + _In_ const char *mdname) +{ + if (!p_scossl_rsa_sigalg_signverify_init(ctx, keyCtx, params, operation, mdname)) + { + return SCOSSL_FAILURE; + } + + if (ctx->mdctx == NULL) + { + if ((ctx->mdctx = EVP_MD_CTX_new()) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return SCOSSL_FAILURE; + } + } + + if (!EVP_DigestInit_ex2(ctx->mdctx, ctx->md, params)) + { + EVP_MD_CTX_free(ctx->mdctx); + ctx->mdctx = NULL; + return SCOSSL_FAILURE; + } + + return SCOSSL_SUCCESS; +} + +static SCOSSL_STATUS p_scossl_rsa_sigalg_signverify_message_update(_In_ SCOSSL_RSA_SIGN_CTX *ctx, + _In_reads_bytes_(datalen) const unsigned char *data, + size_t datalen) +{ + if (ctx == NULL || ctx->mdctx == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); + return SCOSSL_FAILURE; + } + + if (!ctx->allowUpdate) + { + ERR_raise(ERR_LIB_PROV, PROV_R_UPDATE_CALL_OUT_OF_ORDER); + return SCOSSL_FAILURE; + } + + ctx->allowOneshot = 0; + + return EVP_DigestUpdate(ctx->mdctx, data, datalen); +} + +static SCOSSL_STATUS p_scossl_rsa_sigalg_sign_message_final(_In_ SCOSSL_RSA_SIGN_CTX *ctx, + _Out_writes_bytes_opt_(*siglen) unsigned char *sig, + _Out_ size_t *siglen, size_t sigsize) +{ + BYTE abDigest[EVP_MAX_MD_SIZE]; + unsigned int cbDigest = 0; + + if (ctx == NULL || ctx->mdctx == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); + return SCOSSL_FAILURE; + } + + if (!ctx->allowFinal) + { + ERR_raise(ERR_LIB_PROV, PROV_R_FINAL_CALL_OUT_OF_ORDER); + return SCOSSL_FAILURE; + } + + // If sig is NULL, this is a size fetch, and the digest does not need to be computed + if (sig != NULL) + { + if (!EVP_DigestFinal_ex(ctx->mdctx, abDigest, &cbDigest)) + { + return SCOSSL_FAILURE; + } + + ctx->allowUpdate = FALSE; + ctx->allowFinal = FALSE; + ctx->allowOneshot = FALSE; + } + + return p_scossl_rsa_sign(ctx, sig, siglen, sigsize, abDigest, cbDigest); +} + +static int p_scossl_rsa_sigalg_verify_message_final(_In_ SCOSSL_RSA_SIGN_CTX *ctx) +{ + BYTE abDigest[EVP_MAX_MD_SIZE]; + unsigned int cbDigest = 0; + + if (ctx == NULL || ctx->mdctx == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); + return SCOSSL_FAILURE; + } + + if (!ctx->allowFinal) + { + ERR_raise(ERR_LIB_PROV, PROV_R_FINAL_CALL_OUT_OF_ORDER); + return SCOSSL_FAILURE; + } + + if (!EVP_DigestFinal_ex(ctx->mdctx, abDigest, &cbDigest)) + { + return SCOSSL_FAILURE; + } + + ctx->allowUpdate = FALSE; + ctx->allowFinal = FALSE; + ctx->allowOneshot = FALSE; + + return p_scossl_rsa_verify(ctx, ctx->pbSignature, ctx->cbSignature, abDigest, cbDigest); +} + +static const char **p_scossl_rsa_sigalg_query_key_types(void) +{ + static const char *keyTypes[] = { "RSA", NULL }; + return keyTypes; +} + +#define IMPLEMENT_SCOSSL_RSA_SIGALG(md, MD) \ + static SCOSSL_STATUS p_scossl_rsa_##md##_sign_init(_Inout_ SCOSSL_RSA_SIGN_CTX *ctx, \ + _In_ SCOSSL_PROV_RSA_KEY_CTX *keyCtx, \ + _In_ const OSSL_PARAM params[]) \ + { \ + return p_scossl_rsa_sigalg_signverify_init(ctx, keyCtx, params, EVP_PKEY_OP_SIGN, MD); \ + } \ + \ + static SCOSSL_STATUS p_scossl_rsa_##md##_verify_init(_Inout_ SCOSSL_RSA_SIGN_CTX *ctx, \ + _In_ SCOSSL_PROV_RSA_KEY_CTX *keyCtx, \ + _In_ const OSSL_PARAM params[]) \ + { \ + return p_scossl_rsa_sigalg_signverify_init(ctx, keyCtx, params, EVP_PKEY_OP_VERIFY, MD); \ + } \ + \ + static SCOSSL_STATUS p_scossl_rsa_##md##_sign_message_init(_Inout_ SCOSSL_RSA_SIGN_CTX *ctx, \ + _In_ SCOSSL_PROV_RSA_KEY_CTX *keyCtx, \ + _In_ const OSSL_PARAM params[]) \ + { \ + return p_scossl_rsa_sigalg_message_signverify_init(ctx, keyCtx, params, EVP_PKEY_OP_SIGNMSG, MD); \ + } \ + \ + static SCOSSL_STATUS p_scossl_rsa_##md##_verify_message_init(_Inout_ SCOSSL_RSA_SIGN_CTX *ctx, \ + _In_ SCOSSL_PROV_RSA_KEY_CTX *keyCtx, \ + _In_ const OSSL_PARAM params[]) \ + { \ + return p_scossl_rsa_sigalg_message_signverify_init(ctx, keyCtx, params, EVP_PKEY_OP_VERIFYMSG, MD); \ + } \ + \ + const OSSL_DISPATCH p_scossl_rsa_##md##_signature_functions[] = { \ + {OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))p_scossl_rsa_newctx}, \ + {OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))p_scossl_rsa_dupctx}, \ + {OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))p_scossl_rsa_freectx}, \ + {OSSL_FUNC_SIGNATURE_SIGN_INIT, (void (*)(void))p_scossl_rsa_##md##_sign_init}, \ + {OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))p_scossl_rsa_sign}, \ + {OSSL_FUNC_SIGNATURE_SIGN_MESSAGE_INIT, (void (*)(void))p_scossl_rsa_##md##_sign_message_init}, \ + {OSSL_FUNC_SIGNATURE_SIGN_MESSAGE_UPDATE, (void (*)(void))p_scossl_rsa_sigalg_signverify_message_update}, \ + {OSSL_FUNC_SIGNATURE_SIGN_MESSAGE_FINAL, (void (*)(void))p_scossl_rsa_sigalg_sign_message_final}, \ + {OSSL_FUNC_SIGNATURE_VERIFY_INIT, (void (*)(void))p_scossl_rsa_##md##_verify_init}, \ + {OSSL_FUNC_SIGNATURE_VERIFY, (void (*)(void))p_scossl_rsa_verify}, \ + {OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_INIT, (void (*)(void))p_scossl_rsa_##md##_verify_message_init}, \ + {OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_UPDATE,(void (*)(void))p_scossl_rsa_sigalg_signverify_message_update}, \ + {OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_FINAL, (void (*)(void))p_scossl_rsa_sigalg_verify_message_final}, \ + {OSSL_FUNC_SIGNATURE_QUERY_KEY_TYPES, (void (*)(void))p_scossl_rsa_sigalg_query_key_types}, \ + {OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))p_scossl_rsa_get_ctx_params}, \ + {OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_rsa_gettable_ctx_params}, \ + {OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, (void (*)(void))p_scossl_rsa_sigalg_set_ctx_params}, \ + {OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_rsa_sigalg_settable_ctx_params}, \ + {0, NULL}}; + +IMPLEMENT_SCOSSL_RSA_SIGALG(sha1, OSSL_DIGEST_NAME_SHA1) +IMPLEMENT_SCOSSL_RSA_SIGALG(sha224, OSSL_DIGEST_NAME_SHA2_224) +IMPLEMENT_SCOSSL_RSA_SIGALG(sha256, OSSL_DIGEST_NAME_SHA2_256) +IMPLEMENT_SCOSSL_RSA_SIGALG(sha384, OSSL_DIGEST_NAME_SHA2_384) +IMPLEMENT_SCOSSL_RSA_SIGALG(sha512, OSSL_DIGEST_NAME_SHA2_512) +IMPLEMENT_SCOSSL_RSA_SIGALG(sha512_224, OSSL_DIGEST_NAME_SHA2_512_224) +IMPLEMENT_SCOSSL_RSA_SIGALG(sha512_256, OSSL_DIGEST_NAME_SHA2_512_256) +IMPLEMENT_SCOSSL_RSA_SIGALG(sha3_224, OSSL_DIGEST_NAME_SHA3_224) +IMPLEMENT_SCOSSL_RSA_SIGALG(sha3_256, OSSL_DIGEST_NAME_SHA3_256) +IMPLEMENT_SCOSSL_RSA_SIGALG(sha3_384, OSSL_DIGEST_NAME_SHA3_384) +IMPLEMENT_SCOSSL_RSA_SIGALG(sha3_512, OSSL_DIGEST_NAME_SHA3_512) + #ifdef __cplusplus } #endif \ No newline at end of file From b0df71301ccbf62e12e07add8ff05621673ebf1e Mon Sep 17 00:00:00 2001 From: Maxwell Moyer-McKee Date: Tue, 21 Apr 2026 17:52:12 +0000 Subject: [PATCH 03/12] Add RSA sigalg implementations --- ScosslCommon/src/scossl_rsa.c | 4 - .../src/signature/p_scossl_rsa_signature.c | 247 ++++++++++++++---- 2 files changed, 190 insertions(+), 61 deletions(-) diff --git a/ScosslCommon/src/scossl_rsa.c b/ScosslCommon/src/scossl_rsa.c index 66a9916a..1bc7b91d 100644 --- a/ScosslCommon/src/scossl_rsa.c +++ b/ScosslCommon/src/scossl_rsa.c @@ -266,11 +266,9 @@ SCOSSL_STATUS scossl_rsapss_sign(PSYMCRYPT_RSAKEY key, int mdnid, int cbSalt, case RSA_PSS_SALTLEN_MAX: cbSalt = cbSaltMax; break; -#ifdef RSA_PSS_SALTLEN_AUTO_DIGEST_MAX // Added in 3.1, smaller of digest length or maximized salt length case RSA_PSS_SALTLEN_AUTO_DIGEST_MAX: cbSalt = cbSaltMax < (int)cbHashValue ? cbSaltMax : (int)cbHashValue; -#endif } if (cbSalt < 0 || cbSalt > cbSaltMax) @@ -370,10 +368,8 @@ SCOSSL_STATUS scossl_rsapss_verify(PSYMCRYPT_RSAKEY key, int mdnid, int cbSalt, cbSalt = cbSaltMax; break; case RSA_PSS_SALTLEN_AUTO: -#ifdef RSA_PSS_SALTLEN_AUTO_DIGEST_MAX // Added in 3.1; auto salt len for verify case RSA_PSS_SALTLEN_AUTO_DIGEST_MAX: -#endif scFlags = SYMCRYPT_FLAG_RSA_PSS_VERIFY_WITH_MINIMUM_SALT; cbSalt = 0; } diff --git a/SymCryptProvider/src/signature/p_scossl_rsa_signature.c b/SymCryptProvider/src/signature/p_scossl_rsa_signature.c index bed45b03..ecd137e2 100644 --- a/SymCryptProvider/src/signature/p_scossl_rsa_signature.c +++ b/SymCryptProvider/src/signature/p_scossl_rsa_signature.c @@ -151,7 +151,15 @@ static SCOSSL_RSA_SIGN_CTX *p_scossl_rsa_dupctx(_In_ SCOSSL_RSA_SIGN_CTX *ctx) copyCtx->md = ctx->md; copyCtx->cbSalt = ctx->cbSalt; copyCtx->mdInfo = ctx->mdInfo; + copyCtx->allowMdUpdates = ctx->allowMdUpdates; + copyCtx->pssRestricted = ctx->pssRestricted; copyCtx->mgf1MdInfo = ctx->mgf1MdInfo; + copyCtx->cbSaltMin = ctx->cbSaltMin; + copyCtx->isSigalg = ctx->isSigalg; + copyCtx->allowUpdate = ctx->allowUpdate; + copyCtx->allowFinal = ctx->allowFinal; + copyCtx->allowOneshot = ctx->allowOneshot; + copyCtx->cbSignature = ctx->cbSignature; } return copyCtx; @@ -168,10 +176,18 @@ static SCOSSL_STATUS p_scossl_rsa_signverify_init(_Inout_ SCOSSL_RSA_SIGN_CTX *c } ctx->cbSalt = RSA_PSS_SALTLEN_AUTO_DIGEST_MAX; + ctx->cbSaltMin = -1; ctx->operation = operation; + ctx->allowMdUpdates = TRUE; ctx->allowUpdate = TRUE; ctx->allowFinal = TRUE; ctx->allowOneshot = TRUE; + ctx->isSigalg = FALSE; + ctx->pssRestricted = FALSE; + + OPENSSL_free(ctx->pbSignature); + ctx->pbSignature = NULL; + ctx->cbSignature = 0; if (keyCtx != NULL) { @@ -214,7 +230,7 @@ static SCOSSL_STATUS p_scossl_rsa_signverify_init(_Inout_ SCOSSL_RSA_SIGN_CTX *c #ifdef KEYSINUSE_ENABLED if (keysinuse_is_running() && - operation == EVP_PKEY_OP_SIGN) + (operation == EVP_PKEY_OP_SIGN || operation == EVP_PKEY_OP_SIGNMSG)) { p_scossl_rsa_init_keysinuse(keyCtx); } @@ -236,9 +252,9 @@ static SCOSSL_STATUS p_scossl_rsa_verify_init(_Inout_ SCOSSL_RSA_SIGN_CTX *ctx, return p_scossl_rsa_signverify_init(ctx, keyCtx, params, EVP_PKEY_OP_VERIFY); } -static SCOSSL_STATUS p_scossl_rsa_sign(_In_ SCOSSL_RSA_SIGN_CTX *ctx, - _Out_writes_bytes_(*siglen) unsigned char *sig, _Out_ size_t *siglen, size_t sigsize, - _In_reads_bytes_(tbslen) const unsigned char *tbs, size_t tbslen) +static SCOSSL_STATUS p_scossl_rsa_sign_internal(_In_ SCOSSL_RSA_SIGN_CTX *ctx, + _Out_writes_bytes_(*siglen) unsigned char *sig, _Out_ size_t *siglen, size_t sigsize, + _In_reads_bytes_(tbslen) const unsigned char *tbs, size_t tbslen) { int mdnid = ctx->mdInfo == NULL ? NID_undef : ctx->mdInfo->id; SCOSSL_STATUS ret = SCOSSL_FAILURE; @@ -249,12 +265,6 @@ static SCOSSL_STATUS p_scossl_rsa_sign(_In_ SCOSSL_RSA_SIGN_CTX *ctx, return SCOSSL_FAILURE; } - if (ctx->operation != EVP_PKEY_OP_SIGN) - { - ERR_raise(ERR_LIB_PROV, ERR_R_OPERATION_FAIL); - return SCOSSL_FAILURE; - } - if (sig != NULL && sigsize < SymCryptRsakeySizeofModulus(ctx->keyCtx->key)) { ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); @@ -291,9 +301,9 @@ static SCOSSL_STATUS p_scossl_rsa_sign(_In_ SCOSSL_RSA_SIGN_CTX *ctx, return ret; } -static SCOSSL_STATUS p_scossl_rsa_verify(_In_ SCOSSL_RSA_SIGN_CTX *ctx, - _In_reads_bytes_(siglen) const unsigned char *sig, size_t siglen, - _In_reads_bytes_(tbslen) const unsigned char *tbs, size_t tbslen) +static SCOSSL_STATUS p_scossl_rsa_verify_internal(_In_ SCOSSL_RSA_SIGN_CTX *ctx, + _In_reads_bytes_(siglen) const unsigned char *sig, size_t siglen, + _In_reads_bytes_(tbslen) const unsigned char *tbs, size_t tbslen) { int mdnid = ctx->mdInfo == NULL ? NID_undef : ctx->mdInfo->id; @@ -303,12 +313,6 @@ static SCOSSL_STATUS p_scossl_rsa_verify(_In_ SCOSSL_RSA_SIGN_CTX *ctx, return SCOSSL_FAILURE; } - if (ctx->operation != EVP_PKEY_OP_VERIFY) - { - ERR_raise(ERR_LIB_PROV, ERR_R_OPERATION_FAIL); - return SCOSSL_FAILURE; - } - switch (ctx->padding) { case RSA_PKCS1_PADDING: @@ -327,7 +331,6 @@ static SCOSSL_STATUS p_scossl_rsa_verify(_In_ SCOSSL_RSA_SIGN_CTX *ctx, return SCOSSL_FAILURE; } - static SCOSSL_STATUS p_scossl_rsa_digest_signverify_init(_In_ SCOSSL_RSA_SIGN_CTX *ctx, _In_ const char *mdname, _In_ SCOSSL_PROV_RSA_KEY_CTX *keyCtx, _In_ const OSSL_PARAM params[], int operation) { @@ -396,11 +399,26 @@ static SCOSSL_STATUS p_scossl_rsa_digest_verify_init(_In_ SCOSSL_RSA_SIGN_CTX *c static SCOSSL_STATUS p_scossl_rsa_digest_signverify_update(_In_ SCOSSL_RSA_SIGN_CTX *ctx, _In_reads_bytes_(datalen) const unsigned char *data, size_t datalen) { - if (ctx->mdctx == NULL) + if (ctx == NULL || ctx->mdctx == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); return SCOSSL_FAILURE; } + if (ctx->isSigalg) + { + ERR_raise(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED); + return SCOSSL_FAILURE; + } + + if (!ctx->allowUpdate) + { + ERR_raise(ERR_LIB_PROV, PROV_R_UPDATE_CALL_OUT_OF_ORDER); + return SCOSSL_FAILURE; + } + + ctx->allowOneshot = FALSE; + return EVP_DigestUpdate(ctx->mdctx, data, datalen); } @@ -411,36 +429,83 @@ static SCOSSL_STATUS p_scossl_rsa_digest_sign_final(_In_ SCOSSL_RSA_SIGN_CTX *ct BYTE digest[EVP_MAX_MD_SIZE]; unsigned int cbDigest = 0; - if (ctx->mdctx == NULL) + if (ctx == NULL || ctx->mdctx == NULL) { - return ret; + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); + return SCOSSL_FAILURE; + } + + if (ctx->isSigalg) + { + ERR_raise(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED); + return SCOSSL_FAILURE; + } + + if (!ctx->allowFinal) + { + ERR_raise(ERR_LIB_PROV, PROV_R_FINAL_CALL_OUT_OF_ORDER); + return SCOSSL_FAILURE; } // If sig is NULL, this is a size fetch, and the digest does not need to be computed - if (sig == NULL || EVP_DigestFinal_ex(ctx->mdctx, digest, &cbDigest)) + if (sig != NULL) { - ctx->allowMdUpdates = sig != NULL; - ret = p_scossl_rsa_sign(ctx, sig, siglen, sigsize, digest, cbDigest); + if (!EVP_DigestFinal_ex(ctx->mdctx, digest, &cbDigest)) + { + return SCOSSL_FAILURE; + } + + ctx->allowUpdate = FALSE; + ctx->allowFinal = FALSE; + ctx->allowOneshot = FALSE; } + ret = p_scossl_rsa_sign_internal(ctx, sig, siglen, sigsize, digest, cbDigest); + + ctx->allowMdUpdates = TRUE; + return ret; } static SCOSSL_STATUS p_scossl_rsa_digest_verify_final(_In_ SCOSSL_RSA_SIGN_CTX *ctx, _In_reads_bytes_(siglen) unsigned char *sig, size_t siglen) { + SCOSSL_STATUS ret = SCOSSL_FAILURE; BYTE digest[EVP_MAX_MD_SIZE]; unsigned int cbDigest = 0; - if (ctx->mdctx == NULL) + if (ctx == NULL || ctx->mdctx == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); + return SCOSSL_FAILURE; + } + + if (ctx->isSigalg) + { + ERR_raise(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED); + return SCOSSL_FAILURE; + } + + if (!ctx->allowFinal) { + ERR_raise(ERR_LIB_PROV, PROV_R_FINAL_CALL_OUT_OF_ORDER); return SCOSSL_FAILURE; } + if (!EVP_DigestFinal_ex(ctx->mdctx, digest, &cbDigest)) + { + return SCOSSL_FAILURE; + } + + ctx->allowUpdate = FALSE; + ctx->allowFinal = FALSE; + ctx->allowOneshot = FALSE; + + ret = p_scossl_rsa_verify_internal(ctx, sig, siglen, digest, cbDigest); + ctx->allowMdUpdates = TRUE; - return EVP_DigestFinal_ex(ctx->mdctx, digest, &cbDigest) && - p_scossl_rsa_verify(ctx, sig, siglen, digest, cbDigest); + return ret; } static const OSSL_PARAM *p_scossl_rsa_settable_ctx_params(_In_ SCOSSL_RSA_SIGN_CTX *ctx, @@ -628,7 +693,8 @@ static SCOSSL_STATUS p_scossl_rsa_set_ctx_params(_Inout_ SCOSSL_RSA_SIGN_CTX *ct { case RSA_PSS_SALTLEN_AUTO: case RSA_PSS_SALTLEN_AUTO_DIGEST_MAX: - if (ctx->operation == EVP_PKEY_OP_VERIFY) + if (ctx->operation == EVP_PKEY_OP_VERIFY || + ctx->operation == EVP_PKEY_OP_VERIFYMSG) { ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH); return SCOSSL_FAILURE; @@ -713,7 +779,7 @@ static SCOSSL_STATUS p_scossl_rsa_set_ctx_params(_Inout_ SCOSSL_RSA_SIGN_CTX *ct static const OSSL_PARAM *p_scossl_rsa_sigalg_settable_ctx_params(_In_ SCOSSL_RSA_SIGN_CTX *ctx, ossl_unused void *provctx) { - if (ctx != NULL && ctx->operation != EVP_PKEY_OP_VERIFYMSG) + if (ctx != NULL && ctx->operation == EVP_PKEY_OP_VERIFYMSG) { return p_scossl_rsa_sigalg_ctx_settable_param_types; } @@ -1106,30 +1172,6 @@ static SCOSSL_STATUS p_scossl_rsa_set_ctx_md_params(_In_ SCOSSL_RSA_SIGN_CTX *ct return EVP_MD_CTX_set_params(ctx->mdctx, params); } -const OSSL_DISPATCH p_scossl_rsa_signature_functions[] = { - {OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))p_scossl_rsa_newctx}, - {OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))p_scossl_rsa_dupctx}, - {OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))p_scossl_rsa_freectx}, - {OSSL_FUNC_SIGNATURE_SIGN_INIT, (void (*)(void))p_scossl_rsa_sign_init}, - {OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))p_scossl_rsa_sign}, - {OSSL_FUNC_SIGNATURE_VERIFY_INIT, (void (*)(void))p_scossl_rsa_verify_init}, - {OSSL_FUNC_SIGNATURE_VERIFY, (void (*)(void))p_scossl_rsa_verify}, - {OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT, (void (*)(void))p_scossl_rsa_digest_sign_init}, - {OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE, (void (*)(void))p_scossl_rsa_digest_signverify_update}, - {OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL, (void (*)(void))p_scossl_rsa_digest_sign_final}, - {OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT, (void (*)(void))p_scossl_rsa_digest_verify_init}, - {OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE, (void (*)(void))p_scossl_rsa_digest_signverify_update}, - {OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL, (void (*)(void))p_scossl_rsa_digest_verify_final}, - {OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))p_scossl_rsa_get_ctx_params}, - {OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_rsa_gettable_ctx_params}, - {OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, (void (*)(void))p_scossl_rsa_set_ctx_params}, - {OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_rsa_settable_ctx_params}, - {OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS, (void (*)(void))p_scossl_rsa_get_ctx_md_params}, - {OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS, (void (*)(void))p_scossl_rsa_gettable_ctx_md_params}, - {OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS, (void (*)(void))p_scossl_rsa_set_ctx_md_params}, - {OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS, (void (*)(void))p_scossl_rsa_settable_ctx_md_params}, - {0, NULL}}; - static SCOSSL_STATUS p_scossl_rsa_sigalg_signverify_init(_Inout_ SCOSSL_RSA_SIGN_CTX *ctx, _In_ SCOSSL_PROV_RSA_KEY_CTX *keyCtx, _In_ const OSSL_PARAM params[], int operation, _In_ const char *mdname) @@ -1246,7 +1288,7 @@ static SCOSSL_STATUS p_scossl_rsa_sigalg_sign_message_final(_In_ SCOSSL_RSA_SIGN ctx->allowOneshot = FALSE; } - return p_scossl_rsa_sign(ctx, sig, siglen, sigsize, abDigest, cbDigest); + return p_scossl_rsa_sign_internal(ctx, sig, siglen, sigsize, abDigest, cbDigest); } static int p_scossl_rsa_sigalg_verify_message_final(_In_ SCOSSL_RSA_SIGN_CTX *ctx) @@ -1275,9 +1317,100 @@ static int p_scossl_rsa_sigalg_verify_message_final(_In_ SCOSSL_RSA_SIGN_CTX *ct ctx->allowFinal = FALSE; ctx->allowOneshot = FALSE; - return p_scossl_rsa_verify(ctx, ctx->pbSignature, ctx->cbSignature, abDigest, cbDigest); + return p_scossl_rsa_verify_internal(ctx, ctx->pbSignature, ctx->cbSignature, abDigest, cbDigest); +} + +static SCOSSL_STATUS p_scossl_rsa_sign(_In_ SCOSSL_RSA_SIGN_CTX *ctx, + _Out_writes_bytes_(*siglen) unsigned char *sig, _Out_ size_t *siglen, size_t sigsize, + _In_reads_bytes_(tbslen) const unsigned char *tbs, size_t tbslen) +{ + if (ctx == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); + return SCOSSL_FAILURE; + } + + if (!ctx->allowOneshot) + { + ERR_raise(ERR_LIB_PROV, PROV_R_ONESHOT_CALL_OUT_OF_ORDER); + return SCOSSL_FAILURE; + } + + if (ctx->operation == EVP_PKEY_OP_SIGNMSG) + { + if (sig == NULL) + { + return p_scossl_rsa_sigalg_sign_message_final(ctx, sig, siglen, sigsize); + } + + return p_scossl_rsa_sigalg_signverify_message_update(ctx, tbs, tbslen) && + p_scossl_rsa_sigalg_sign_message_final(ctx, sig, siglen, sigsize); + } + + return p_scossl_rsa_sign_internal(ctx, sig, siglen, sigsize, tbs, tbslen); +} + +// Dispatch-facing verify function. +// If verifying a message, digests tbs and verifies the result. +// Otherwise, verifies tbs directly as a pre-computed digest. +static SCOSSL_STATUS p_scossl_rsa_verify(_In_ SCOSSL_RSA_SIGN_CTX *ctx, + _In_reads_bytes_(siglen) const unsigned char *sig, size_t siglen, + _In_reads_bytes_(tbslen) const unsigned char *tbs, size_t tbslen) +{ + if (ctx == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); + return SCOSSL_FAILURE; + } + + if (!ctx->allowOneshot) + { + ERR_raise(ERR_LIB_PROV, PROV_R_ONESHOT_CALL_OUT_OF_ORDER); + return SCOSSL_FAILURE; + } + + if (ctx->operation == EVP_PKEY_OP_VERIFYMSG) + { + OPENSSL_free(ctx->pbSignature); + ctx->cbSignature = 0; + if ((ctx->pbSignature = OPENSSL_memdup(sig, siglen)) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return SCOSSL_FAILURE; + } + ctx->cbSignature = siglen; + + return p_scossl_rsa_sigalg_signverify_message_update(ctx, tbs, tbslen) && + p_scossl_rsa_sigalg_verify_message_final(ctx); + } + + return p_scossl_rsa_verify_internal(ctx, sig, siglen, tbs, tbslen); } +const OSSL_DISPATCH p_scossl_rsa_signature_functions[] = { + {OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))p_scossl_rsa_newctx}, + {OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))p_scossl_rsa_dupctx}, + {OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))p_scossl_rsa_freectx}, + {OSSL_FUNC_SIGNATURE_SIGN_INIT, (void (*)(void))p_scossl_rsa_sign_init}, + {OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))p_scossl_rsa_sign}, + {OSSL_FUNC_SIGNATURE_VERIFY_INIT, (void (*)(void))p_scossl_rsa_verify_init}, + {OSSL_FUNC_SIGNATURE_VERIFY, (void (*)(void))p_scossl_rsa_verify}, + {OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT, (void (*)(void))p_scossl_rsa_digest_sign_init}, + {OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE, (void (*)(void))p_scossl_rsa_digest_signverify_update}, + {OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL, (void (*)(void))p_scossl_rsa_digest_sign_final}, + {OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT, (void (*)(void))p_scossl_rsa_digest_verify_init}, + {OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE, (void (*)(void))p_scossl_rsa_digest_signverify_update}, + {OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL, (void (*)(void))p_scossl_rsa_digest_verify_final}, + {OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))p_scossl_rsa_get_ctx_params}, + {OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_rsa_gettable_ctx_params}, + {OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, (void (*)(void))p_scossl_rsa_set_ctx_params}, + {OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_rsa_settable_ctx_params}, + {OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS, (void (*)(void))p_scossl_rsa_get_ctx_md_params}, + {OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS, (void (*)(void))p_scossl_rsa_gettable_ctx_md_params}, + {OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS, (void (*)(void))p_scossl_rsa_set_ctx_md_params}, + {OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS, (void (*)(void))p_scossl_rsa_settable_ctx_md_params}, + {0, NULL}}; + static const char **p_scossl_rsa_sigalg_query_key_types(void) { static const char *keyTypes[] = { "RSA", NULL }; From f513b782434d5b27b0f824d0d412b413dfaa66c0 Mon Sep 17 00:00:00 2001 From: Maxwell Moyer-McKee Date: Tue, 21 Apr 2026 18:37:55 +0000 Subject: [PATCH 04/12] Separate rsa sigalg functions into another file. --- .../signature/p_scossl_rsa_sigalg_signature.c | 340 ++++++++++++++ .../src/signature/p_scossl_rsa_signature.c | 432 +++--------------- .../src/signature/p_scossl_rsa_signature.h | 69 +++ 3 files changed, 470 insertions(+), 371 deletions(-) create mode 100644 SymCryptProvider/src/signature/p_scossl_rsa_sigalg_signature.c create mode 100644 SymCryptProvider/src/signature/p_scossl_rsa_signature.h diff --git a/SymCryptProvider/src/signature/p_scossl_rsa_sigalg_signature.c b/SymCryptProvider/src/signature/p_scossl_rsa_sigalg_signature.c new file mode 100644 index 00000000..cac5ff25 --- /dev/null +++ b/SymCryptProvider/src/signature/p_scossl_rsa_sigalg_signature.c @@ -0,0 +1,340 @@ +// +// Copyright (c) Microsoft Corporation. Licensed under the MIT license. +// + +#include +#include +#include +#include + +#include "p_scossl_rsa_signature.h" + +#ifdef __cplusplus +extern "C" { +#endif + +static const OSSL_PARAM p_scossl_rsa_sigalg_ctx_settable_param_types[] = { + OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_SIGNATURE, NULL, 0), + OSSL_PARAM_END}; + +static SCOSSL_STATUS p_scossl_rsa_sigalg_signverify_init(_Inout_ SCOSSL_RSA_SIGN_CTX *ctx, _In_ SCOSSL_PROV_RSA_KEY_CTX *keyCtx, + _In_ const OSSL_PARAM params[], int operation, + _In_ const char *mdname) +{ + EVP_MD *md = NULL; + const OSSL_ITEM *mdInfo = NULL; + + if (!p_scossl_rsa_signverify_init(ctx, keyCtx, params, operation)) + { + return SCOSSL_FAILURE; + } + + // Sigalgs are not supported for PSS keys + if (ctx->padding == RSA_PKCS1_PSS_PADDING) + { + ERR_raise(ERR_LIB_PROV, PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return SCOSSL_FAILURE; + } + + mdInfo = p_scossl_rsa_get_supported_md(ctx->libctx, RSA_PKCS1_PADDING, mdname, NULL, &md); + if (mdInfo == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST); + return SCOSSL_FAILURE; + } + + EVP_MD_free(ctx->md); + ctx->md = md; + ctx->mdInfo = mdInfo; + ctx->padding = RSA_PKCS1_PADDING; + ctx->allowMdUpdates = FALSE; + ctx->isSigalg = TRUE; + + return SCOSSL_SUCCESS; +} + +static SCOSSL_STATUS p_scossl_rsa_sigalg_signverify_message_init(_Inout_ SCOSSL_RSA_SIGN_CTX *ctx, _In_ SCOSSL_PROV_RSA_KEY_CTX *keyCtx, + _In_ const OSSL_PARAM params[], int operation, + _In_ const char *mdname) +{ + if (!p_scossl_rsa_sigalg_signverify_init(ctx, keyCtx, params, operation, mdname)) + { + return SCOSSL_FAILURE; + } + + if (ctx->mdctx == NULL) + { + if ((ctx->mdctx = EVP_MD_CTX_new()) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return SCOSSL_FAILURE; + } + } + + if (!EVP_DigestInit_ex2(ctx->mdctx, ctx->md, params)) + { + EVP_MD_CTX_free(ctx->mdctx); + ctx->mdctx = NULL; + return SCOSSL_FAILURE; + } + + return SCOSSL_SUCCESS; +} + +static SCOSSL_STATUS p_scossl_rsa_sigalg_signverify_message_update(_In_ SCOSSL_RSA_SIGN_CTX *ctx, + _In_reads_bytes_(datalen) const unsigned char *data, + size_t datalen) +{ + if (ctx == NULL || ctx->mdctx == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); + return SCOSSL_FAILURE; + } + + if (!ctx->allowUpdate) + { + ERR_raise(ERR_LIB_PROV, PROV_R_UPDATE_CALL_OUT_OF_ORDER); + return SCOSSL_FAILURE; + } + + ctx->allowOneshot = 0; + + return EVP_DigestUpdate(ctx->mdctx, data, datalen); +} + +static SCOSSL_STATUS p_scossl_rsa_sigalg_sign_message_final(_In_ SCOSSL_RSA_SIGN_CTX *ctx, + _Out_writes_bytes_opt_(*siglen) unsigned char *sig, + _Out_ size_t *siglen, size_t sigsize) +{ + BYTE abDigest[EVP_MAX_MD_SIZE]; + unsigned int cbDigest = 0; + + if (ctx == NULL || ctx->mdctx == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); + return SCOSSL_FAILURE; + } + + if (!ctx->allowFinal) + { + ERR_raise(ERR_LIB_PROV, PROV_R_FINAL_CALL_OUT_OF_ORDER); + return SCOSSL_FAILURE; + } +\ + if (sig != NULL) + { + if (!EVP_DigestFinal_ex(ctx->mdctx, abDigest, &cbDigest)) + { + return SCOSSL_FAILURE; + } + + ctx->allowUpdate = FALSE; + ctx->allowFinal = FALSE; + ctx->allowOneshot = FALSE; + } + + return p_scossl_rsa_sign_internal(ctx, sig, siglen, sigsize, abDigest, cbDigest); +} + +static int p_scossl_rsa_sigalg_verify_message_final(_In_ SCOSSL_RSA_SIGN_CTX *ctx) +{ + BYTE abDigest[EVP_MAX_MD_SIZE]; + unsigned int cbDigest = 0; + + if (ctx == NULL || ctx->mdctx == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); + return SCOSSL_FAILURE; + } + + if (!ctx->allowFinal) + { + ERR_raise(ERR_LIB_PROV, PROV_R_FINAL_CALL_OUT_OF_ORDER); + return SCOSSL_FAILURE; + } + + if (!EVP_DigestFinal_ex(ctx->mdctx, abDigest, &cbDigest)) + { + return SCOSSL_FAILURE; + } + + ctx->allowUpdate = FALSE; + ctx->allowFinal = FALSE; + ctx->allowOneshot = FALSE; + + return p_scossl_rsa_verify_internal(ctx, ctx->pbSignature, ctx->cbSignature, abDigest, cbDigest); +} + +static SCOSSL_STATUS p_scossl_rsa_sigalg_sign(_In_ SCOSSL_RSA_SIGN_CTX *ctx, + _Out_writes_bytes_(*siglen) unsigned char *sig, _Out_ size_t *siglen, size_t sigsize, + _In_reads_bytes_(tbslen) const unsigned char *tbs, size_t tbslen) +{ + if (ctx == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); + return SCOSSL_FAILURE; + } + + if (!ctx->allowOneshot) + { + ERR_raise(ERR_LIB_PROV, PROV_R_ONESHOT_CALL_OUT_OF_ORDER); + return SCOSSL_FAILURE; + } + + if (ctx->operation == EVP_PKEY_OP_SIGNMSG) + { + if (sig == NULL) + { + return p_scossl_rsa_sigalg_sign_message_final(ctx, sig, siglen, sigsize); + } + + return p_scossl_rsa_sigalg_signverify_message_update(ctx, tbs, tbslen) && + p_scossl_rsa_sigalg_sign_message_final(ctx, sig, siglen, sigsize); + } + + return p_scossl_rsa_sign_internal(ctx, sig, siglen, sigsize, tbs, tbslen); +} + +static SCOSSL_STATUS p_scossl_rsa_sigalg_verify(_In_ SCOSSL_RSA_SIGN_CTX *ctx, + _In_reads_bytes_(siglen) const unsigned char *sig, size_t siglen, + _In_reads_bytes_(tbslen) const unsigned char *tbs, size_t tbslen) +{ + if (ctx == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); + return SCOSSL_FAILURE; + } + + if (!ctx->allowOneshot) + { + ERR_raise(ERR_LIB_PROV, PROV_R_ONESHOT_CALL_OUT_OF_ORDER); + return SCOSSL_FAILURE; + } + + if (ctx->operation == EVP_PKEY_OP_VERIFYMSG) + { + OPENSSL_free(ctx->pbSignature); + ctx->cbSignature = 0; + + if ((ctx->pbSignature = OPENSSL_memdup(sig, siglen)) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return SCOSSL_FAILURE; + } + ctx->cbSignature = siglen; + + return p_scossl_rsa_sigalg_signverify_message_update(ctx, tbs, tbslen) && + p_scossl_rsa_sigalg_verify_message_final(ctx); + } + + return p_scossl_rsa_verify_internal(ctx, sig, siglen, tbs, tbslen); +} + +static const OSSL_PARAM *p_scossl_rsa_sigalg_settable_ctx_params(_In_ SCOSSL_RSA_SIGN_CTX *ctx, ossl_unused void *provctx) +{ + if (ctx != NULL && ctx->operation == EVP_PKEY_OP_VERIFYMSG) + { + return p_scossl_rsa_sigalg_ctx_settable_param_types; + } + + return NULL; +} + +static SCOSSL_STATUS p_scossl_rsa_sigalg_set_ctx_params(_Inout_ SCOSSL_RSA_SIGN_CTX *ctx, _In_ const OSSL_PARAM params[]) +{ + const OSSL_PARAM *p; + + if (ctx == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); + return SCOSSL_FAILURE; + } + + if (ctx->operation == EVP_PKEY_OP_VERIFYMSG) + { + if ((p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_SIGNATURE)) != NULL) + { + OPENSSL_free(ctx->pbSignature); + ctx->pbSignature = NULL; + ctx->cbSignature = 0; + if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->pbSignature, 0, &ctx->cbSignature)) + { + return SCOSSL_FAILURE; + } + } + } + + return SCOSSL_SUCCESS; +} + +static const char **p_scossl_rsa_sigalg_query_key_types(void) +{ + static const char *keyTypes[] = { "RSA", NULL }; + return keyTypes; +} + +#define IMPLEMENT_SCOSSL_RSA_SIGALG(md, MD) \ + static SCOSSL_STATUS p_scossl_rsa_##md##_sign_init(_Inout_ SCOSSL_RSA_SIGN_CTX *ctx, \ + _In_ SCOSSL_PROV_RSA_KEY_CTX *keyCtx, \ + _In_ const OSSL_PARAM params[]) \ + { \ + return p_scossl_rsa_sigalg_signverify_init(ctx, keyCtx, params, EVP_PKEY_OP_SIGN, MD); \ + } \ + \ + static SCOSSL_STATUS p_scossl_rsa_##md##_verify_init(_Inout_ SCOSSL_RSA_SIGN_CTX *ctx, \ + _In_ SCOSSL_PROV_RSA_KEY_CTX *keyCtx, \ + _In_ const OSSL_PARAM params[]) \ + { \ + return p_scossl_rsa_sigalg_signverify_init(ctx, keyCtx, params, EVP_PKEY_OP_VERIFY, MD); \ + } \ + \ + static SCOSSL_STATUS p_scossl_rsa_##md##_sign_message_init(_Inout_ SCOSSL_RSA_SIGN_CTX *ctx, \ + _In_ SCOSSL_PROV_RSA_KEY_CTX *keyCtx, \ + _In_ const OSSL_PARAM params[]) \ + { \ + return p_scossl_rsa_sigalg_signverify_message_init(ctx, keyCtx, params, EVP_PKEY_OP_SIGNMSG, MD); \ + } \ + \ + static SCOSSL_STATUS p_scossl_rsa_##md##_verify_message_init(_Inout_ SCOSSL_RSA_SIGN_CTX *ctx, \ + _In_ SCOSSL_PROV_RSA_KEY_CTX *keyCtx, \ + _In_ const OSSL_PARAM params[]) \ + { \ + return p_scossl_rsa_sigalg_signverify_message_init(ctx, keyCtx, params, EVP_PKEY_OP_VERIFYMSG, MD); \ + } \ + \ + const OSSL_DISPATCH p_scossl_rsa_##md##_signature_functions[] = { \ + {OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))p_scossl_rsa_newctx}, \ + {OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))p_scossl_rsa_dupctx}, \ + {OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))p_scossl_rsa_freectx}, \ + {OSSL_FUNC_SIGNATURE_SIGN_INIT, (void (*)(void))p_scossl_rsa_##md##_sign_init}, \ + {OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))p_scossl_rsa_sigalg_sign}, \ + {OSSL_FUNC_SIGNATURE_SIGN_MESSAGE_INIT, (void (*)(void))p_scossl_rsa_##md##_sign_message_init}, \ + {OSSL_FUNC_SIGNATURE_SIGN_MESSAGE_UPDATE, (void (*)(void))p_scossl_rsa_sigalg_signverify_message_update}, \ + {OSSL_FUNC_SIGNATURE_SIGN_MESSAGE_FINAL, (void (*)(void))p_scossl_rsa_sigalg_sign_message_final}, \ + {OSSL_FUNC_SIGNATURE_VERIFY_INIT, (void (*)(void))p_scossl_rsa_##md##_verify_init}, \ + {OSSL_FUNC_SIGNATURE_VERIFY, (void (*)(void))p_scossl_rsa_sigalg_verify}, \ + {OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_INIT, (void (*)(void))p_scossl_rsa_##md##_verify_message_init}, \ + {OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_UPDATE,(void (*)(void))p_scossl_rsa_sigalg_signverify_message_update}, \ + {OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_FINAL, (void (*)(void))p_scossl_rsa_sigalg_verify_message_final}, \ + {OSSL_FUNC_SIGNATURE_QUERY_KEY_TYPES, (void (*)(void))p_scossl_rsa_sigalg_query_key_types}, \ + {OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))p_scossl_rsa_get_ctx_params}, \ + {OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_rsa_gettable_ctx_params}, \ + {OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, (void (*)(void))p_scossl_rsa_sigalg_set_ctx_params}, \ + {OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_rsa_sigalg_settable_ctx_params}, \ + {0, NULL}}; + +IMPLEMENT_SCOSSL_RSA_SIGALG(sha1, OSSL_DIGEST_NAME_SHA1) +IMPLEMENT_SCOSSL_RSA_SIGALG(sha224, OSSL_DIGEST_NAME_SHA2_224) +IMPLEMENT_SCOSSL_RSA_SIGALG(sha256, OSSL_DIGEST_NAME_SHA2_256) +IMPLEMENT_SCOSSL_RSA_SIGALG(sha384, OSSL_DIGEST_NAME_SHA2_384) +IMPLEMENT_SCOSSL_RSA_SIGALG(sha512, OSSL_DIGEST_NAME_SHA2_512) +IMPLEMENT_SCOSSL_RSA_SIGALG(sha512_224, OSSL_DIGEST_NAME_SHA2_512_224) +IMPLEMENT_SCOSSL_RSA_SIGALG(sha512_256, OSSL_DIGEST_NAME_SHA2_512_256) +IMPLEMENT_SCOSSL_RSA_SIGALG(sha3_224, OSSL_DIGEST_NAME_SHA3_224) +IMPLEMENT_SCOSSL_RSA_SIGALG(sha3_256, OSSL_DIGEST_NAME_SHA3_256) +IMPLEMENT_SCOSSL_RSA_SIGALG(sha3_384, OSSL_DIGEST_NAME_SHA3_384) +IMPLEMENT_SCOSSL_RSA_SIGALG(sha3_512, OSSL_DIGEST_NAME_SHA3_512) + +#ifdef __cplusplus +} +#endif diff --git a/SymCryptProvider/src/signature/p_scossl_rsa_signature.c b/SymCryptProvider/src/signature/p_scossl_rsa_signature.c index ecd137e2..f837de5c 100644 --- a/SymCryptProvider/src/signature/p_scossl_rsa_signature.c +++ b/SymCryptProvider/src/signature/p_scossl_rsa_signature.c @@ -7,45 +7,13 @@ #include #include -#include "scossl_rsa.h" -#include "p_scossl_rsa.h" -#include "p_scossl_base.h" +#include "p_scossl_rsa_signature.h" #ifdef __cplusplus extern "C" { #endif -typedef struct -{ - SCOSSL_PROV_RSA_KEY_CTX *keyCtx; - UINT8 padding; - int operation; - - // Needed for fetching md - OSSL_LIB_CTX *libctx; - char* propq; - - EVP_MD_CTX *mdctx; - EVP_MD *md; - const OSSL_ITEM *mdInfo; // Informational, must match md if set - BOOL allowMdUpdates; - - // PSS params - BOOL pssRestricted; - const OSSL_ITEM *mgf1MdInfo; // Informational, must match md if set - int cbSalt; - int cbSaltMin; - - // Sigalg state tracking - BOOL isSigalg; - BOOL allowUpdate; - BOOL allowFinal; - BOOL allowOneshot; - - // Sigalg verify message support - PBYTE pbSignature; - SIZE_T cbSignature; -} SCOSSL_RSA_SIGN_CTX; +static SCOSSL_STATUS p_scossl_rsa_set_ctx_params(_Inout_ SCOSSL_RSA_SIGN_CTX *ctx, _In_ const OSSL_PARAM params[]); #define SCOSSL_RSA_SIGNATURE_GETTABLE_PARAMS \ OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0), \ @@ -70,10 +38,6 @@ static const OSSL_PARAM p_scossl_rsa_pss_sig_ctx_gettable_param_types[] = { SCOSSL_RSA_PSS_SIGNATURE_GETTABLE_PARAMS OSSL_PARAM_END}; -static const OSSL_PARAM p_scossl_rsa_sigalg_ctx_settable_param_types[] = { - OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_SIGNATURE, NULL, 0), - OSSL_PARAM_END}; - // Padding may not be set at the time of querying settable params, so PSS params // are always accepted. The provider will check the padding before attempting // to set the PSS parameters @@ -95,9 +59,8 @@ static OSSL_ITEM p_scossl_rsa_sign_padding_modes[] = { {RSA_PKCS1_PSS_PADDING, OSSL_PKEY_RSA_PAD_MODE_PSS}, {0, NULL}}; -static SCOSSL_STATUS p_scossl_rsa_set_ctx_params(_Inout_ SCOSSL_RSA_SIGN_CTX *ctx, _In_ const OSSL_PARAM params[]); - -static SCOSSL_RSA_SIGN_CTX *p_scossl_rsa_newctx(_In_ SCOSSL_PROVCTX *provctx, _In_ const char *propq) +_Use_decl_annotations_ +SCOSSL_RSA_SIGN_CTX *p_scossl_rsa_newctx(SCOSSL_PROVCTX *provctx, const char *propq) { SCOSSL_RSA_SIGN_CTX *ctx = OPENSSL_zalloc(sizeof(SCOSSL_RSA_SIGN_CTX)); if (ctx != NULL) @@ -118,7 +81,8 @@ static SCOSSL_RSA_SIGN_CTX *p_scossl_rsa_newctx(_In_ SCOSSL_PROVCTX *provctx, _I return ctx; } -static void p_scossl_rsa_freectx(SCOSSL_RSA_SIGN_CTX *ctx) +_Use_decl_annotations_ +void p_scossl_rsa_freectx(SCOSSL_RSA_SIGN_CTX *ctx) { if (ctx == NULL) return; @@ -130,7 +94,8 @@ static void p_scossl_rsa_freectx(SCOSSL_RSA_SIGN_CTX *ctx) OPENSSL_free(ctx); } -static SCOSSL_RSA_SIGN_CTX *p_scossl_rsa_dupctx(_In_ SCOSSL_RSA_SIGN_CTX *ctx) +_Use_decl_annotations_ +SCOSSL_RSA_SIGN_CTX *p_scossl_rsa_dupctx(SCOSSL_RSA_SIGN_CTX *ctx) { SCOSSL_RSA_SIGN_CTX *copyCtx = OPENSSL_zalloc(sizeof(SCOSSL_RSA_SIGN_CTX)); if (copyCtx != NULL) @@ -165,8 +130,9 @@ static SCOSSL_RSA_SIGN_CTX *p_scossl_rsa_dupctx(_In_ SCOSSL_RSA_SIGN_CTX *ctx) return copyCtx; } -static SCOSSL_STATUS p_scossl_rsa_signverify_init(_Inout_ SCOSSL_RSA_SIGN_CTX *ctx, _In_ SCOSSL_PROV_RSA_KEY_CTX *keyCtx, - _In_ const OSSL_PARAM params[], int operation) +_Use_decl_annotations_ +SCOSSL_STATUS p_scossl_rsa_signverify_init(SCOSSL_RSA_SIGN_CTX *ctx, SCOSSL_PROV_RSA_KEY_CTX *keyCtx, + const OSSL_PARAM params[], int operation) { if (ctx == NULL || (keyCtx == NULL && ctx->keyCtx == NULL)) @@ -252,9 +218,10 @@ static SCOSSL_STATUS p_scossl_rsa_verify_init(_Inout_ SCOSSL_RSA_SIGN_CTX *ctx, return p_scossl_rsa_signverify_init(ctx, keyCtx, params, EVP_PKEY_OP_VERIFY); } -static SCOSSL_STATUS p_scossl_rsa_sign_internal(_In_ SCOSSL_RSA_SIGN_CTX *ctx, - _Out_writes_bytes_(*siglen) unsigned char *sig, _Out_ size_t *siglen, size_t sigsize, - _In_reads_bytes_(tbslen) const unsigned char *tbs, size_t tbslen) +_Use_decl_annotations_ +SCOSSL_STATUS p_scossl_rsa_sign_internal(SCOSSL_RSA_SIGN_CTX *ctx, + unsigned char *sig, size_t *siglen, size_t sigsize, + const unsigned char *tbs, size_t tbslen) { int mdnid = ctx->mdInfo == NULL ? NID_undef : ctx->mdInfo->id; SCOSSL_STATUS ret = SCOSSL_FAILURE; @@ -301,9 +268,10 @@ static SCOSSL_STATUS p_scossl_rsa_sign_internal(_In_ SCOSSL_RSA_SIGN_CTX *ctx, return ret; } -static SCOSSL_STATUS p_scossl_rsa_verify_internal(_In_ SCOSSL_RSA_SIGN_CTX *ctx, - _In_reads_bytes_(siglen) const unsigned char *sig, size_t siglen, - _In_reads_bytes_(tbslen) const unsigned char *tbs, size_t tbslen) +_Use_decl_annotations_ +SCOSSL_STATUS p_scossl_rsa_verify_internal(SCOSSL_RSA_SIGN_CTX *ctx, + const unsigned char *sig, size_t siglen, + const unsigned char *tbs, size_t tbslen) { int mdnid = ctx->mdInfo == NULL ? NID_undef : ctx->mdInfo->id; @@ -508,6 +476,44 @@ static SCOSSL_STATUS p_scossl_rsa_digest_verify_final(_In_ SCOSSL_RSA_SIGN_CTX * return ret; } +static SCOSSL_STATUS p_scossl_rsa_sign(_In_ SCOSSL_RSA_SIGN_CTX *ctx, + _Out_writes_bytes_(*siglen) unsigned char *sig, _Out_ size_t *siglen, size_t sigsize, + _In_reads_bytes_(tbslen) const unsigned char *tbs, size_t tbslen) +{ + if (ctx == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); + return SCOSSL_FAILURE; + } + + if (!ctx->allowOneshot) + { + ERR_raise(ERR_LIB_PROV, PROV_R_ONESHOT_CALL_OUT_OF_ORDER); + return SCOSSL_FAILURE; + } + + return p_scossl_rsa_sign_internal(ctx, sig, siglen, sigsize, tbs, tbslen); +} + +static SCOSSL_STATUS p_scossl_rsa_verify(_In_ SCOSSL_RSA_SIGN_CTX *ctx, + _In_reads_bytes_(siglen) const unsigned char *sig, size_t siglen, + _In_reads_bytes_(tbslen) const unsigned char *tbs, size_t tbslen) +{ + if (ctx == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); + return SCOSSL_FAILURE; + } + + if (!ctx->allowOneshot) + { + ERR_raise(ERR_LIB_PROV, PROV_R_ONESHOT_CALL_OUT_OF_ORDER); + return SCOSSL_FAILURE; + } + + return p_scossl_rsa_verify_internal(ctx, sig, siglen, tbs, tbslen); +} + static const OSSL_PARAM *p_scossl_rsa_settable_ctx_params(_In_ SCOSSL_RSA_SIGN_CTX *ctx, ossl_unused void *provctx) { @@ -777,42 +783,8 @@ static SCOSSL_STATUS p_scossl_rsa_set_ctx_params(_Inout_ SCOSSL_RSA_SIGN_CTX *ct return SCOSSL_SUCCESS; } -static const OSSL_PARAM *p_scossl_rsa_sigalg_settable_ctx_params(_In_ SCOSSL_RSA_SIGN_CTX *ctx, ossl_unused void *provctx) -{ - if (ctx != NULL && ctx->operation == EVP_PKEY_OP_VERIFYMSG) - { - return p_scossl_rsa_sigalg_ctx_settable_param_types; - } - - return NULL; -} - -static SCOSSL_STATUS p_scossl_rsa_sigalg_set_ctx_params(_Inout_ SCOSSL_RSA_SIGN_CTX *ctx, _In_ const OSSL_PARAM params[]) -{ - const OSSL_PARAM *p; - - if (ctx == NULL) - return SCOSSL_FAILURE; - - if (ctx->operation == EVP_PKEY_OP_VERIFYMSG) - { - if ((p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_SIGNATURE)) != NULL) - { - OPENSSL_free(ctx->pbSignature); - ctx->pbSignature = NULL; - ctx->cbSignature = 0; - if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->pbSignature, 0, &ctx->cbSignature)) - { - return SCOSSL_FAILURE; - } - } - } - - return SCOSSL_SUCCESS; -} - -static const OSSL_PARAM *p_scossl_rsa_gettable_ctx_params(_In_ SCOSSL_RSA_SIGN_CTX *ctx, - ossl_unused void *provctx) +_Use_decl_annotations_ +const OSSL_PARAM *p_scossl_rsa_gettable_ctx_params(SCOSSL_RSA_SIGN_CTX *ctx, ossl_unused void *provctx) { return ctx->padding == RSA_PKCS1_PSS_PADDING ? p_scossl_rsa_pss_sig_ctx_gettable_param_types : p_scossl_rsa_sig_ctx_gettable_param_types; } @@ -915,7 +887,8 @@ static ASN1_STRING *p_scossl_rsa_pss_params_to_asn1_sequence(_In_ SCOSSL_RSA_SIG return pssParamSeq; } -static SCOSSL_STATUS p_scossl_rsa_get_ctx_params(_In_ SCOSSL_RSA_SIGN_CTX *ctx, _Inout_ OSSL_PARAM params[]) +_Use_decl_annotations_ +SCOSSL_STATUS p_scossl_rsa_get_ctx_params(SCOSSL_RSA_SIGN_CTX *ctx, OSSL_PARAM params[]) { if (params == NULL) { @@ -1172,221 +1145,6 @@ static SCOSSL_STATUS p_scossl_rsa_set_ctx_md_params(_In_ SCOSSL_RSA_SIGN_CTX *ct return EVP_MD_CTX_set_params(ctx->mdctx, params); } -static SCOSSL_STATUS p_scossl_rsa_sigalg_signverify_init(_Inout_ SCOSSL_RSA_SIGN_CTX *ctx, _In_ SCOSSL_PROV_RSA_KEY_CTX *keyCtx, - _In_ const OSSL_PARAM params[], int operation, - _In_ const char *mdname) -{ - EVP_MD *md = NULL; - - if (!p_scossl_rsa_signverify_init(ctx, keyCtx, params, operation)) - { - return SCOSSL_FAILURE; - } - - // Sigalgs are not supported for PSS keys - if (ctx->padding == RSA_PKCS1_PSS_PADDING) - { - ERR_raise(ERR_LIB_PROV, PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); - return SCOSSL_FAILURE; - } - - const OSSL_ITEM *mdInfo = p_scossl_rsa_get_supported_md(ctx->libctx, RSA_PKCS1_PADDING, mdname, NULL, &md); - if (mdInfo == NULL) - { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST); - return SCOSSL_FAILURE; - } - - EVP_MD_free(ctx->md); - ctx->md = md; - ctx->mdInfo = mdInfo; - ctx->padding = RSA_PKCS1_PADDING; - ctx->allowMdUpdates = FALSE; - ctx->isSigalg = TRUE; - - return SCOSSL_SUCCESS; -} - -static SCOSSL_STATUS p_scossl_rsa_sigalg_message_signverify_init(_Inout_ SCOSSL_RSA_SIGN_CTX *ctx, _In_ SCOSSL_PROV_RSA_KEY_CTX *keyCtx, - _In_ const OSSL_PARAM params[], int operation, - _In_ const char *mdname) -{ - if (!p_scossl_rsa_sigalg_signverify_init(ctx, keyCtx, params, operation, mdname)) - { - return SCOSSL_FAILURE; - } - - if (ctx->mdctx == NULL) - { - if ((ctx->mdctx = EVP_MD_CTX_new()) == NULL) - { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - return SCOSSL_FAILURE; - } - } - - if (!EVP_DigestInit_ex2(ctx->mdctx, ctx->md, params)) - { - EVP_MD_CTX_free(ctx->mdctx); - ctx->mdctx = NULL; - return SCOSSL_FAILURE; - } - - return SCOSSL_SUCCESS; -} - -static SCOSSL_STATUS p_scossl_rsa_sigalg_signverify_message_update(_In_ SCOSSL_RSA_SIGN_CTX *ctx, - _In_reads_bytes_(datalen) const unsigned char *data, - size_t datalen) -{ - if (ctx == NULL || ctx->mdctx == NULL) - { - ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); - return SCOSSL_FAILURE; - } - - if (!ctx->allowUpdate) - { - ERR_raise(ERR_LIB_PROV, PROV_R_UPDATE_CALL_OUT_OF_ORDER); - return SCOSSL_FAILURE; - } - - ctx->allowOneshot = 0; - - return EVP_DigestUpdate(ctx->mdctx, data, datalen); -} - -static SCOSSL_STATUS p_scossl_rsa_sigalg_sign_message_final(_In_ SCOSSL_RSA_SIGN_CTX *ctx, - _Out_writes_bytes_opt_(*siglen) unsigned char *sig, - _Out_ size_t *siglen, size_t sigsize) -{ - BYTE abDigest[EVP_MAX_MD_SIZE]; - unsigned int cbDigest = 0; - - if (ctx == NULL || ctx->mdctx == NULL) - { - ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); - return SCOSSL_FAILURE; - } - - if (!ctx->allowFinal) - { - ERR_raise(ERR_LIB_PROV, PROV_R_FINAL_CALL_OUT_OF_ORDER); - return SCOSSL_FAILURE; - } - - // If sig is NULL, this is a size fetch, and the digest does not need to be computed - if (sig != NULL) - { - if (!EVP_DigestFinal_ex(ctx->mdctx, abDigest, &cbDigest)) - { - return SCOSSL_FAILURE; - } - - ctx->allowUpdate = FALSE; - ctx->allowFinal = FALSE; - ctx->allowOneshot = FALSE; - } - - return p_scossl_rsa_sign_internal(ctx, sig, siglen, sigsize, abDigest, cbDigest); -} - -static int p_scossl_rsa_sigalg_verify_message_final(_In_ SCOSSL_RSA_SIGN_CTX *ctx) -{ - BYTE abDigest[EVP_MAX_MD_SIZE]; - unsigned int cbDigest = 0; - - if (ctx == NULL || ctx->mdctx == NULL) - { - ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); - return SCOSSL_FAILURE; - } - - if (!ctx->allowFinal) - { - ERR_raise(ERR_LIB_PROV, PROV_R_FINAL_CALL_OUT_OF_ORDER); - return SCOSSL_FAILURE; - } - - if (!EVP_DigestFinal_ex(ctx->mdctx, abDigest, &cbDigest)) - { - return SCOSSL_FAILURE; - } - - ctx->allowUpdate = FALSE; - ctx->allowFinal = FALSE; - ctx->allowOneshot = FALSE; - - return p_scossl_rsa_verify_internal(ctx, ctx->pbSignature, ctx->cbSignature, abDigest, cbDigest); -} - -static SCOSSL_STATUS p_scossl_rsa_sign(_In_ SCOSSL_RSA_SIGN_CTX *ctx, - _Out_writes_bytes_(*siglen) unsigned char *sig, _Out_ size_t *siglen, size_t sigsize, - _In_reads_bytes_(tbslen) const unsigned char *tbs, size_t tbslen) -{ - if (ctx == NULL) - { - ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); - return SCOSSL_FAILURE; - } - - if (!ctx->allowOneshot) - { - ERR_raise(ERR_LIB_PROV, PROV_R_ONESHOT_CALL_OUT_OF_ORDER); - return SCOSSL_FAILURE; - } - - if (ctx->operation == EVP_PKEY_OP_SIGNMSG) - { - if (sig == NULL) - { - return p_scossl_rsa_sigalg_sign_message_final(ctx, sig, siglen, sigsize); - } - - return p_scossl_rsa_sigalg_signverify_message_update(ctx, tbs, tbslen) && - p_scossl_rsa_sigalg_sign_message_final(ctx, sig, siglen, sigsize); - } - - return p_scossl_rsa_sign_internal(ctx, sig, siglen, sigsize, tbs, tbslen); -} - -// Dispatch-facing verify function. -// If verifying a message, digests tbs and verifies the result. -// Otherwise, verifies tbs directly as a pre-computed digest. -static SCOSSL_STATUS p_scossl_rsa_verify(_In_ SCOSSL_RSA_SIGN_CTX *ctx, - _In_reads_bytes_(siglen) const unsigned char *sig, size_t siglen, - _In_reads_bytes_(tbslen) const unsigned char *tbs, size_t tbslen) -{ - if (ctx == NULL) - { - ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); - return SCOSSL_FAILURE; - } - - if (!ctx->allowOneshot) - { - ERR_raise(ERR_LIB_PROV, PROV_R_ONESHOT_CALL_OUT_OF_ORDER); - return SCOSSL_FAILURE; - } - - if (ctx->operation == EVP_PKEY_OP_VERIFYMSG) - { - OPENSSL_free(ctx->pbSignature); - ctx->cbSignature = 0; - if ((ctx->pbSignature = OPENSSL_memdup(sig, siglen)) == NULL) - { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - return SCOSSL_FAILURE; - } - ctx->cbSignature = siglen; - - return p_scossl_rsa_sigalg_signverify_message_update(ctx, tbs, tbslen) && - p_scossl_rsa_sigalg_verify_message_final(ctx); - } - - return p_scossl_rsa_verify_internal(ctx, sig, siglen, tbs, tbslen); -} - const OSSL_DISPATCH p_scossl_rsa_signature_functions[] = { {OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))p_scossl_rsa_newctx}, {OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))p_scossl_rsa_dupctx}, @@ -1411,74 +1169,6 @@ const OSSL_DISPATCH p_scossl_rsa_signature_functions[] = { {OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS, (void (*)(void))p_scossl_rsa_settable_ctx_md_params}, {0, NULL}}; -static const char **p_scossl_rsa_sigalg_query_key_types(void) -{ - static const char *keyTypes[] = { "RSA", NULL }; - return keyTypes; -} - -#define IMPLEMENT_SCOSSL_RSA_SIGALG(md, MD) \ - static SCOSSL_STATUS p_scossl_rsa_##md##_sign_init(_Inout_ SCOSSL_RSA_SIGN_CTX *ctx, \ - _In_ SCOSSL_PROV_RSA_KEY_CTX *keyCtx, \ - _In_ const OSSL_PARAM params[]) \ - { \ - return p_scossl_rsa_sigalg_signverify_init(ctx, keyCtx, params, EVP_PKEY_OP_SIGN, MD); \ - } \ - \ - static SCOSSL_STATUS p_scossl_rsa_##md##_verify_init(_Inout_ SCOSSL_RSA_SIGN_CTX *ctx, \ - _In_ SCOSSL_PROV_RSA_KEY_CTX *keyCtx, \ - _In_ const OSSL_PARAM params[]) \ - { \ - return p_scossl_rsa_sigalg_signverify_init(ctx, keyCtx, params, EVP_PKEY_OP_VERIFY, MD); \ - } \ - \ - static SCOSSL_STATUS p_scossl_rsa_##md##_sign_message_init(_Inout_ SCOSSL_RSA_SIGN_CTX *ctx, \ - _In_ SCOSSL_PROV_RSA_KEY_CTX *keyCtx, \ - _In_ const OSSL_PARAM params[]) \ - { \ - return p_scossl_rsa_sigalg_message_signverify_init(ctx, keyCtx, params, EVP_PKEY_OP_SIGNMSG, MD); \ - } \ - \ - static SCOSSL_STATUS p_scossl_rsa_##md##_verify_message_init(_Inout_ SCOSSL_RSA_SIGN_CTX *ctx, \ - _In_ SCOSSL_PROV_RSA_KEY_CTX *keyCtx, \ - _In_ const OSSL_PARAM params[]) \ - { \ - return p_scossl_rsa_sigalg_message_signverify_init(ctx, keyCtx, params, EVP_PKEY_OP_VERIFYMSG, MD); \ - } \ - \ - const OSSL_DISPATCH p_scossl_rsa_##md##_signature_functions[] = { \ - {OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))p_scossl_rsa_newctx}, \ - {OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))p_scossl_rsa_dupctx}, \ - {OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))p_scossl_rsa_freectx}, \ - {OSSL_FUNC_SIGNATURE_SIGN_INIT, (void (*)(void))p_scossl_rsa_##md##_sign_init}, \ - {OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))p_scossl_rsa_sign}, \ - {OSSL_FUNC_SIGNATURE_SIGN_MESSAGE_INIT, (void (*)(void))p_scossl_rsa_##md##_sign_message_init}, \ - {OSSL_FUNC_SIGNATURE_SIGN_MESSAGE_UPDATE, (void (*)(void))p_scossl_rsa_sigalg_signverify_message_update}, \ - {OSSL_FUNC_SIGNATURE_SIGN_MESSAGE_FINAL, (void (*)(void))p_scossl_rsa_sigalg_sign_message_final}, \ - {OSSL_FUNC_SIGNATURE_VERIFY_INIT, (void (*)(void))p_scossl_rsa_##md##_verify_init}, \ - {OSSL_FUNC_SIGNATURE_VERIFY, (void (*)(void))p_scossl_rsa_verify}, \ - {OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_INIT, (void (*)(void))p_scossl_rsa_##md##_verify_message_init}, \ - {OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_UPDATE,(void (*)(void))p_scossl_rsa_sigalg_signverify_message_update}, \ - {OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_FINAL, (void (*)(void))p_scossl_rsa_sigalg_verify_message_final}, \ - {OSSL_FUNC_SIGNATURE_QUERY_KEY_TYPES, (void (*)(void))p_scossl_rsa_sigalg_query_key_types}, \ - {OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))p_scossl_rsa_get_ctx_params}, \ - {OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_rsa_gettable_ctx_params}, \ - {OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, (void (*)(void))p_scossl_rsa_sigalg_set_ctx_params}, \ - {OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_rsa_sigalg_settable_ctx_params}, \ - {0, NULL}}; - -IMPLEMENT_SCOSSL_RSA_SIGALG(sha1, OSSL_DIGEST_NAME_SHA1) -IMPLEMENT_SCOSSL_RSA_SIGALG(sha224, OSSL_DIGEST_NAME_SHA2_224) -IMPLEMENT_SCOSSL_RSA_SIGALG(sha256, OSSL_DIGEST_NAME_SHA2_256) -IMPLEMENT_SCOSSL_RSA_SIGALG(sha384, OSSL_DIGEST_NAME_SHA2_384) -IMPLEMENT_SCOSSL_RSA_SIGALG(sha512, OSSL_DIGEST_NAME_SHA2_512) -IMPLEMENT_SCOSSL_RSA_SIGALG(sha512_224, OSSL_DIGEST_NAME_SHA2_512_224) -IMPLEMENT_SCOSSL_RSA_SIGALG(sha512_256, OSSL_DIGEST_NAME_SHA2_512_256) -IMPLEMENT_SCOSSL_RSA_SIGALG(sha3_224, OSSL_DIGEST_NAME_SHA3_224) -IMPLEMENT_SCOSSL_RSA_SIGALG(sha3_256, OSSL_DIGEST_NAME_SHA3_256) -IMPLEMENT_SCOSSL_RSA_SIGALG(sha3_384, OSSL_DIGEST_NAME_SHA3_384) -IMPLEMENT_SCOSSL_RSA_SIGALG(sha3_512, OSSL_DIGEST_NAME_SHA3_512) - #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/SymCryptProvider/src/signature/p_scossl_rsa_signature.h b/SymCryptProvider/src/signature/p_scossl_rsa_signature.h new file mode 100644 index 00000000..d508f43d --- /dev/null +++ b/SymCryptProvider/src/signature/p_scossl_rsa_signature.h @@ -0,0 +1,69 @@ +// +// Copyright (c) Microsoft Corporation. Licensed under the MIT license. +// + +#pragma once + +#include +#include + +#include "scossl_rsa.h" +#include "p_scossl_rsa.h" +#include "p_scossl_base.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + SCOSSL_PROV_RSA_KEY_CTX *keyCtx; + UINT8 padding; + int operation; + + // Needed for fetching md + OSSL_LIB_CTX *libctx; + char* propq; + + EVP_MD_CTX *mdctx; + EVP_MD *md; + const OSSL_ITEM *mdInfo; // Informational, must match md if set + BOOL allowMdUpdates; + + // PSS params + BOOL pssRestricted; + const OSSL_ITEM *mgf1MdInfo; // Informational, must match md if set + int cbSalt; + int cbSaltMin; + + // Sigalg state tracking + BOOL isSigalg; + BOOL allowUpdate; + BOOL allowFinal; + BOOL allowOneshot; + + // Sigalg verify message support + PBYTE pbSignature; + SIZE_T cbSignature; +} SCOSSL_RSA_SIGN_CTX; + +SCOSSL_RSA_SIGN_CTX *p_scossl_rsa_newctx(_In_ SCOSSL_PROVCTX *provctx, _In_ const char *propq); +void p_scossl_rsa_freectx(_Inout_ SCOSSL_RSA_SIGN_CTX *ctx); +SCOSSL_RSA_SIGN_CTX *p_scossl_rsa_dupctx(_In_ SCOSSL_RSA_SIGN_CTX *ctx); + +SCOSSL_STATUS p_scossl_rsa_signverify_init(_Inout_ SCOSSL_RSA_SIGN_CTX *ctx, _In_ SCOSSL_PROV_RSA_KEY_CTX *keyCtx, + _In_ const OSSL_PARAM params[], int operation); + +SCOSSL_STATUS p_scossl_rsa_sign_internal(_In_ SCOSSL_RSA_SIGN_CTX *ctx, + _Out_writes_bytes_(*siglen) unsigned char *sig, _Out_ size_t *siglen, size_t sigsize, + _In_reads_bytes_(tbslen) const unsigned char *tbs, size_t tbslen); +SCOSSL_STATUS p_scossl_rsa_verify_internal(_In_ SCOSSL_RSA_SIGN_CTX *ctx, + _In_reads_bytes_(siglen) const unsigned char *sig, size_t siglen, + _In_reads_bytes_(tbslen) const unsigned char *tbs, size_t tbslen); + +const OSSL_PARAM *p_scossl_rsa_gettable_ctx_params(_In_ SCOSSL_RSA_SIGN_CTX *ctx, ossl_unused void *provctx); +SCOSSL_STATUS p_scossl_rsa_get_ctx_params(_In_ SCOSSL_RSA_SIGN_CTX *ctx, _Inout_ OSSL_PARAM params[]); + +#ifdef __cplusplus +} +#endif From 5f8d8edd639f7880a8a1b0e0e8ab42e15553deb0 Mon Sep 17 00:00:00 2001 From: Maxwell Moyer-McKee Date: Tue, 21 Apr 2026 19:19:30 +0000 Subject: [PATCH 05/12] ECDSA composite signature implementation --- .../p_scossl_ecdsa_sigalg_signature.c | 330 ++++++++++++++++++ .../src/signature/p_scossl_ecdsa_signature.c | 129 ++++--- .../src/signature/p_scossl_ecdsa_signature.h | 62 ++++ 3 files changed, 470 insertions(+), 51 deletions(-) create mode 100644 SymCryptProvider/src/signature/p_scossl_ecdsa_sigalg_signature.c create mode 100644 SymCryptProvider/src/signature/p_scossl_ecdsa_signature.h diff --git a/SymCryptProvider/src/signature/p_scossl_ecdsa_sigalg_signature.c b/SymCryptProvider/src/signature/p_scossl_ecdsa_sigalg_signature.c new file mode 100644 index 00000000..34394f19 --- /dev/null +++ b/SymCryptProvider/src/signature/p_scossl_ecdsa_sigalg_signature.c @@ -0,0 +1,330 @@ +// +// Copyright (c) Microsoft Corporation. Licensed under the MIT license. +// + +#include +#include +#include +#include + +#include "p_scossl_ecdsa_signature.h" + +#ifdef __cplusplus +extern "C" { +#endif + +static const OSSL_PARAM p_scossl_ecdsa_sigalg_ctx_settable_param_types[] = { + OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_SIGNATURE, NULL, 0), + OSSL_PARAM_END}; + +static SCOSSL_STATUS p_scossl_ecdsa_sigalg_signverify_init(_Inout_ SCOSSL_ECDSA_CTX *ctx, _In_ SCOSSL_ECC_KEY_CTX *keyCtx, + _In_ const OSSL_PARAM params[], _In_ const char *mdname, + int operation) +{ + if (!p_scossl_ecdsa_signverify_init(ctx, keyCtx, params, operation)) + { + return SCOSSL_FAILURE; + } + + EVP_MD_free(ctx->md); + + ctx->md = EVP_MD_fetch(ctx->libctx, mdname, NULL); + if (ctx->md == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST); + return SCOSSL_FAILURE; + } + + ctx->mdSize = EVP_MD_get_size(ctx->md); + ctx->allowMdUpdates = FALSE; + ctx->isSigalg = TRUE; + + return SCOSSL_SUCCESS; +} + +static SCOSSL_STATUS p_scossl_ecdsa_sigalg_message_signverify_init(_Inout_ SCOSSL_ECDSA_CTX *ctx, _In_ SCOSSL_ECC_KEY_CTX *keyCtx, + _In_ const OSSL_PARAM params[], _In_ const char *mdname, + int operation) +{ + if (!p_scossl_ecdsa_sigalg_signverify_init(ctx, keyCtx, params, mdname, operation)) + { + return SCOSSL_FAILURE; + } + + if (ctx->mdctx == NULL && + ((ctx->mdctx = EVP_MD_CTX_new()) == NULL)) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return SCOSSL_FAILURE; + } + + if (!EVP_DigestInit_ex2(ctx->mdctx, ctx->md, params)) + { + EVP_MD_CTX_free(ctx->mdctx); + ctx->mdctx = NULL; + return SCOSSL_FAILURE; + } + + return SCOSSL_SUCCESS; +} + +static SCOSSL_STATUS p_scossl_ecdsa_sigalg_signverify_message_update(_In_ SCOSSL_ECDSA_CTX *ctx, + _In_reads_bytes_(inlen) const unsigned char *in, + size_t inlen) +{ + if (ctx == NULL || ctx->mdctx == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); + return SCOSSL_FAILURE; + } + + if (!ctx->allowUpdate) + { + ERR_raise(ERR_LIB_PROV, PROV_R_UPDATE_CALL_OUT_OF_ORDER); + return SCOSSL_FAILURE; + } + + ctx->allowOneshot = FALSE; + + return EVP_DigestUpdate(ctx->mdctx, in, inlen); +} + +static SCOSSL_STATUS p_scossl_ecdsa_sigalg_sign_message_final(_In_ SCOSSL_ECDSA_CTX *ctx, + _Out_writes_bytes_opt_(*siglen) unsigned char *sig, + _Out_ size_t *siglen, size_t sigsize) +{ + BYTE digest[EVP_MAX_MD_SIZE]; + unsigned int cbDigest = 0; + + if (ctx == NULL || ctx->mdctx == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); + return SCOSSL_FAILURE; + } + + if (!ctx->allowFinal) + { + ERR_raise(ERR_LIB_PROV, PROV_R_FINAL_CALL_OUT_OF_ORDER); + return SCOSSL_FAILURE; + } + + // If sig is NULL, this is a size fetch, and the digest does not need to be computed + if (sig != NULL) + { + if (!EVP_DigestFinal_ex(ctx->mdctx, digest, &cbDigest)) + { + return SCOSSL_FAILURE; + } + + ctx->allowUpdate = FALSE; + ctx->allowOneshot = FALSE; + ctx->allowFinal = FALSE; + } + + return p_scossl_ecdsa_sign_internal(ctx, sig, siglen, sigsize, digest, cbDigest); +} + +static int p_scossl_ecdsa_sigalg_verify_message_final(_In_ SCOSSL_ECDSA_CTX *ctx) +{ + BYTE digest[EVP_MAX_MD_SIZE]; + unsigned int cbDigest = 0; + + if (ctx == NULL || ctx->mdctx == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); + return SCOSSL_FAILURE; + } + + if (!ctx->allowFinal) + { + ERR_raise(ERR_LIB_PROV, PROV_R_FINAL_CALL_OUT_OF_ORDER); + return SCOSSL_FAILURE; + } + + if (!EVP_DigestFinal_ex(ctx->mdctx, digest, &cbDigest)) + { + return SCOSSL_FAILURE; + } + + ctx->allowUpdate = FALSE; + ctx->allowFinal = FALSE; + ctx->allowOneshot = FALSE; + + return p_scossl_ecdsa_verify_internal(ctx, ctx->pbSignature, ctx->cbSignature, digest, cbDigest); +} + +static SCOSSL_STATUS p_scossl_ecdsa_sigalg_sign(_In_ SCOSSL_ECDSA_CTX *ctx, + _Out_writes_bytes_opt_(*siglen) unsigned char *sig, _Out_ size_t *siglen, size_t sigsize, + _In_reads_bytes_(tbslen) const unsigned char *tbs, size_t tbslen) +{ + if (ctx == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); + return SCOSSL_FAILURE; + } + + if (!ctx->allowOneshot) + { + ERR_raise(ERR_LIB_PROV, PROV_R_ONESHOT_CALL_OUT_OF_ORDER); + return SCOSSL_FAILURE; + } + + if (ctx->operation == EVP_PKEY_OP_SIGNMSG) + { + // If sig is NULL, the caller is only looking for the sig length. + // Do not update the input in this case. + if (sig == NULL) + { + return p_scossl_ecdsa_sigalg_sign_message_final(ctx, sig, siglen, sigsize); + } + + return p_scossl_ecdsa_sigalg_signverify_message_update(ctx, tbs, tbslen) && + p_scossl_ecdsa_sigalg_sign_message_final(ctx, sig, siglen, sigsize); + } + + return p_scossl_ecdsa_sign_internal(ctx, sig, siglen, sigsize, tbs, tbslen); +} + +static int p_scossl_ecdsa_sigalg_verify(_In_ SCOSSL_ECDSA_CTX *ctx, + _In_reads_bytes_(siglen) const unsigned char *sig, size_t siglen, + _In_reads_bytes_(tbslen) const unsigned char *tbs, size_t tbslen) +{ + if (ctx == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); + return -1; + } + + if (!ctx->allowOneshot) + { + ERR_raise(ERR_LIB_PROV, PROV_R_ONESHOT_CALL_OUT_OF_ORDER); + return -1; + } + + if (ctx->operation == EVP_PKEY_OP_VERIFYMSG) + { + OPENSSL_free(ctx->pbSignature); + ctx->cbSignature = 0; + + if ((ctx->pbSignature = OPENSSL_memdup(sig, siglen)) == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return -1; + } + ctx->cbSignature = siglen; + + return p_scossl_ecdsa_sigalg_signverify_message_update(ctx, tbs, tbslen) && + p_scossl_ecdsa_sigalg_verify_message_final(ctx); + } + + return p_scossl_ecdsa_verify_internal(ctx, sig, siglen, tbs, tbslen); +} + +static const OSSL_PARAM *p_scossl_ecdsa_sigalg_settable_ctx_params(_In_ SCOSSL_ECDSA_CTX *ctx, + ossl_unused void *provctx) +{ + if (ctx != NULL && ctx->operation == EVP_PKEY_OP_VERIFYMSG) + { + return p_scossl_ecdsa_sigalg_ctx_settable_param_types; + } + + return NULL; +} + +static SCOSSL_STATUS p_scossl_ecdsa_sigalg_set_ctx_params(_Inout_ SCOSSL_ECDSA_CTX *ctx, + _In_ const OSSL_PARAM params[]) +{ + const OSSL_PARAM *p; + + if (ctx == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); + return SCOSSL_FAILURE; + } + + if (ctx->operation == EVP_PKEY_OP_VERIFYMSG) + { + if ((p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_SIGNATURE)) != NULL) + { + OPENSSL_free(ctx->pbSignature); + ctx->pbSignature = NULL; + ctx->cbSignature = 0; + if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->pbSignature, 0, &ctx->cbSignature)) + { + return SCOSSL_FAILURE; + } + } + } + + return SCOSSL_SUCCESS; +} + +static const char **p_scossl_ecdsa_sigalg_query_key_types(void) +{ + static const char *keyTypes[] = { "EC", NULL }; + return keyTypes; +} + +#define IMPL_SCOSSL_ECDSA_SIGALG(md, MD) \ + static SCOSSL_STATUS p_scossl_ecdsa_##md##_sign_init(_Inout_ SCOSSL_ECDSA_CTX *ctx, \ + _In_ SCOSSL_ECC_KEY_CTX *keyCtx, \ + _In_ const OSSL_PARAM params[]) \ + { \ + return p_scossl_ecdsa_sigalg_signverify_init(ctx, keyCtx, params, MD, EVP_PKEY_OP_SIGN); \ + } \ + \ + static SCOSSL_STATUS p_scossl_ecdsa_##md##_verify_init(_Inout_ SCOSSL_ECDSA_CTX *ctx, \ + _In_ SCOSSL_ECC_KEY_CTX *keyCtx, \ + _In_ const OSSL_PARAM params[]) \ + { \ + return p_scossl_ecdsa_sigalg_signverify_init(ctx, keyCtx, params, MD, EVP_PKEY_OP_VERIFY); \ + } \ + \ + static SCOSSL_STATUS p_scossl_ecdsa_##md##_sign_message_init(_Inout_ SCOSSL_ECDSA_CTX *ctx, \ + _In_ SCOSSL_ECC_KEY_CTX *keyCtx, \ + _In_ const OSSL_PARAM params[]) \ + { \ + return p_scossl_ecdsa_sigalg_message_signverify_init(ctx, keyCtx, params, MD, EVP_PKEY_OP_SIGNMSG); \ + } \ + \ + static SCOSSL_STATUS p_scossl_ecdsa_##md##_verify_message_init(_Inout_ SCOSSL_ECDSA_CTX *ctx, \ + _In_ SCOSSL_ECC_KEY_CTX *keyCtx, \ + _In_ const OSSL_PARAM params[]) \ + { \ + return p_scossl_ecdsa_sigalg_message_signverify_init(ctx, keyCtx, params, MD, EVP_PKEY_OP_VERIFYMSG); \ + } \ + \ + const OSSL_DISPATCH p_scossl_ecdsa_##md##_signature_functions[] = { \ + {OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))p_scossl_ecdsa_newctx}, \ + {OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))p_scossl_ecdsa_dupctx}, \ + {OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))p_scossl_ecdsa_freectx}, \ + {OSSL_FUNC_SIGNATURE_SIGN_INIT, (void (*)(void))p_scossl_ecdsa_##md##_sign_init}, \ + {OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))p_scossl_ecdsa_sigalg_sign}, \ + {OSSL_FUNC_SIGNATURE_SIGN_MESSAGE_INIT, (void (*)(void))p_scossl_ecdsa_##md##_sign_message_init}, \ + {OSSL_FUNC_SIGNATURE_SIGN_MESSAGE_UPDATE, (void (*)(void))p_scossl_ecdsa_sigalg_signverify_message_update}, \ + {OSSL_FUNC_SIGNATURE_SIGN_MESSAGE_FINAL, (void (*)(void))p_scossl_ecdsa_sigalg_sign_message_final}, \ + {OSSL_FUNC_SIGNATURE_VERIFY_INIT, (void (*)(void))p_scossl_ecdsa_##md##_verify_init}, \ + {OSSL_FUNC_SIGNATURE_VERIFY, (void (*)(void))p_scossl_ecdsa_sigalg_verify}, \ + {OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_INIT, (void (*)(void))p_scossl_ecdsa_##md##_verify_message_init}, \ + {OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_UPDATE, (void (*)(void))p_scossl_ecdsa_sigalg_signverify_message_update}, \ + {OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_FINAL, (void (*)(void))p_scossl_ecdsa_sigalg_verify_message_final},\ + {OSSL_FUNC_SIGNATURE_QUERY_KEY_TYPES, (void (*)(void))p_scossl_ecdsa_sigalg_query_key_types}, \ + {OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))p_scossl_ecdsa_get_ctx_params}, \ + {OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_ecdsa_gettable_ctx_params}, \ + {OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, (void (*)(void))p_scossl_ecdsa_sigalg_set_ctx_params}, \ + {OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS, (void (*)(void))p_scossl_ecdsa_sigalg_settable_ctx_params}, \ + {0, NULL}}; + +IMPL_SCOSSL_ECDSA_SIGALG(sha1, OSSL_DIGEST_NAME_SHA1) +IMPL_SCOSSL_ECDSA_SIGALG(sha224, OSSL_DIGEST_NAME_SHA2_224) +IMPL_SCOSSL_ECDSA_SIGALG(sha256, OSSL_DIGEST_NAME_SHA2_256) +IMPL_SCOSSL_ECDSA_SIGALG(sha384, OSSL_DIGEST_NAME_SHA2_384) +IMPL_SCOSSL_ECDSA_SIGALG(sha512, OSSL_DIGEST_NAME_SHA2_512) +IMPL_SCOSSL_ECDSA_SIGALG(sha3_224, OSSL_DIGEST_NAME_SHA3_224) +IMPL_SCOSSL_ECDSA_SIGALG(sha3_256, OSSL_DIGEST_NAME_SHA3_256) +IMPL_SCOSSL_ECDSA_SIGALG(sha3_384, OSSL_DIGEST_NAME_SHA3_384) +IMPL_SCOSSL_ECDSA_SIGALG(sha3_512, OSSL_DIGEST_NAME_SHA3_512) + +#ifdef __cplusplus +} +#endif diff --git a/SymCryptProvider/src/signature/p_scossl_ecdsa_signature.c b/SymCryptProvider/src/signature/p_scossl_ecdsa_signature.c index f455901a..36bcbb2f 100644 --- a/SymCryptProvider/src/signature/p_scossl_ecdsa_signature.c +++ b/SymCryptProvider/src/signature/p_scossl_ecdsa_signature.c @@ -2,31 +2,15 @@ // Copyright (c) Microsoft Corporation. Licensed under the MIT license. // -#include "scossl_ecc.h" -#include "p_scossl_ecc.h" -#include "p_scossl_base.h" +#include "p_scossl_ecdsa_signature.h" +#include #include #ifdef __cplusplus extern "C" { #endif -typedef struct -{ - SCOSSL_ECC_KEY_CTX *keyCtx; - int operation; - - // Needed for fetching md - OSSL_LIB_CTX *libctx; - char* propq; - - EVP_MD_CTX *mdctx; - EVP_MD *md; - SIZE_T mdSize; - BOOL allowMdUpdates; -} SCOSSL_ECDSA_CTX; - static const OSSL_PARAM p_scossl_ecdsa_ctx_gettable_param_types[] = { OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0), OSSL_PARAM_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, NULL), @@ -45,7 +29,8 @@ static const OSSL_PARAM p_scossl_ecdsa_ctx_settable_param_types_no_digest[] = { static SCOSSL_STATUS p_scossl_ecdsa_set_ctx_params(_Inout_ SCOSSL_ECDSA_CTX *ctx, _In_ const OSSL_PARAM params[]); -static SCOSSL_ECDSA_CTX *p_scossl_ecdsa_newctx(_In_ SCOSSL_PROVCTX *provctx, _In_ const char *propq) +_Use_decl_annotations_ +SCOSSL_ECDSA_CTX *p_scossl_ecdsa_newctx(SCOSSL_PROVCTX *provctx, const char *propq) { SCOSSL_ECDSA_CTX *ctx = OPENSSL_zalloc(sizeof(SCOSSL_ECDSA_CTX)); if (ctx != NULL) @@ -64,7 +49,7 @@ static SCOSSL_ECDSA_CTX *p_scossl_ecdsa_newctx(_In_ SCOSSL_PROVCTX *provctx, _In return ctx; } -static void p_scossl_ecdsa_freectx(SCOSSL_ECDSA_CTX *ctx) +void p_scossl_ecdsa_freectx(SCOSSL_ECDSA_CTX *ctx) { if (ctx == NULL) return; @@ -72,10 +57,12 @@ static void p_scossl_ecdsa_freectx(SCOSSL_ECDSA_CTX *ctx) EVP_MD_CTX_free(ctx->mdctx); EVP_MD_free(ctx->md); OPENSSL_free(ctx->propq); + OPENSSL_free(ctx->pbSignature); OPENSSL_free(ctx); } -static SCOSSL_ECDSA_CTX *p_scossl_ecdsa_dupctx(_In_ SCOSSL_ECDSA_CTX *ctx) +_Use_decl_annotations_ +SCOSSL_ECDSA_CTX *p_scossl_ecdsa_dupctx(SCOSSL_ECDSA_CTX *ctx) { SCOSSL_ECDSA_CTX *copyCtx = OPENSSL_zalloc(sizeof(SCOSSL_ECDSA_CTX)); if (copyCtx != NULL) @@ -86,22 +73,27 @@ static SCOSSL_ECDSA_CTX *p_scossl_ecdsa_dupctx(_In_ SCOSSL_ECDSA_CTX *ctx) { p_scossl_ecdsa_freectx(copyCtx); ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - copyCtx = NULL; + return NULL; } copyCtx->keyCtx = ctx->keyCtx; copyCtx->operation = ctx->operation; copyCtx->libctx = ctx->libctx; copyCtx->md = ctx->md; - ctx->mdSize = ctx->mdSize; + copyCtx->mdSize = ctx->mdSize; copyCtx->allowMdUpdates = ctx->allowMdUpdates; + copyCtx->isSigalg = ctx->isSigalg; + copyCtx->allowUpdate = ctx->allowUpdate; + copyCtx->allowFinal = ctx->allowFinal; + copyCtx->allowOneshot = ctx->allowOneshot; } return copyCtx; } -static SCOSSL_STATUS p_scossl_ecdsa_signverify_init(_Inout_ SCOSSL_ECDSA_CTX *ctx, _In_ SCOSSL_ECC_KEY_CTX *keyCtx, - _In_ const OSSL_PARAM params[], int operation) +_Use_decl_annotations_ +SCOSSL_STATUS p_scossl_ecdsa_signverify_init(SCOSSL_ECDSA_CTX *ctx, SCOSSL_ECC_KEY_CTX *keyCtx, + const OSSL_PARAM params[], int operation) { if (ctx == NULL || (keyCtx == NULL && ctx->keyCtx == NULL)) @@ -111,6 +103,10 @@ static SCOSSL_STATUS p_scossl_ecdsa_signverify_init(_Inout_ SCOSSL_ECDSA_CTX *ct } ctx->operation = operation; + ctx->isSigalg = FALSE; + ctx->allowUpdate = TRUE; + ctx->allowFinal = TRUE; + ctx->allowOneshot = TRUE; if (keyCtx != NULL) { @@ -123,7 +119,7 @@ static SCOSSL_STATUS p_scossl_ecdsa_signverify_init(_Inout_ SCOSSL_ECDSA_CTX *ct ctx->keyCtx = keyCtx; #ifdef KEYSINUSE_ENABLED if (keysinuse_is_running() && - operation == EVP_PKEY_OP_SIGN) + (operation == EVP_PKEY_OP_SIGN || operation == EVP_PKEY_OP_SIGNMSG)) { p_scossl_ecc_init_keysinuse(keyCtx); } @@ -144,10 +140,10 @@ static SCOSSL_STATUS p_scossl_ecdsa_verify_init(_Inout_ SCOSSL_ECDSA_CTX *ctx, _ { return p_scossl_ecdsa_signverify_init(ctx, keyCtx, params, EVP_PKEY_OP_VERIFY); } - -static SCOSSL_STATUS p_scossl_ecdsa_sign(_In_ SCOSSL_ECDSA_CTX *ctx, - _Out_writes_bytes_(*siglen) unsigned char *sig, _Out_ size_t *siglen, size_t sigsize, - _In_reads_bytes_(tbslen) const unsigned char *tbs, size_t tbslen) +_Use_decl_annotations_ +SCOSSL_STATUS p_scossl_ecdsa_sign_internal(SCOSSL_ECDSA_CTX *ctx, + unsigned char *sig, size_t *siglen, size_t sigsize, + const unsigned char *tbs, size_t tbslen) { SIZE_T cbResult; @@ -157,12 +153,6 @@ static SCOSSL_STATUS p_scossl_ecdsa_sign(_In_ SCOSSL_ECDSA_CTX *ctx, return SCOSSL_FAILURE; } - if (ctx->operation != EVP_PKEY_OP_SIGN) - { - ERR_raise(ERR_LIB_PROV, ERR_R_OPERATION_FAIL); - return SCOSSL_FAILURE; - } - if (siglen == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); @@ -204,9 +194,10 @@ static SCOSSL_STATUS p_scossl_ecdsa_sign(_In_ SCOSSL_ECDSA_CTX *ctx, // 1 (SCOSSL_SUCCESS) for valid signature // 0 (SCOSSL_FAILURE) for invalid signature // -1 for error -static int p_scossl_ecdsa_verify(_In_ SCOSSL_ECDSA_CTX *ctx, - _In_reads_bytes_(siglen) const unsigned char *sig, size_t siglen, - _In_reads_bytes_(tbslen) const unsigned char *tbs, size_t tbslen) +_Use_decl_annotations_ +int p_scossl_ecdsa_verify_internal(SCOSSL_ECDSA_CTX *ctx, + const unsigned char *sig, size_t siglen, + const unsigned char *tbs, size_t tbslen) { if (ctx == NULL || ctx->keyCtx == NULL) { @@ -214,12 +205,6 @@ static int p_scossl_ecdsa_verify(_In_ SCOSSL_ECDSA_CTX *ctx, return -1; } - if (ctx->operation != EVP_PKEY_OP_VERIFY) - { - ERR_raise(ERR_LIB_PROV, ERR_R_OPERATION_FAIL); - return -1; - } - return scossl_ecdsa_verify(ctx->keyCtx->key, ctx->keyCtx->curve, tbs, tbslen, sig, siglen); } @@ -282,7 +267,7 @@ static SCOSSL_STATUS p_scossl_ecdsa_digest_signverify_update(_In_ SCOSSL_ECDSA_C } static SCOSSL_STATUS p_scossl_ecdsa_digest_sign_final(_In_ SCOSSL_ECDSA_CTX *ctx, - _Out_writes_bytes_(*siglen) unsigned char *sig, _Out_ size_t *siglen, size_t sigsize) + _Out_writes_bytes_opt_(*siglen) unsigned char *sig, _Out_ size_t *siglen, size_t sigsize) { BYTE digest[EVP_MAX_MD_SIZE]; unsigned int cbDigest = 0; @@ -303,7 +288,7 @@ static SCOSSL_STATUS p_scossl_ecdsa_digest_sign_final(_In_ SCOSSL_ECDSA_CTX *ctx } } - return p_scossl_ecdsa_sign(ctx, sig, siglen, sigsize, digest, cbDigest); + return p_scossl_ecdsa_sign_internal(ctx, sig, siglen, sigsize, digest, cbDigest); } static int p_scossl_ecdsa_digest_verify_final(_In_ SCOSSL_ECDSA_CTX *ctx, @@ -324,7 +309,47 @@ static int p_scossl_ecdsa_digest_verify_final(_In_ SCOSSL_ECDSA_CTX *ctx, return 0; } - return p_scossl_ecdsa_verify(ctx, sig, siglen, digest, cbDigest); + return p_scossl_ecdsa_verify_internal(ctx, sig, siglen, digest, cbDigest); +} + +static SCOSSL_STATUS p_scossl_ecdsa_sign(_In_ SCOSSL_ECDSA_CTX *ctx, + _Out_writes_bytes_opt_(*siglen) unsigned char *sig, _Out_ size_t *siglen, size_t sigsize, + _In_reads_bytes_(tbslen) const unsigned char *tbs, size_t tbslen) +{ + if (ctx == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); + return SCOSSL_FAILURE; + } + + if (!ctx->allowOneshot) + { + ERR_raise(ERR_LIB_PROV, PROV_R_ONESHOT_CALL_OUT_OF_ORDER); + return SCOSSL_FAILURE; + } + + return p_scossl_ecdsa_sign_internal(ctx, sig, siglen, sigsize, tbs, tbslen); +} + +// Generic dispatch one-shot verify. Enforces oneshot state before delegating +// to the primitive. +static int p_scossl_ecdsa_verify(_In_ SCOSSL_ECDSA_CTX *ctx, + _In_reads_bytes_(siglen) const unsigned char *sig, size_t siglen, + _In_reads_bytes_(tbslen) const unsigned char *tbs, size_t tbslen) +{ + if (ctx == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); + return -1; + } + + if (!ctx->allowOneshot) + { + ERR_raise(ERR_LIB_PROV, PROV_R_ONESHOT_CALL_OUT_OF_ORDER); + return -1; + } + + return p_scossl_ecdsa_verify_internal(ctx, sig, siglen, tbs, tbslen); } static const OSSL_PARAM *p_scossl_ecdsa_settable_ctx_params(_In_ SCOSSL_ECDSA_CTX *ctx, @@ -393,13 +418,15 @@ static SCOSSL_STATUS p_scossl_ecdsa_set_ctx_params(_Inout_ SCOSSL_ECDSA_CTX *ctx return SCOSSL_SUCCESS; } -static const OSSL_PARAM *p_scossl_ecdsa_gettable_ctx_params(ossl_unused void *ctx, - ossl_unused void *provctx) +_Use_decl_annotations_ +const OSSL_PARAM *p_scossl_ecdsa_gettable_ctx_params(ossl_unused void *ctx, + ossl_unused void *provctx) { return p_scossl_ecdsa_ctx_gettable_param_types; } -static SCOSSL_STATUS p_scossl_ecdsa_get_ctx_params(_In_ SCOSSL_ECDSA_CTX *ctx, _Inout_ OSSL_PARAM params[]) +_Use_decl_annotations_ +SCOSSL_STATUS p_scossl_ecdsa_get_ctx_params(SCOSSL_ECDSA_CTX *ctx, OSSL_PARAM params[]) { if (params == NULL) { diff --git a/SymCryptProvider/src/signature/p_scossl_ecdsa_signature.h b/SymCryptProvider/src/signature/p_scossl_ecdsa_signature.h new file mode 100644 index 00000000..e09b2e10 --- /dev/null +++ b/SymCryptProvider/src/signature/p_scossl_ecdsa_signature.h @@ -0,0 +1,62 @@ +// +// Copyright (c) Microsoft Corporation. Licensed under the MIT license. +// + +#pragma once + +#include +#include + +#include "scossl_ecc.h" +#include "p_scossl_ecc.h" +#include "p_scossl_base.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + SCOSSL_ECC_KEY_CTX *keyCtx; + int operation; + + // Needed for fetching md + OSSL_LIB_CTX *libctx; + char* propq; + + EVP_MD_CTX *mdctx; + EVP_MD *md; + SIZE_T mdSize; + BOOL allowMdUpdates; + + // Sigalg state tracking + BOOL isSigalg; + BOOL allowUpdate; + BOOL allowFinal; + BOOL allowOneshot; + + // Sigalg verify message support + PBYTE pbSignature; + SIZE_T cbSignature; +} SCOSSL_ECDSA_CTX; + +SCOSSL_ECDSA_CTX *p_scossl_ecdsa_newctx(_In_ SCOSSL_PROVCTX *provctx, _In_ const char *propq); +void p_scossl_ecdsa_freectx(_Inout_ SCOSSL_ECDSA_CTX *ctx); +SCOSSL_ECDSA_CTX *p_scossl_ecdsa_dupctx(_In_ SCOSSL_ECDSA_CTX *ctx); + +SCOSSL_STATUS p_scossl_ecdsa_signverify_init(_Inout_ SCOSSL_ECDSA_CTX *ctx, _In_ SCOSSL_ECC_KEY_CTX *keyCtx, + _In_ const OSSL_PARAM params[], int operation); + +SCOSSL_STATUS p_scossl_ecdsa_sign_internal(_In_ SCOSSL_ECDSA_CTX *ctx, + _Out_writes_bytes_opt_(*siglen) unsigned char *sig, _Out_ size_t *siglen, size_t sigsize, + _In_reads_bytes_(tbslen) const unsigned char *tbs, size_t tbslen); +int p_scossl_ecdsa_verify_internal(_In_ SCOSSL_ECDSA_CTX *ctx, + _In_reads_bytes_(siglen) const unsigned char *sig, size_t siglen, + _In_reads_bytes_(tbslen) const unsigned char *tbs, size_t tbslen); + +const OSSL_PARAM *p_scossl_ecdsa_gettable_ctx_params(ossl_unused void *ctx, ossl_unused void *provctx); +SCOSSL_STATUS p_scossl_ecdsa_get_ctx_params(_In_ SCOSSL_ECDSA_CTX *ctx, _Inout_ OSSL_PARAM params[]); + +#ifdef __cplusplus +} +#endif From 5c30eb91a5812c13fdd9814bcc1c12b6879f0f07 Mon Sep 17 00:00:00 2001 From: Maxwell Moyer-McKee Date: Tue, 21 Apr 2026 19:19:45 +0000 Subject: [PATCH 06/12] Clean up RSA --- SymCryptProvider/CMakeLists.txt | 2 ++ .../src/signature/p_scossl_rsa_sigalg_signature.c | 12 ++++++------ .../src/signature/p_scossl_rsa_signature.c | 4 ++-- .../src/signature/p_scossl_rsa_signature.h | 2 +- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/SymCryptProvider/CMakeLists.txt b/SymCryptProvider/CMakeLists.txt index 18f7bb2c..7e8471cf 100644 --- a/SymCryptProvider/CMakeLists.txt +++ b/SymCryptProvider/CMakeLists.txt @@ -51,7 +51,9 @@ set(SCOSSL_SOURCES ./src/mac/p_scossl_hmac.c ./src/mac/p_scossl_kmac.c ./src/signature/p_scossl_ecdsa_signature.c + ./src/signature/p_scossl_ecdsa_sigalg_signature.c ./src/signature/p_scossl_rsa_signature.c + ./src/signature/p_scossl_rsa_sigalg_signature.c ./src/skeymgmt/p_scossl_aes_skeymgmt.c ./src/skeymgmt/p_scossl_generic_skeymgmt.c ./src/p_scossl_bio.c diff --git a/SymCryptProvider/src/signature/p_scossl_rsa_sigalg_signature.c b/SymCryptProvider/src/signature/p_scossl_rsa_sigalg_signature.c index cac5ff25..b56d356b 100644 --- a/SymCryptProvider/src/signature/p_scossl_rsa_sigalg_signature.c +++ b/SymCryptProvider/src/signature/p_scossl_rsa_sigalg_signature.c @@ -82,8 +82,8 @@ static SCOSSL_STATUS p_scossl_rsa_sigalg_signverify_message_init(_Inout_ SCOSSL_ } static SCOSSL_STATUS p_scossl_rsa_sigalg_signverify_message_update(_In_ SCOSSL_RSA_SIGN_CTX *ctx, - _In_reads_bytes_(datalen) const unsigned char *data, - size_t datalen) + _In_reads_bytes_(inlen) const unsigned char *in, + size_t inlen) { if (ctx == NULL || ctx->mdctx == NULL) { @@ -99,7 +99,7 @@ static SCOSSL_STATUS p_scossl_rsa_sigalg_signverify_message_update(_In_ SCOSSL_R ctx->allowOneshot = 0; - return EVP_DigestUpdate(ctx->mdctx, data, datalen); + return EVP_DigestUpdate(ctx->mdctx, in, inlen); } static SCOSSL_STATUS p_scossl_rsa_sigalg_sign_message_final(_In_ SCOSSL_RSA_SIGN_CTX *ctx, @@ -166,12 +166,12 @@ static int p_scossl_rsa_sigalg_verify_message_final(_In_ SCOSSL_RSA_SIGN_CTX *ct } static SCOSSL_STATUS p_scossl_rsa_sigalg_sign(_In_ SCOSSL_RSA_SIGN_CTX *ctx, - _Out_writes_bytes_(*siglen) unsigned char *sig, _Out_ size_t *siglen, size_t sigsize, + _Out_writes_bytes_opt_(*siglen) unsigned char *sig, _Out_ size_t *siglen, size_t sigsize, _In_reads_bytes_(tbslen) const unsigned char *tbs, size_t tbslen) { if (ctx == NULL) { - ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); return SCOSSL_FAILURE; } @@ -201,7 +201,7 @@ static SCOSSL_STATUS p_scossl_rsa_sigalg_verify(_In_ SCOSSL_RSA_SIGN_CTX *ctx, { if (ctx == NULL) { - ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); return SCOSSL_FAILURE; } diff --git a/SymCryptProvider/src/signature/p_scossl_rsa_signature.c b/SymCryptProvider/src/signature/p_scossl_rsa_signature.c index f837de5c..959f3d31 100644 --- a/SymCryptProvider/src/signature/p_scossl_rsa_signature.c +++ b/SymCryptProvider/src/signature/p_scossl_rsa_signature.c @@ -391,7 +391,7 @@ static SCOSSL_STATUS p_scossl_rsa_digest_signverify_update(_In_ SCOSSL_RSA_SIGN_ } static SCOSSL_STATUS p_scossl_rsa_digest_sign_final(_In_ SCOSSL_RSA_SIGN_CTX *ctx, - _Out_writes_bytes_(*siglen) unsigned char *sig, _Out_ size_t *siglen, size_t sigsize) + _Out_writes_bytes_opt_(*siglen) unsigned char *sig, _Out_ size_t *siglen, size_t sigsize) { SCOSSL_STATUS ret = SCOSSL_FAILURE; BYTE digest[EVP_MAX_MD_SIZE]; @@ -477,7 +477,7 @@ static SCOSSL_STATUS p_scossl_rsa_digest_verify_final(_In_ SCOSSL_RSA_SIGN_CTX * } static SCOSSL_STATUS p_scossl_rsa_sign(_In_ SCOSSL_RSA_SIGN_CTX *ctx, - _Out_writes_bytes_(*siglen) unsigned char *sig, _Out_ size_t *siglen, size_t sigsize, + _Out_writes_bytes_opt_(*siglen) unsigned char *sig, _Out_ size_t *siglen, size_t sigsize, _In_reads_bytes_(tbslen) const unsigned char *tbs, size_t tbslen) { if (ctx == NULL) diff --git a/SymCryptProvider/src/signature/p_scossl_rsa_signature.h b/SymCryptProvider/src/signature/p_scossl_rsa_signature.h index d508f43d..db3f8263 100644 --- a/SymCryptProvider/src/signature/p_scossl_rsa_signature.h +++ b/SymCryptProvider/src/signature/p_scossl_rsa_signature.h @@ -55,7 +55,7 @@ SCOSSL_STATUS p_scossl_rsa_signverify_init(_Inout_ SCOSSL_RSA_SIGN_CTX *ctx, _In _In_ const OSSL_PARAM params[], int operation); SCOSSL_STATUS p_scossl_rsa_sign_internal(_In_ SCOSSL_RSA_SIGN_CTX *ctx, - _Out_writes_bytes_(*siglen) unsigned char *sig, _Out_ size_t *siglen, size_t sigsize, + _Out_writes_bytes_opt_(*siglen) unsigned char *sig, _Out_ size_t *siglen, size_t sigsize, _In_reads_bytes_(tbslen) const unsigned char *tbs, size_t tbslen); SCOSSL_STATUS p_scossl_rsa_verify_internal(_In_ SCOSSL_RSA_SIGN_CTX *ctx, _In_reads_bytes_(siglen) const unsigned char *sig, size_t siglen, From dd3976b9c4d2fa1eed8456d70b312231ce39cd90 Mon Sep 17 00:00:00 2001 From: Maxwell Moyer-McKee Date: Tue, 21 Apr 2026 21:28:11 +0000 Subject: [PATCH 07/12] Cleanup --- .../p_scossl_ecdsa_sigalg_signature.c | 24 +++++++++++++++---- .../src/signature/p_scossl_ecdsa_signature.c | 10 +++++--- .../signature/p_scossl_rsa_sigalg_signature.c | 16 +++++++++---- .../src/signature/p_scossl_rsa_signature.c | 5 ++-- 4 files changed, 42 insertions(+), 13 deletions(-) diff --git a/SymCryptProvider/src/signature/p_scossl_ecdsa_sigalg_signature.c b/SymCryptProvider/src/signature/p_scossl_ecdsa_sigalg_signature.c index 34394f19..0bb416a3 100644 --- a/SymCryptProvider/src/signature/p_scossl_ecdsa_sigalg_signature.c +++ b/SymCryptProvider/src/signature/p_scossl_ecdsa_sigalg_signature.c @@ -124,6 +124,10 @@ static SCOSSL_STATUS p_scossl_ecdsa_sigalg_sign_message_final(_In_ SCOSSL_ECDSA_ return p_scossl_ecdsa_sign_internal(ctx, sig, siglen, sigsize, digest, cbDigest); } +// Return +// 1 (SCOSSL_SUCCESS) for valid signature +// 0 (SCOSSL_FAILURE) for invalid signature +// -1 for error static int p_scossl_ecdsa_sigalg_verify_message_final(_In_ SCOSSL_ECDSA_CTX *ctx) { BYTE digest[EVP_MAX_MD_SIZE]; @@ -178,13 +182,21 @@ static SCOSSL_STATUS p_scossl_ecdsa_sigalg_sign(_In_ SCOSSL_ECDSA_CTX *ctx, return p_scossl_ecdsa_sigalg_sign_message_final(ctx, sig, siglen, sigsize); } - return p_scossl_ecdsa_sigalg_signverify_message_update(ctx, tbs, tbslen) && - p_scossl_ecdsa_sigalg_sign_message_final(ctx, sig, siglen, sigsize); + if (p_scossl_ecdsa_sigalg_signverify_message_update(ctx, tbs, tbslen) <= 0) + { + return SCOSSL_FAILURE; + } + + return p_scossl_ecdsa_sigalg_sign_message_final(ctx, sig, siglen, sigsize); } return p_scossl_ecdsa_sign_internal(ctx, sig, siglen, sigsize, tbs, tbslen); } +// Return +// 1 (SCOSSL_SUCCESS) for valid signature +// 0 (SCOSSL_FAILURE) for invalid signature +// -1 for error static int p_scossl_ecdsa_sigalg_verify(_In_ SCOSSL_ECDSA_CTX *ctx, _In_reads_bytes_(siglen) const unsigned char *sig, size_t siglen, _In_reads_bytes_(tbslen) const unsigned char *tbs, size_t tbslen) @@ -213,8 +225,12 @@ static int p_scossl_ecdsa_sigalg_verify(_In_ SCOSSL_ECDSA_CTX *ctx, } ctx->cbSignature = siglen; - return p_scossl_ecdsa_sigalg_signverify_message_update(ctx, tbs, tbslen) && - p_scossl_ecdsa_sigalg_verify_message_final(ctx); + if (p_scossl_ecdsa_sigalg_signverify_message_update(ctx, tbs, tbslen) <= 0) + { + return 0; + } + + return p_scossl_ecdsa_sigalg_verify_message_final(ctx); } return p_scossl_ecdsa_verify_internal(ctx, sig, siglen, tbs, tbslen); diff --git a/SymCryptProvider/src/signature/p_scossl_ecdsa_signature.c b/SymCryptProvider/src/signature/p_scossl_ecdsa_signature.c index 36bcbb2f..c697f25a 100644 --- a/SymCryptProvider/src/signature/p_scossl_ecdsa_signature.c +++ b/SymCryptProvider/src/signature/p_scossl_ecdsa_signature.c @@ -69,7 +69,8 @@ SCOSSL_ECDSA_CTX *p_scossl_ecdsa_dupctx(SCOSSL_ECDSA_CTX *ctx) { if ((ctx->propq != NULL && ((copyCtx->propq = OPENSSL_strdup(ctx->propq)) == NULL)) || (ctx->mdctx != NULL && ((copyCtx->mdctx = EVP_MD_CTX_dup((const EVP_MD_CTX *)ctx->mdctx)) == NULL)) || - (ctx->md != NULL && !EVP_MD_up_ref(ctx->md))) + (ctx->md != NULL && !EVP_MD_up_ref(ctx->md)) || + (ctx->pbSignature != NULL && ((copyCtx->pbSignature = OPENSSL_memdup(ctx->pbSignature, ctx->cbSignature)) == NULL))) { p_scossl_ecdsa_freectx(copyCtx); ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); @@ -86,6 +87,7 @@ SCOSSL_ECDSA_CTX *p_scossl_ecdsa_dupctx(SCOSSL_ECDSA_CTX *ctx) copyCtx->allowUpdate = ctx->allowUpdate; copyCtx->allowFinal = ctx->allowFinal; copyCtx->allowOneshot = ctx->allowOneshot; + copyCtx->cbSignature = ctx->cbSignature; } return copyCtx; @@ -331,8 +333,10 @@ static SCOSSL_STATUS p_scossl_ecdsa_sign(_In_ SCOSSL_ECDSA_CTX *ctx, return p_scossl_ecdsa_sign_internal(ctx, sig, siglen, sigsize, tbs, tbslen); } -// Generic dispatch one-shot verify. Enforces oneshot state before delegating -// to the primitive. +// Return +// 1 (SCOSSL_SUCCESS) for valid signature +// 0 (SCOSSL_FAILURE) for invalid signature +// -1 for error static int p_scossl_ecdsa_verify(_In_ SCOSSL_ECDSA_CTX *ctx, _In_reads_bytes_(siglen) const unsigned char *sig, size_t siglen, _In_reads_bytes_(tbslen) const unsigned char *tbs, size_t tbslen) diff --git a/SymCryptProvider/src/signature/p_scossl_rsa_sigalg_signature.c b/SymCryptProvider/src/signature/p_scossl_rsa_sigalg_signature.c index b56d356b..1b3551da 100644 --- a/SymCryptProvider/src/signature/p_scossl_rsa_sigalg_signature.c +++ b/SymCryptProvider/src/signature/p_scossl_rsa_sigalg_signature.c @@ -188,8 +188,12 @@ static SCOSSL_STATUS p_scossl_rsa_sigalg_sign(_In_ SCOSSL_RSA_SIGN_CTX *ctx, return p_scossl_rsa_sigalg_sign_message_final(ctx, sig, siglen, sigsize); } - return p_scossl_rsa_sigalg_signverify_message_update(ctx, tbs, tbslen) && - p_scossl_rsa_sigalg_sign_message_final(ctx, sig, siglen, sigsize); + if (p_scossl_rsa_sigalg_signverify_message_update(ctx, tbs, tbslen) != SCOSSL_SUCCESS) + { + return SCOSSL_FAILURE; + } + + return p_scossl_rsa_sigalg_sign_message_final(ctx, sig, siglen, sigsize); } return p_scossl_rsa_sign_internal(ctx, sig, siglen, sigsize, tbs, tbslen); @@ -223,8 +227,12 @@ static SCOSSL_STATUS p_scossl_rsa_sigalg_verify(_In_ SCOSSL_RSA_SIGN_CTX *ctx, } ctx->cbSignature = siglen; - return p_scossl_rsa_sigalg_signverify_message_update(ctx, tbs, tbslen) && - p_scossl_rsa_sigalg_verify_message_final(ctx); + if (p_scossl_rsa_sigalg_signverify_message_update(ctx, tbs, tbslen) != SCOSSL_SUCCESS) + { + return SCOSSL_FAILURE; + } + + return p_scossl_rsa_sigalg_verify_message_final(ctx); } return p_scossl_rsa_verify_internal(ctx, sig, siglen, tbs, tbslen); diff --git a/SymCryptProvider/src/signature/p_scossl_rsa_signature.c b/SymCryptProvider/src/signature/p_scossl_rsa_signature.c index 959f3d31..76814849 100644 --- a/SymCryptProvider/src/signature/p_scossl_rsa_signature.c +++ b/SymCryptProvider/src/signature/p_scossl_rsa_signature.c @@ -102,11 +102,12 @@ SCOSSL_RSA_SIGN_CTX *p_scossl_rsa_dupctx(SCOSSL_RSA_SIGN_CTX *ctx) { if ((ctx->propq != NULL && ((copyCtx->propq = OPENSSL_strdup(ctx->propq)) == NULL)) || (ctx->mdctx != NULL && ((copyCtx->mdctx = EVP_MD_CTX_dup((const EVP_MD_CTX *)ctx->mdctx)) == NULL)) || - (ctx->md != NULL && !EVP_MD_up_ref(ctx->md))) + (ctx->md != NULL && !EVP_MD_up_ref(ctx->md)) || + (ctx->pbSignature != NULL && ((copyCtx->pbSignature = OPENSSL_memdup(ctx->pbSignature, ctx->cbSignature)) == NULL))) { p_scossl_rsa_freectx(copyCtx); ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - copyCtx = NULL; + return NULL; } copyCtx->keyCtx = ctx->keyCtx; From 63c0659cb75ed7c2e26c553243db60073537c323 Mon Sep 17 00:00:00 2001 From: Maxwell Moyer-McKee Date: Wed, 22 Apr 2026 18:28:18 +0000 Subject: [PATCH 08/12] Improve ECC error messaging and parameter validation --- ScosslCommon/inc/scossl_ecc.h | 8 +++ ScosslCommon/src/scossl_ecc.c | 31 +++++----- SymCryptEngine/src/e_scossl_ecc.c | 6 +- SymCryptEngine/src/e_scossl_ecc.h | 2 +- .../p_scossl_ecdsa_sigalg_signature.c | 57 ++++++++++++++++--- .../src/signature/p_scossl_ecdsa_signature.c | 15 +++-- 6 files changed, 86 insertions(+), 33 deletions(-) diff --git a/ScosslCommon/inc/scossl_ecc.h b/ScosslCommon/inc/scossl_ecc.h index 21826351..085c85c7 100644 --- a/ScosslCommon/inc/scossl_ecc.h +++ b/ScosslCommon/inc/scossl_ecc.h @@ -8,6 +8,14 @@ extern "C" { #endif +// If r and s are both 0, the DER encoding would be 8 bytes +// (0x30 0x06 0x02 0x01 0x00 0x02 0x01 0x00) +// integers must contain at least 1 octet of content in DER +#define SCOSSL_ECDSA_MIN_DER_SIGNATURE_LEN (8) +// Largest supported curve is P521 => 66 * 2 + 4 (int headers) + 3 (seq header) +#define SCOSSL_ECDSA_MAX_DER_SIGNATURE_LEN (139) +// Smallest supported curve is P192 => 24 * 2 byte SymCrypt signatures +#define SCOSSL_ECDSA_MIN_SYMCRYPT_SIGNATURE_LEN (48) // Largest supported curve is P521 => 66 * 2 byte SymCrypt signatures #define SCOSSL_ECDSA_MAX_SYMCRYPT_SIGNATURE_LEN (132) diff --git a/ScosslCommon/src/scossl_ecc.c b/ScosslCommon/src/scossl_ecc.c index 6e6b66c4..447d9a90 100644 --- a/ScosslCommon/src/scossl_ecc.c +++ b/ScosslCommon/src/scossl_ecc.c @@ -14,15 +14,6 @@ extern "C" { #define NID_secp192r1 (NID_X9_62_prime192v1) #define NID_secp256r1 (NID_X9_62_prime256v1) -// If r and s are both 0, the DER encoding would be 8 bytes -// (0x30 0x06 0x02 0x01 0x00 0x02 0x01 0x00) -// integers must contain at least 1 octet of content in DER -#define SCOSSL_ECDSA_MIN_DER_SIGNATURE_LEN (8) -// Largest supported curve is P521 => 66 * 2 + 4 (int headers) + 3 (seq header) -#define SCOSSL_ECDSA_MAX_DER_SIGNATURE_LEN (139) -// Smallest supported curve is P192 => 24 * 2 byte SymCrypt signatures -#define SCOSSL_ECDSA_MIN_SYMCRYPT_SIGNATURE_LEN (48) - static BOOL scossl_ecc_initialized = FALSE; static PSYMCRYPT_ECURVE _hidden_curve_P192 = NULL; static PSYMCRYPT_ECURVE _hidden_curve_P224 = NULL; @@ -422,13 +413,13 @@ SCOSSL_STATUS scossl_ecc_init_static() ((_hidden_curve_P256 = SymCryptEcurveAllocate(SymCryptEcurveParamsNistP256, 0)) == NULL) || ((_hidden_curve_P384 = SymCryptEcurveAllocate(SymCryptEcurveParamsNistP384, 0)) == NULL) || ((_hidden_curve_P521 = SymCryptEcurveAllocate(SymCryptEcurveParamsNistP521, 0)) == NULL) || - ((_hidden_curve_X25519 = SymCryptEcurveAllocate(SymCryptEcurveParamsCurve25519, 0)) == NULL) || + ((_hidden_curve_X25519 = SymCryptEcurveAllocate(SymCryptEcurveParamsCurve25519, 0)) == NULL) || ((_hidden_curve_brainpoolP256r1 = SymCryptEcurveAllocate(SymCryptEcurveParamsBrainpoolP256r1, 0)) == NULL) || ((_hidden_curve_brainpoolP384r1 = SymCryptEcurveAllocate(SymCryptEcurveParamsBrainpoolP384r1, 0)) == NULL) || ((_hidden_curve_brainpoolP512r1 = SymCryptEcurveAllocate(SymCryptEcurveParamsBrainpoolP512r1, 0)) == NULL) || ((_hidden_curve_brainpoolP256t1 = SymCryptEcurveAllocate(SymCryptEcurveParamsBrainpoolP256t1, 0)) == NULL) || - ((_hidden_curve_brainpoolP384t1 = SymCryptEcurveAllocate(SymCryptEcurveParamsBrainpoolP384t1, 0)) == NULL) || - ((_hidden_curve_brainpoolP512t1 = SymCryptEcurveAllocate(SymCryptEcurveParamsBrainpoolP512t1, 0)) == NULL)) + ((_hidden_curve_brainpoolP384t1 = SymCryptEcurveAllocate(SymCryptEcurveParamsBrainpoolP384t1, 0)) == NULL) || + ((_hidden_curve_brainpoolP512t1 = SymCryptEcurveAllocate(SymCryptEcurveParamsBrainpoolP512t1, 0)) == NULL)) { return SCOSSL_FAILURE; } @@ -1068,10 +1059,14 @@ SCOSSL_STATUS scossl_ecdsa_sign(PSYMCRYPT_ECKEY key, PCSYMCRYPT_ECURVE curve, return SCOSSL_SUCCESS; } +// Return +// 1 (SCOSSL_SUCCESS) for valid signature +// 0 (SCOSSL_FAILURE) for invalid signature +// -1 for error _Use_decl_annotations_ -SCOSSL_STATUS scossl_ecdsa_verify(PSYMCRYPT_ECKEY key, PCSYMCRYPT_ECURVE curve, - PCBYTE pbHashValue, SIZE_T cbHashValue, - PCBYTE pbSignature, SIZE_T pcbSignature) +int scossl_ecdsa_verify(PSYMCRYPT_ECKEY key, PCSYMCRYPT_ECURVE curve, + PCBYTE pbHashValue, SIZE_T cbHashValue, + PCBYTE pbSignature, SIZE_T pcbSignature) { SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; BYTE buf[SCOSSL_ECDSA_MAX_SYMCRYPT_SIGNATURE_LEN] = {0}; @@ -1082,14 +1077,14 @@ SCOSSL_STATUS scossl_ecdsa_verify(PSYMCRYPT_ECKEY key, PCSYMCRYPT_ECURVE curve, { SCOSSL_LOG_SYMCRYPT_ERROR(SCOSSL_ERR_F_ECDSA_VERIFY, "SymCryptEckeyExtendKeyUsage failed", scError); - return SCOSSL_FAILURE; + return -1; } - if (!scossl_ecdsa_remove_der(pbSignature, pcbSignature, &buf[0], cbSymCryptSig)) + if (scossl_ecdsa_remove_der(pbSignature, pcbSignature, &buf[0], cbSymCryptSig) != SCOSSL_SUCCESS) { SCOSSL_LOG_ERROR(SCOSSL_ERR_F_ECDSA_VERIFY, ERR_R_OPERATION_FAIL, "scossl_ecdsa_remove_der failed"); - return SCOSSL_FAILURE; + return -1; } scError = SymCryptEcDsaVerify( diff --git a/SymCryptEngine/src/e_scossl_ecc.c b/SymCryptEngine/src/e_scossl_ecc.c index 57e92cb6..79ce3c23 100644 --- a/SymCryptEngine/src/e_scossl_ecc.c +++ b/SymCryptEngine/src/e_scossl_ecc.c @@ -606,7 +606,11 @@ ECDSA_SIG* e_scossl_eckey_sign_sig(_In_reads_bytes_(dgstlen) const unsigned char return returnSignature; } -SCOSSL_STATUS e_scossl_eckey_verify(int type, _In_reads_bytes_(dgst_len) const unsigned char* dgst, int dgst_len, +// Return +// 1 (SCOSSL_SUCCESS) for valid signature +// 0 (SCOSSL_FAILURE) for invalid signature +// -1 for error +int e_scossl_eckey_verify(int type, _In_reads_bytes_(dgst_len) const unsigned char* dgst, int dgst_len, _In_reads_bytes_(sig_len) const unsigned char* sigbuf, int sig_len, _In_ EC_KEY* eckey) { const EC_KEY_METHOD* ossl_eckey_method = NULL; diff --git a/SymCryptEngine/src/e_scossl_ecc.h b/SymCryptEngine/src/e_scossl_ecc.h index 2a75bdf4..ad830bb0 100644 --- a/SymCryptEngine/src/e_scossl_ecc.h +++ b/SymCryptEngine/src/e_scossl_ecc.h @@ -64,7 +64,7 @@ ECDSA_SIG* e_scossl_eckey_sign_sig(_In_reads_bytes_(dgstlen) const unsigned char // Verifies that the signature in sigbuf of size sig_len is a valid ECDSA signature of the hash value dgst // of size dgst_len using the public key eckey. The parameter type is ignored. // Returns 1 for a valid signature, 0 for an invalid signature, and -1 on error. -SCOSSL_STATUS e_scossl_eckey_verify(int type, _In_reads_bytes_(dgst_len) const unsigned char* dgst, int dgst_len, +int e_scossl_eckey_verify(int type, _In_reads_bytes_(dgst_len) const unsigned char* dgst, int dgst_len, _In_reads_bytes_(sig_len) const unsigned char* sigbuf, int sig_len, _In_ EC_KEY* eckey); // Verifies that the signature in sig is a valid ECDSA signature of the hash value dgst of size dgst_len diff --git a/SymCryptProvider/src/signature/p_scossl_ecdsa_sigalg_signature.c b/SymCryptProvider/src/signature/p_scossl_ecdsa_sigalg_signature.c index 0bb416a3..5e62e610 100644 --- a/SymCryptProvider/src/signature/p_scossl_ecdsa_sigalg_signature.c +++ b/SymCryptProvider/src/signature/p_scossl_ecdsa_sigalg_signature.c @@ -96,12 +96,18 @@ static SCOSSL_STATUS p_scossl_ecdsa_sigalg_sign_message_final(_In_ SCOSSL_ECDSA_ BYTE digest[EVP_MAX_MD_SIZE]; unsigned int cbDigest = 0; - if (ctx == NULL || ctx->mdctx == NULL) + if (ctx == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); return SCOSSL_FAILURE; } + if (ctx->mdctx == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); + return 0; + } + if (!ctx->allowFinal) { ERR_raise(ERR_LIB_PROV, PROV_R_FINAL_CALL_OUT_OF_ORDER); @@ -133,21 +139,27 @@ static int p_scossl_ecdsa_sigalg_verify_message_final(_In_ SCOSSL_ECDSA_CTX *ctx BYTE digest[EVP_MAX_MD_SIZE]; unsigned int cbDigest = 0; - if (ctx == NULL || ctx->mdctx == NULL) + if (ctx == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); - return SCOSSL_FAILURE; + return 0; + } + + if (ctx->mdctx == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); + return 0; } if (!ctx->allowFinal) { ERR_raise(ERR_LIB_PROV, PROV_R_FINAL_CALL_OUT_OF_ORDER); - return SCOSSL_FAILURE; + return 0; } if (!EVP_DigestFinal_ex(ctx->mdctx, digest, &cbDigest)) { - return SCOSSL_FAILURE; + return 0; } ctx->allowUpdate = FALSE; @@ -204,24 +216,32 @@ static int p_scossl_ecdsa_sigalg_verify(_In_ SCOSSL_ECDSA_CTX *ctx, if (ctx == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); - return -1; + return 0; } if (!ctx->allowOneshot) { ERR_raise(ERR_LIB_PROV, PROV_R_ONESHOT_CALL_OUT_OF_ORDER); - return -1; + return 0; } if (ctx->operation == EVP_PKEY_OP_VERIFYMSG) { OPENSSL_free(ctx->pbSignature); + ctx->pbSignature = NULL; ctx->cbSignature = 0; + if (siglen == 0 || + siglen > SCOSSL_ECDSA_MAX_DER_SIGNATURE_LEN) + { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SIGNATURE_SIZE); + return 0; + } + if ((ctx->pbSignature = OPENSSL_memdup(sig, siglen)) == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - return -1; + return 0; } ctx->cbSignature = siglen; @@ -262,13 +282,32 @@ static SCOSSL_STATUS p_scossl_ecdsa_sigalg_set_ctx_params(_Inout_ SCOSSL_ECDSA_C { if ((p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_SIGNATURE)) != NULL) { + PCBYTE pbSignature = NULL; + SIZE_T cbSignature = 0; + OPENSSL_free(ctx->pbSignature); ctx->pbSignature = NULL; ctx->cbSignature = 0; - if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->pbSignature, 0, &ctx->cbSignature)) + + if (!OSSL_PARAM_get_octet_string_ptr(p, (const void **)&pbSignature, &cbSignature)) + { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return SCOSSL_FAILURE; + } + + if (cbSignature == 0 || + cbSignature > SCOSSL_ECDSA_MAX_DER_SIGNATURE_LEN) + { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SIGNATURE_SIZE); + return SCOSSL_FAILURE; + } + + if ((ctx->pbSignature = OPENSSL_memdup(pbSignature, cbSignature)) == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); return SCOSSL_FAILURE; } + ctx->cbSignature = cbSignature; } } diff --git a/SymCryptProvider/src/signature/p_scossl_ecdsa_signature.c b/SymCryptProvider/src/signature/p_scossl_ecdsa_signature.c index c697f25a..b84bedbc 100644 --- a/SymCryptProvider/src/signature/p_scossl_ecdsa_signature.c +++ b/SymCryptProvider/src/signature/p_scossl_ecdsa_signature.c @@ -201,7 +201,7 @@ int p_scossl_ecdsa_verify_internal(SCOSSL_ECDSA_CTX *ctx, const unsigned char *sig, size_t siglen, const unsigned char *tbs, size_t tbslen) { - if (ctx == NULL || ctx->keyCtx == NULL) + if (ctx->keyCtx == NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); return -1; @@ -299,8 +299,15 @@ static int p_scossl_ecdsa_digest_verify_final(_In_ SCOSSL_ECDSA_CTX *ctx, BYTE digest[EVP_MAX_MD_SIZE]; unsigned int cbDigest = 0; + if (ctx == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (ctx->mdctx == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); return 0; } @@ -343,14 +350,14 @@ static int p_scossl_ecdsa_verify(_In_ SCOSSL_ECDSA_CTX *ctx, { if (ctx == NULL) { - ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); - return -1; + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); + return 0; } if (!ctx->allowOneshot) { ERR_raise(ERR_LIB_PROV, PROV_R_ONESHOT_CALL_OUT_OF_ORDER); - return -1; + return 0; } return p_scossl_ecdsa_verify_internal(ctx, sig, siglen, tbs, tbslen); From c19232a5c54937ab9205f0f652108f04bc2f8fdc Mon Sep 17 00:00:00 2001 From: Maxwell Moyer-McKee Date: Wed, 22 Apr 2026 20:51:15 +0000 Subject: [PATCH 09/12] Harden RSA input validation and PR comments --- .../p_scossl_ecdsa_sigalg_signature.c | 6 ++-- .../signature/p_scossl_rsa_sigalg_signature.c | 32 +++++++++++++++++-- .../src/signature/p_scossl_rsa_signature.c | 3 +- 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/SymCryptProvider/src/signature/p_scossl_ecdsa_sigalg_signature.c b/SymCryptProvider/src/signature/p_scossl_ecdsa_sigalg_signature.c index 5e62e610..461e6f9c 100644 --- a/SymCryptProvider/src/signature/p_scossl_ecdsa_sigalg_signature.c +++ b/SymCryptProvider/src/signature/p_scossl_ecdsa_sigalg_signature.c @@ -282,14 +282,14 @@ static SCOSSL_STATUS p_scossl_ecdsa_sigalg_set_ctx_params(_Inout_ SCOSSL_ECDSA_C { if ((p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_SIGNATURE)) != NULL) { - PCBYTE pbSignature = NULL; + PCBYTE pcbSignature = NULL; SIZE_T cbSignature = 0; OPENSSL_free(ctx->pbSignature); ctx->pbSignature = NULL; ctx->cbSignature = 0; - if (!OSSL_PARAM_get_octet_string_ptr(p, (const void **)&pbSignature, &cbSignature)) + if (!OSSL_PARAM_get_octet_string_ptr(p, (const void **)&pcbSignature, &cbSignature)) { ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); return SCOSSL_FAILURE; @@ -302,7 +302,7 @@ static SCOSSL_STATUS p_scossl_ecdsa_sigalg_set_ctx_params(_Inout_ SCOSSL_ECDSA_C return SCOSSL_FAILURE; } - if ((ctx->pbSignature = OPENSSL_memdup(pbSignature, cbSignature)) == NULL) + if ((ctx->pbSignature = OPENSSL_memdup(pcbSignature, cbSignature)) == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); return SCOSSL_FAILURE; diff --git a/SymCryptProvider/src/signature/p_scossl_rsa_sigalg_signature.c b/SymCryptProvider/src/signature/p_scossl_rsa_sigalg_signature.c index 1b3551da..ade35ce8 100644 --- a/SymCryptProvider/src/signature/p_scossl_rsa_sigalg_signature.c +++ b/SymCryptProvider/src/signature/p_scossl_rsa_sigalg_signature.c @@ -13,6 +13,8 @@ extern "C" { #endif +#define SCOSSL_RSA_MAX_SIGNATURE_LEN (SYMCRYPT_RSAKEY_MAX_BITSIZE_MODULUS / 8) + static const OSSL_PARAM p_scossl_rsa_sigalg_ctx_settable_param_types[] = { OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_SIGNATURE, NULL, 0), OSSL_PARAM_END}; @@ -97,7 +99,7 @@ static SCOSSL_STATUS p_scossl_rsa_sigalg_signverify_message_update(_In_ SCOSSL_R return SCOSSL_FAILURE; } - ctx->allowOneshot = 0; + ctx->allowOneshot = FALSE; return EVP_DigestUpdate(ctx->mdctx, in, inlen); } @@ -220,6 +222,13 @@ static SCOSSL_STATUS p_scossl_rsa_sigalg_verify(_In_ SCOSSL_RSA_SIGN_CTX *ctx, OPENSSL_free(ctx->pbSignature); ctx->cbSignature = 0; + if (siglen == 0 || + siglen > SCOSSL_RSA_MAX_SIGNATURE_LEN) + { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SIGNATURE_SIZE); + return SCOSSL_FAILURE; + } + if ((ctx->pbSignature = OPENSSL_memdup(sig, siglen)) == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); @@ -262,13 +271,32 @@ static SCOSSL_STATUS p_scossl_rsa_sigalg_set_ctx_params(_Inout_ SCOSSL_RSA_SIGN_ { if ((p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_SIGNATURE)) != NULL) { + PCBYTE pcbSignature = NULL; + SIZE_T cbSignature = 0; + OPENSSL_free(ctx->pbSignature); ctx->pbSignature = NULL; ctx->cbSignature = 0; - if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->pbSignature, 0, &ctx->cbSignature)) + + if (!OSSL_PARAM_get_octet_string_ptr(p, (const void **)&pcbSignature, &cbSignature)) + { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return SCOSSL_FAILURE; + } + + if (cbSignature == 0 || + cbSignature > SCOSSL_RSA_MAX_SIGNATURE_LEN) + { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SIGNATURE_SIZE); + return SCOSSL_FAILURE; + } + + if ((ctx->pbSignature = OPENSSL_memdup(pcbSignature, cbSignature)) == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); return SCOSSL_FAILURE; } + ctx->cbSignature = cbSignature; } } diff --git a/SymCryptProvider/src/signature/p_scossl_rsa_signature.c b/SymCryptProvider/src/signature/p_scossl_rsa_signature.c index 76814849..a94cb99f 100644 --- a/SymCryptProvider/src/signature/p_scossl_rsa_signature.c +++ b/SymCryptProvider/src/signature/p_scossl_rsa_signature.c @@ -419,6 +419,8 @@ static SCOSSL_STATUS p_scossl_rsa_digest_sign_final(_In_ SCOSSL_RSA_SIGN_CTX *ct // If sig is NULL, this is a size fetch, and the digest does not need to be computed if (sig != NULL) { + ctx->allowMdUpdates = TRUE; + if (!EVP_DigestFinal_ex(ctx->mdctx, digest, &cbDigest)) { return SCOSSL_FAILURE; @@ -431,7 +433,6 @@ static SCOSSL_STATUS p_scossl_rsa_digest_sign_final(_In_ SCOSSL_RSA_SIGN_CTX *ct ret = p_scossl_rsa_sign_internal(ctx, sig, siglen, sigsize, digest, cbDigest); - ctx->allowMdUpdates = TRUE; return ret; } From 44d98cb9d33d4f1c1d2778339ee144d485e1be69 Mon Sep 17 00:00:00 2001 From: Maxwell Moyer-McKee Date: Thu, 23 Apr 2026 16:32:28 +0000 Subject: [PATCH 10/12] Add sigalg tests --- EvpTestRecipes/3.5/evppkey_ecdsa_sigalg.txt | 155 +++++++++++++++++++ EvpTestRecipes/3.5/evppkey_rsa_sigalg.txt | 157 ++++++++++++++++++++ 2 files changed, 312 insertions(+) create mode 100644 EvpTestRecipes/3.5/evppkey_ecdsa_sigalg.txt create mode 100644 EvpTestRecipes/3.5/evppkey_rsa_sigalg.txt diff --git a/EvpTestRecipes/3.5/evppkey_ecdsa_sigalg.txt b/EvpTestRecipes/3.5/evppkey_ecdsa_sigalg.txt new file mode 100644 index 00000000..3b541699 --- /dev/null +++ b/EvpTestRecipes/3.5/evppkey_ecdsa_sigalg.txt @@ -0,0 +1,155 @@ +# +# Copyright 2024 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the Apache License 2.0 (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# Tests start with one of these keywords +# Cipher Decrypt Derive Digest Encoding KDF MAC PBE +# PrivPubKeyPair Sign Verify VerifyRecover +# and continue until a blank line. Lines starting with a pound sign are ignored. +# The keyword Availablein must appear before the test name if needed. + +# Public key algorithm tests + +# Private keys used for PKEY operations. + +# EC P-256 key + +PrivateKey=P-256 +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgiocvtiiTxNH/xbnw ++RdYBp+DUuCPoFpJ+NuSbLVyhyWhRANCAAQsFQ9CnOcPIWwlLPXgYs4fY5zV0WXH ++JQkBywnGX14szuSDpXNtmTpkNzwz+oNlOKo5q+dDlgFbmUxBJJbn+bJ +-----END PRIVATE KEY----- + +# EC public key for above + +PublicKey=P-256-PUBLIC +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELBUPQpznDyFsJSz14GLOH2Oc1dFl +x/iUJAcsJxl9eLM7kg6VzbZk6ZDc8M/qDZTiqOavnQ5YBW5lMQSSW5/myQ== +-----END PUBLIC KEY----- + +PrivPubKeyPair = P-256:P-256-PUBLIC + +Title = ECDSA tests + +Verify = ECDSA-SHA1:P-256-PUBLIC +Input = "0123456789ABCDEF1234" +Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec8 + +# Digest too long +Verify = ECDSA-SHA1:P-256-PUBLIC +Input = "0123456789ABCDEF12345" +Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec8 +Result = VERIFY_ERROR + +# Digest too short +Verify = ECDSA-SHA1:P-256-PUBLIC +Input = "0123456789ABCDEF123" +Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec8 +Result = VERIFY_ERROR + +# Digest invalid +Verify = ECDSA-SHA1:P-256-PUBLIC +Input = "0123456789ABCDEF1235" +Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec8 +Result = VERIFY_ERROR + +# Invalid signature +Verify = ECDSA-SHA1:P-256-PUBLIC +Input = "0123456789ABCDEF1234" +Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec7 +Result = VERIFY_ERROR + +# Garbage after signature +Verify = ECDSA-SHA1:P-256-PUBLIC +Input = "0123456789ABCDEF1234" +Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec800 +Result = VERIFY_ERROR + +# BER signature +Verify = ECDSA-SHA1:P-256-PUBLIC +Input = "0123456789ABCDEF1234" +Output = 3080022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec80000 +Result = VERIFY_ERROR + +Verify = ECDSA-SHA1:P-256-PUBLIC +Input = "0123456789ABCDEF1234" +Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec8 + +Title = Sign-Message and Verify-Message + +Verify-Message-Public = ECDSA-SHA256:P-256-PUBLIC +Input = "Hello World" +Output = 3046022100e7515177ec3817b77a4a94066ab3070817b7aa9d44a8a09f040da250116e8972022100ba59b0f631258e59a9026be5d84f60685f4cf22b9165a0c2736d5c21c8ec1862 + +PublicKey=P-384-PUBLIC +-----BEGIN PUBLIC KEY----- +MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAES/TlL5WEJ+u1kV+4yVlVUbTTo/2rZ7rd +nWwwk/QlukNjDfcfQvDrfOqpTZ9kSKhd0wMxWIJJ/S/cCzCex+2EgbwW8ngAwT19 +twD8guGxyFRaoMDTtW47/nifwYqRaIfC +-----END PUBLIC KEY----- + +Verify-Message-Public = ECDSA-SHA384:P-384-PUBLIC +Input = "123400" +Output = 304d0218389cb27e0bc8d21fa7e5f24cb74f58851313e696333ad68b023100ffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52970 + +# Oneshot tests +Verify-Message-Public = ECDSA-SHA256:P-256-PUBLIC +Input = "Hello World" +Output = 3046022100e7515177ec3817b77a4a94066ab3070817b7aa9d44a8a09f040da250116e8972022100ba59b0f631258e59a9026be5d84f60685f4cf22b9165a0c2736d5c21c8ec1862 + +# Test that mdsize != tbssize fails +Sign = ECDSA-SHA256:P-256 +Input = "0123456789ABCDEF1234" +Result = KEYOP_ERROR + +PrivateKey = P-256_NAMED_CURVE_EXPLICIT +-----BEGIN PRIVATE KEY----- +MIIBeQIBADCCAQMGByqGSM49AgEwgfcCAQEwLAYHKoZIzj0BAQIhAP////8AAAAB +AAAAAAAAAAAAAAAA////////////////MFsEIP////8AAAABAAAAAAAAAAAAAAAA +///////////////8BCBaxjXYqjqT57PrvVV2mIa8ZR0GsMxTsPY7zjw+J9JgSwMV +AMSdNgiG5wSTamZ44ROdJreBn36QBEEEaxfR8uEsQkf4vOblY6RA8ncDfYEt6zOg +9KE5RdiYwpZP40Li/hp/m47n60p8D54WK84zV2sxXs7LtkBoN79R9QIhAP////8A +AAAA//////////+85vqtpxeehPO5ysL8YyVRAgEBBG0wawIBAQQgiUTxtr5vLVjj +0BOXUa/4r82DJ30QoupYS/wlilW4gWehRANCAATM0n3q2UaDyaQ7OxzJM3B6prhW +3ev1gTwRBduzqqlwd54AUSgI+pjttW8zrWNitO8H1sf59MPWOESKxNtZ1+Nl +-----END PRIVATE KEY----- + +PrivateKey = EC_EXPLICIT +-----BEGIN PRIVATE KEY----- +MIIBeQIBADCCAQMGByqGSM49AgEwgfcCAQEwLAYHKoZIzj0BAQIhAP////8AAAAB +AAAAAAAAAAAAAAAA////////////////MFsEIP////8AAAABAAAAAAAAAAAAAAAA +///////////////8BCBaxjXYqjqT57PrvVV2mIa8ZR0GsMxTsPY7zjw+J9JgSwMV +AMSdNgiG5wSTamZ44ROdJreBn36QBEEE5JcIvn36opqjEm/k59Al40rBAxWM2TPG +l0L13Je51zHpfXQ9Z2o7IQicMXP4wSfJ0qCgg2bgydqoxlYrlLGuVQIhAP////8A +AAAA//////////+85vqtpxeehPO5ysL8YyVRAgEBBG0wawIBAQQgec92jwduadCk +OjoNRI+YT5Be5TkzZXzYCyTLkMOikDmhRANCAATtECEhQbLEaiUj/Wu0qjcr81lL +46dx5zYgArz/iaSNJ3W80oO+F7v04jlQ7wxQzg96R0bwKiMeq5CcW9ZFt6xg +-----END PRIVATE KEY----- + +PrivateKey = B-163 +-----BEGIN PRIVATE KEY----- +MGMCAQAwEAYHKoZIzj0CAQYFK4EEAA8ETDBKAgEBBBUDnQW0mLiHVha/jqFznX/K +DnVlDgChLgMsAAQB1qZ00fPIct+QN8skv1XIHtBNp3EGLytJV0tsAUTYtGhtrzRj +e3GzYyg= +-----END PRIVATE KEY----- + +PrivateKey = secp256k1 +-----BEGIN PRIVATE KEY----- +MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQgsLpFV9joHc0bisyV53XL +mrG6/Gu6ZaHoXtKP/VFX44ehRANCAARLYWGgp5nP4N8guypLSbYGCVN6ZPCnWW4x +srYkcpdbxr4neRT3zC62keCKgPbJf5SIHkJ2Tcaw6hVSrBOUFtix +-----END PRIVATE KEY----- + +Title = FIPS tests + +# Test that a nist curve with SHA3 is allowed in fips mode +# The sign will get a mismatch error since the output signature changes on each run +Sign-Message = ECDSA-SHA3-512:P-256 +Input = "Hello World" +Result = KEYOP_MISMATCH diff --git a/EvpTestRecipes/3.5/evppkey_rsa_sigalg.txt b/EvpTestRecipes/3.5/evppkey_rsa_sigalg.txt new file mode 100644 index 00000000..04b197c1 --- /dev/null +++ b/EvpTestRecipes/3.5/evppkey_rsa_sigalg.txt @@ -0,0 +1,157 @@ +# +# Copyright 2001-2025 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the Apache License 2.0 (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# Tests start with one of these keywords +# Cipher Decrypt Derive Digest Encoding KDF MAC PBE +# PrivPubKeyPair Sign Verify VerifyRecover +# and continue until a blank line. Lines starting with a pound sign are ignored. +# The keyword Availablein must appear before the test name if needed. + +# Private keys used for PKEY operations. + +# RSA 2048 bit key. + +PrivateKey = RSA-2048 +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDNAIHqeyrh6gbV +n3xz2f+5SglhXC5Lp8Y2zvCN01M+wxhVJbAVx2m5mnfWclv5w1Mqm25fZifV+4UW +B2jT3anL01l0URcX3D0wnS/EfuQfl+Mq23+d2GShxHZ6Zm7NcbwarPXnUX9LOFlP +6psF5C1a2pkSAIAT5FMWpNm7jtCGuI0odYusr5ItRqhotIXSOcm66w4rZFknEPQr +LR6gpLSALAvsqzKPimiwBzvbVG/uqYCdKEmRKzkMFTK8finHZY+BdfrkbzQzL/h7 +yrPkBkm5hXeGnaDqcYNT8HInVIhpE2SHYNEivmduD8SD3SD/wxvalqMZZsmqLnWt +A95H4cRPAgMBAAECggEAYCl6x5kbFnoG1rJHWLjL4gi+ubLZ7Jc4vYD5Ci41AF3X +ziktnim6iFvTFv7x8gkTvArJDWsICLJBTYIQREHYYkozzgIzyPeApIs3Wv8C12cS +IopwJITbP56+zM+77hcJ26GCgA2Unp5CFuC/81WDiPi9kNo3Oh2CdD7D+90UJ/0W +glplejFpEuhpU2URfKL4RckJQF/KxV+JX8FdIDhsJu54yemQdQKaF4psHkzwwgDo +qc+yfp0Vb4bmwq3CKxqEoc1cpbJ5CHXXlAfISzUjlcuBzD/tW7BDtp7eDAcgRVAC +XO6MX0QBcLYSC7SOD3R7zY9SIRCFDfBDxCjf0YcFMQKBgQD2+WG0fLwDXTrt68fe +hQqVa2Xs25z2B2QGPxWqSFU8WNly/mZ1BW413f3De/O58vYi7icTNyVoScm+8hdv +6PfD+LuRujdN1TuvPeyBTSvewQwf3IjN0Wh28mse36PwlBl+301C/x+ylxEDuJjK +hZxCcocIaoQqtBC7ac8tNa9r4wKBgQDUfnJKf/QQSLJwwlJKQQGHi3MVm7c9PbwY +eyIOY1s1NPluJDoYTZP4YLa/u2txwe2aHh9FhYMCPDAelqaSwaCLU9DsnKkQEA2A +RR47fcagG6xK7O+N95iEa8I1oIy7os9MBoBMwRIZ6VYIxxTj8UMNSR+tu6MqV1Gg +T5d0WDTJpQKBgCHyRSu5uV39AoyRS/eZ8cp36JqV1Q08FtOE+EVfi9evnrPfo9WR +2YQt7yNfdjCo5IwIj/ZkLhAXlFNakz4el2+oUJ/HKLLaDEoaCNf883q6rh/zABrK +HcG7sF2d/7qhoJ9/se7zgjfZ68zHIrkzhDbd5xGREnmMJoCcGo3sQyBhAoGAH3UQ +qmLC2N5KPFMoJ4H0HgLQ6LQCrnhDLkScSBEBYaEUA/AtAYgKjcyTgVLXlyGkcRpg +esRHHr+WSBD5W+R6ReYEmeKfTJdzyDdzQE9gZjdyjC0DUbsDwybIu3OnIef6VEDq +IXK7oUZfzDDcsNn4mTDoFaoff5cpqFfgDgM43VkCgYBNHw11b+d+AQmaZS9QqIt7 +aF3FvwCYHV0jdv0Mb+Kc1bY4c0R5MFpzrTwVmdOerjuuA1+9b+0Hwo3nBZM4eaBu +SOamA2hu2OJWCl9q8fLCT69KqWDjghhvFe7c6aJJGucwaA3Uz3eLcPqoaCarMiNH +fMkTd7GabVourqIZdgvu1Q== +-----END PRIVATE KEY----- + +# Corresponding public key + +PublicKey = RSA-2048-PUBLIC +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzQCB6nsq4eoG1Z98c9n/ +uUoJYVwuS6fGNs7wjdNTPsMYVSWwFcdpuZp31nJb+cNTKptuX2Yn1fuFFgdo092p +y9NZdFEXF9w9MJ0vxH7kH5fjKtt/ndhkocR2emZuzXG8Gqz151F/SzhZT+qbBeQt +WtqZEgCAE+RTFqTZu47QhriNKHWLrK+SLUaoaLSF0jnJuusOK2RZJxD0Ky0eoKS0 +gCwL7Ksyj4posAc721Rv7qmAnShJkSs5DBUyvH4px2WPgXX65G80My/4e8qz5AZJ +uYV3hp2g6nGDU/ByJ1SIaRNkh2DRIr5nbg/Eg90g/8Mb2pajGWbJqi51rQPeR+HE +TwIDAQAB +-----END PUBLIC KEY----- + +PrivPubKeyPair = RSA-2048:RSA-2048-PUBLIC + +Title = RSA tests with EVP_PKEY_sign, EVP_PKEY_verify + +# Demonstrate the possibility to use the RSA (not RSA-SHA1) signature +# implementation with EVP_PKEY_sign_init_ex2() the same way as with +# EVP_PKEY_sign_init_ex(). +Sign = RSA:RSA-2048 +Ctrl = digest:SHA1 +Input = "0123456789ABCDEF1234" +Output = c09d402423cbf233d26cae21f954547bc43fe80fd41360a0336cfdbe9aedad05bef6fd2eaee6cd60089a52482d4809a238149520df3bdde4cb9e23d9307b05c0a6f327052325a29adf2cc95b66523be7024e2a585c3d4db15dfbe146efe0ecdc0402e33fe5d40324ee96c5c3edd374a15cdc0f5d84aa243c0f07e188c6518fbfceae158a9943be398e31097da81b62074f626eff738be6160741d5a26957a482b3251fd85d8df78b98148459de10aa93305dbb4a5230aa1da291a9b0e481918f99b7638d72bb687f97661d304ae145d64a474437a4ef39d7b8059332ddeb07e92bf6e0e3acaf8afedc93795e4511737ec1e7aab6d5bc9466afc950c1c17b48ad + +Sign = RSA-SHA1:RSA-2048 +Input = "0123456789ABCDEF1234" +Output = c09d402423cbf233d26cae21f954547bc43fe80fd41360a0336cfdbe9aedad05bef6fd2eaee6cd60089a52482d4809a238149520df3bdde4cb9e23d9307b05c0a6f327052325a29adf2cc95b66523be7024e2a585c3d4db15dfbe146efe0ecdc0402e33fe5d40324ee96c5c3edd374a15cdc0f5d84aa243c0f07e188c6518fbfceae158a9943be398e31097da81b62074f626eff738be6160741d5a26957a482b3251fd85d8df78b98148459de10aa93305dbb4a5230aa1da291a9b0e481918f99b7638d72bb687f97661d304ae145d64a474437a4ef39d7b8059332ddeb07e92bf6e0e3acaf8afedc93795e4511737ec1e7aab6d5bc9466afc950c1c17b48ad + +# Digest too long +Sign = RSA-SHA1:RSA-2048 +Input = "0123456789ABCDEF12345" +Output = 00 +Result = KEYOP_ERROR + +# Digest too short +Sign = RSA-SHA1:RSA-2048 +Input = "0123456789ABCDEF12345" +Output = 00 +Result = KEYOP_ERROR + +# Truncated digest [copy from evppkey_rsa_common.txt] +Sign = RSA-SHA512-224:RSA-2048 +Input = "0123456789ABCDEF123456789ABC" +Output = 5f720e9488139bb21e1c2f027fd5ce5993e6d31c5a8faaee833487b3a944d66891178868ace8070cad3ee2ffbe54aa4885a15fd1a7cc5166970fe1fd8c0423e72bd3e3b56fc4a53ed80aaaeca42497f0ec3c62113edc05cd006608f5eef7ce3ad4cba1069f68731dd28a524a1f93fcdc5547112d48d45586dd943ba0d443be9635720d8a61697c54c96627f0d85c5fbeaa3b4af86a65cf2fc3800dd5de34c046985f25d0efc0bb6edccc1d08b3a4fb9c8faffe181c7e68b31e374ad1440a4a664eec9ca0dc53a9d2f5bc7d9940d866f64201bcbc63612754df45727ea24b531d7de83d1bb707444859fa35521320c33bf6f4dbeb6fb56e653adbf7af15843f17 + +Verify = RSA-SHA512-224:RSA-2048 +Input = "0123456789ABCDEF123456789ABC" +Output = 5f720e9488139bb21e1c2f027fd5ce5993e6d31c5a8faaee833487b3a944d66891178868ace8070cad3ee2ffbe54aa4885a15fd1a7cc5166970fe1fd8c0423e72bd3e3b56fc4a53ed80aaaeca42497f0ec3c62113edc05cd006608f5eef7ce3ad4cba1069f68731dd28a524a1f93fcdc5547112d48d45586dd943ba0d443be9635720d8a61697c54c96627f0d85c5fbeaa3b4af86a65cf2fc3800dd5de34c046985f25d0efc0bb6edccc1d08b3a4fb9c8faffe181c7e68b31e374ad1440a4a664eec9ca0dc53a9d2f5bc7d9940d866f64201bcbc63612754df45727ea24b531d7de83d1bb707444859fa35521320c33bf6f4dbeb6fb56e653adbf7af15843f17 + + +Title = RSA with EVP_PKEY_sign_message, EVP_PKEY_verify_message + +Sign-Message = RSA-SHA1:RSA-2048 +Input = "Hello World" +Output = 3da3ca2bdd1b23a231b0e3c49d95d5959f9398c27a1e534c7e6baf1d2682304d3b6b229385b1edf483f5ef6f9b35bf10c519a302bb2f79c564e1a59ba71aa2fa36df96c942c43e8d9bd4702b5f61c12a078ae2b34d0de221fc8f9f936b79a67c89d11ba5da8c63a1370d0e824c6b661123e9b58b143ff533cf362cbdad70e65b419a6d45723bf22db3c76bb8f5337c5c5c93cb6f38b30d0c835b54c23405ca4217dd0b755f3712ebad285d9e0c02655f6ce5ce6fed78f3c81843de325f628055eef57f280dee0c3170050137ee599b9ab7f2b5d3c5f831777ea05a5eb097c70bad1a7214dadae12d7960bb9425390c7d25a79985e1e3c28ad422ff93c808f4b5 + +Sign-Message = RSA-SHA256:RSA-2048 +Input = "Hello World" +Output = ba8c24b86f18633767ed1778ef12d283a508d0bef32dd50b4a67cbd6b75df0f4ef6e69bfafbc809b01b93ab34aad9a33908644efca6eca04db1afda1016d1c1603183d2263597cf85ce5b7acd6a4872cbcc401b90b221d85aa0a2d0e1f159fc0843e0a55c47dc108c3f207d000e954605fabbb8c938050f280e29653aa1438109d02e53dfbdcb8cb9b46d372dd39ba7317a3f4c0020dba1ddd247b3d58addb1df7208785a62a8e3e4372c1fa6d24a17cd6413f7f5c046ba40a881c21875fde848b3b56fea7264430eca15b27c5c3b72fedcbcc124f8d939ffc11e6d3172c7eb491d378902093fcc3bf3a2835a1fcfabf457c13abf7b37f08595ed72332e27034 + +# As there dont seem to be test vectors for these - they were just generated +# to verify that all digests are supported. +# +# The following can easily be verified manually with this or similar +# command, provided that the RSA-2048 private key is stored in key.pem, +# and that {hashname} is replaced with the actual hash name: +# +# echo -n 'Hello World' | openssl dgst -hex -sign key.pem -{hashname} +# +# That command uses the EVP_DigestSign API. + +Title = Test RSA with different digests + +Sign-Message = RSA-SHA224:RSA-2048 +Input = "Hello World" +Output = 4bae2cf892733233985102eb7117303e49994a8a97b3de64597c33f15a689502ba4dcea20f0ada460b262bd0c92db23dd090453f95debbfd7a835b51d1923ede76f4f66ba04d9ba0715b333a747c8d469283af653f286a307a3c46cd91f51ca2d597f9d3951fc068ff3ed45ba6b3540801159c7c890a252183de9e4aeb0512eb9ae681ac1d436c9efef9f265dcdf64ce67dce73d8a88bcb0008211bc6cd5493822818bfc208b8737ae38874184f834301de26e537694cfdc0abaccc2702820ee58cbba243aac685681329705999f4d77e596615293eb642ec450f149caabfab55092fc0315ec4157d322813ba9790c0f46c6805b8e1c0f21b6211c3529e6d7cc + +Sign-Message = RSA-SHA384:RSA-2048 +Input = "Hello World" +Output = 041348caa7ffaa7dce1ac67567c408967a1736dd44ff73076570a63c4c7128ff09f716918b81fdfaa160368bc8b85c23466f8c0d4172da880386b75065f541c0fb6c9355a1731532ebab9cf5026cafe03a790bc1698586fbdff5f6e8f1a7148b07f1f895a99d0f041b8b36d8ffdd5e77ba36e5177610e0825ba78594f95826dabdc95f682da04edf0d133c55e78fa386dea9dbc1cf748e768e9116976476e75a84b5510d869beac9a1a9ffc579a28629154b24ee9df8d51fee479f4dca5646a2032c27206ad30f4937fc096c41362562bee74562132a4f471bb4b4c76e774be0e9eca9412809665ab13951d3699b3a7ccb6714a0f070345f6f3e037bd0f8ae52 + +Sign-Message = RSA-SHA512:RSA-2048 +Input = "Hello World" +Output = 32e1f87fcd81a9d5a9f988087cdb3931fe0b12197d501b9c958cc1614a236e71a00ee7c96f7d5b3ae5ae3f11e40df5d06b0a818ee2a573aa1459f7f14dc22ca0b0b0ad2d47f4ab9e479baa084973b69f74f691ee700af102aceaf788e513f0e942a862bc6884ef1efb993b11d2ebd95139c61c37f8eac3edd94a4d8a358842f17da6d2971b8141a70097a1de569751eb4533e27880206fb8f8e1ac995688ca6facc85ed116becea9d3c4d0e96b2cb4b422b21c81328a335441d897c7deebf0f605ef086cfc5d81d1ab30ac04f674993511b142ea7ad43a8d3b7b1d2d26ce4a93413b690afdb1718408379fbd002a3c569bf11f0c10ce7cb46e257ce6b62ef62b + +Sign-Message = RSA-SHA512-224:RSA-2048 +Input = "Hello World" +Output = 8f20f0f2389408cfb7f4b47c299ca610c34a2ad20664378530ecf977c3243ce5f01c71296d2101dc962853a27f64a228eea92fee05780be31cdd7fe648d39f136de1dd857609d0d54d0de52c5cdf09d95986d808d1c92dcb3e8e96848af788c959927196316fcc56b884d34711a2a947b7e806caf7a2b05314f0c726b5e083baa0b341ac6515529bf6b3a7098a635c865e8d4b05af68fb3e893feb12ac7c4d667e1233f2e39449c285d4ad2a809e687f68ef66daf710e7d21e97833372c251bc0b45bc79c8bfe4087f16662875c2fc91a02d11078556a2b3232617406fbd947b9d95c193742ac4bb1858934ed7288cd0327c678b5295c682a4d2ba91d8fafae7 + +Sign-Message = RSA-SHA512-256:RSA-2048 +Input = "Hello World" +Output = 00904130234e4e1a51060f7747ab26ca766c64cff1df97e4d0f432169046da422305ddea16b96e0d8fcc5ab651ac247d1b65283f2f27e7e97538e9f6b77f9558c9885d5ddacaf4d6ca600ad61693766498fa815361cd1debe2d71a5af77da71f8bd72d2f5cf741aa177a2dc44107f5887d95b217c67dbc5a4874f9aa8de1fc8a5645815c561edcb348db6458018096a99a98f5d2e677f068c9093618e28f532a97e8d6161aec002d5273884ce8b46f077d37b1e158de682a927126952bdbb6b6dfdf47d7e34a7d9c9b1395315586a11ceadfb72c021b28e28b8397bc9086418a45cb8c1ad46ef47f1c2bedb14b50e50b58bd607992e1d19b895119c6a62471b4 + +Sign-Message = RSA-SHA3-224:RSA-2048 +Input = "Hello World" +Output = 5b6f6834356ba08ef649d822592d7a3d889995283e3752760b0728ed99aa05af901298159485a690f8dab21c850946ef2376bedcc87f403288039e1eb18dfdf4ac1075753528c94b5a8b11f74513ef64eddc215f7df97d977e788fd93db4063529fd87f583c1c98d39cd79178330bae7980d9a846acdf3bdd77a864f85b77941b375c076ff86def44b8da19b5de6131bb8894c870d4deeb62361bd429faad97530abab33795912d63f2fb886b25f1a1d9583fae3b7cf6dd6a5addd1b28320ab88a4dac2d938fb50b6c9115c7a0a4edd6b7b3453e435605839703f0b0c6e58f7bb73ef0fb38cab4f2d9dc1fd8b8b77b36ae945dea7563eaa33608781ce5ac181b + +Sign-Message = RSA-SHA3-256:RSA-2048 +Input = "Hello World" +Output = c531d0db6635b7c58c7118641565796c3d61323e303246cfc39e4e697727fede52b029407f82aa07e25c4833d18ec6ef6b585f3f078ca1494ae80a696fec701e1c2386196100cc5879fb8ea77f07b7019185258e1ad632c28cc672a61296787bb16a0e4f259d6eac1960f7eaaee1f7ab7eea3cf2d9e11435859630f0c71c48c8655b1252e072f18831731b2bc8e788a722c77db57583c7456e9b7fd5273e6781e214616620084dfefffe506910a39087912c3a8586fce65d8a0b1e5803ffe59b53537119653d708a55ef17d2721b9c8c183fe6750991b0e77b79d8d208ad750b2bc3426fbeeebf9b090bfc19f6534e44bf6d7d2f2e1dc2594b38ceda420553c9 + +Sign-Message = RSA-SHA3-384:RSA-2048 +Input = "Hello World" +Output = 78bc11342fd44b4c047a365cc6ef78476bf28547da4eafec09f6bdf68a5593e993716662801b313515d80ddd232dfcc414cf896349a0237976dd89a97a9c88a92cd86992996d9c2747bf4e5dff5acb2fc67aa51ceb27ed1b95edd952d8eab3055cdc576a860593308c426f7ea73e01bd05fb20a4fcb64b10945e1684da67a8367826535344ad25057b4840e138909668c2423669b51f2fec631fd7e919f6e8b82ee293878894cac6a58b21f2168ba6335197e39e587fd60076a369f0b8e779c045c507654fbb98f5ffc998f720ab48bdbfe6d397aa63c7209b45068e24b65371180ff6d775851b2aaceac393082920fffb9e8b6999c682875bd0eff231dfaadf + +Sign-Message = RSA-SHA3-512:RSA-2048 +Input = "Hello World" +Output = 4681312b0e27e4e5f2dd3165ea5bdc98210d4883709a842239cef72099d71855fc322c3d2f74a7e7357647de153c22e4c4f9a0e4f1ce9b7f993242df5ee778ca949e6e184551e87e0aac8440ae990ef76a14f6056a16181390ad3a150bfdbb985cfe4cca3255b5eb0871116654d59fc89f69adb46c307b927c51a5f34069a2f43c854fde8e2df0ded10f8e257d1d800aa44bf31981f93c062128cc551ad7f5f7ba68e9d7c917c8fc51bcda3ce9192680c1e5308bd5c571ac0a5ae7347a897e8698ea94059562cd3035e3ed5fcf6c4ca8c20f58a079dfcdb175242a5726237d1b92378ec7dc4f2db09a0fbd62d1ab6d1a3d0be7afd34ed9c3ecd1bc5a3d2c448c From 024274ee11e6a805e41b08363d64b24720476fa3 Mon Sep 17 00:00:00 2001 From: Maxwell Moyer-McKee Date: Thu, 23 Apr 2026 22:38:57 +0000 Subject: [PATCH 11/12] PR comments --- ScosslCommon/inc/scossl_ecc.h | 6 +++--- .../src/signature/p_scossl_ecdsa_sigalg_signature.c | 6 ++++++ .../src/signature/p_scossl_rsa_sigalg_signature.c | 9 ++++++++- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/ScosslCommon/inc/scossl_ecc.h b/ScosslCommon/inc/scossl_ecc.h index 085c85c7..0e2512ee 100644 --- a/ScosslCommon/inc/scossl_ecc.h +++ b/ScosslCommon/inc/scossl_ecc.h @@ -39,9 +39,9 @@ SIZE_T scossl_ecdsa_size(_In_ PCSYMCRYPT_ECURVE curve); SCOSSL_STATUS scossl_ecdsa_sign(_In_ PSYMCRYPT_ECKEY key, _In_ PCSYMCRYPT_ECURVE curve, _In_reads_bytes_(cbHashValue) PCBYTE pbHashValue, SIZE_T cbHashValue, _Out_writes_bytes_opt_(*pcbSignature) PBYTE pbSignature, _Out_ unsigned int* pcbSignature); -SCOSSL_STATUS scossl_ecdsa_verify(_In_ PSYMCRYPT_ECKEY key, _In_ PCSYMCRYPT_ECURVE curve, - _In_reads_bytes_(cbHashValue) PCBYTE pbHashValue, SIZE_T cbHashValue, - _In_reads_bytes_(pcbSignature) PCBYTE pbSignature, SIZE_T pcbSignature); +int scossl_ecdsa_verify(_In_ PSYMCRYPT_ECKEY key, _In_ PCSYMCRYPT_ECURVE curve, + _In_reads_bytes_(cbHashValue) PCBYTE pbHashValue, SIZE_T cbHashValue, + _In_reads_bytes_(pcbSignature) PCBYTE pbSignature, SIZE_T pcbSignature); #ifdef __cplusplus } diff --git a/SymCryptProvider/src/signature/p_scossl_ecdsa_sigalg_signature.c b/SymCryptProvider/src/signature/p_scossl_ecdsa_sigalg_signature.c index 461e6f9c..0954990c 100644 --- a/SymCryptProvider/src/signature/p_scossl_ecdsa_sigalg_signature.c +++ b/SymCryptProvider/src/signature/p_scossl_ecdsa_sigalg_signature.c @@ -157,6 +157,12 @@ static int p_scossl_ecdsa_sigalg_verify_message_final(_In_ SCOSSL_ECDSA_CTX *ctx return 0; } + if (ctx->pbSignature == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SIGNATURE_SIZE); + return 0; + } + if (!EVP_DigestFinal_ex(ctx->mdctx, digest, &cbDigest)) { return 0; diff --git a/SymCryptProvider/src/signature/p_scossl_rsa_sigalg_signature.c b/SymCryptProvider/src/signature/p_scossl_rsa_sigalg_signature.c index ade35ce8..881c6748 100644 --- a/SymCryptProvider/src/signature/p_scossl_rsa_sigalg_signature.c +++ b/SymCryptProvider/src/signature/p_scossl_rsa_sigalg_signature.c @@ -122,7 +122,7 @@ static SCOSSL_STATUS p_scossl_rsa_sigalg_sign_message_final(_In_ SCOSSL_RSA_SIGN ERR_raise(ERR_LIB_PROV, PROV_R_FINAL_CALL_OUT_OF_ORDER); return SCOSSL_FAILURE; } -\ + if (sig != NULL) { if (!EVP_DigestFinal_ex(ctx->mdctx, abDigest, &cbDigest)) @@ -155,6 +155,12 @@ static int p_scossl_rsa_sigalg_verify_message_final(_In_ SCOSSL_RSA_SIGN_CTX *ct return SCOSSL_FAILURE; } + if (ctx->pbSignature == NULL) + { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SIGNATURE_SIZE); + return SCOSSL_FAILURE; + } + if (!EVP_DigestFinal_ex(ctx->mdctx, abDigest, &cbDigest)) { return SCOSSL_FAILURE; @@ -220,6 +226,7 @@ static SCOSSL_STATUS p_scossl_rsa_sigalg_verify(_In_ SCOSSL_RSA_SIGN_CTX *ctx, if (ctx->operation == EVP_PKEY_OP_VERIFYMSG) { OPENSSL_free(ctx->pbSignature); + ctx->pbSignature = NULL; ctx->cbSignature = 0; if (siglen == 0 || From 797acb0405f2af9b262e36cac7a446523fd36643 Mon Sep 17 00:00:00 2001 From: Maxwell Moyer-McKee Date: Thu, 23 Apr 2026 23:27:46 +0000 Subject: [PATCH 12/12] Correct digest too short test --- EvpTestRecipes/3.5/evppkey_rsa_sigalg.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EvpTestRecipes/3.5/evppkey_rsa_sigalg.txt b/EvpTestRecipes/3.5/evppkey_rsa_sigalg.txt index 04b197c1..81e2d990 100644 --- a/EvpTestRecipes/3.5/evppkey_rsa_sigalg.txt +++ b/EvpTestRecipes/3.5/evppkey_rsa_sigalg.txt @@ -83,7 +83,7 @@ Result = KEYOP_ERROR # Digest too short Sign = RSA-SHA1:RSA-2048 -Input = "0123456789ABCDEF12345" +Input = "0123456789ABCDEF123" Output = 00 Result = KEYOP_ERROR