From fb14dc105a46576862fb7b48f21513af4059cdbb Mon Sep 17 00:00:00 2001 From: liumegan Date: Thu, 5 Jun 2025 23:28:46 +0000 Subject: [PATCH 1/4] SCOSSL: support EVP_PKEY_verify_recover --- SslPlay/SslPlay.cpp | 63 +++++++- .../src/signature/p_scossl_rsa_signature.c | 146 ++++++++++++++++++ 2 files changed, 208 insertions(+), 1 deletion(-) diff --git a/SslPlay/SslPlay.cpp b/SslPlay/SslPlay.cpp index 10c660f9..20fc5bbc 100644 --- a/SslPlay/SslPlay.cpp +++ b/SslPlay/SslPlay.cpp @@ -523,6 +523,9 @@ void TestRsaSignVerify( unsigned char message_digest[64]; size_t message_digest_len = digest_length; int ret = 0; + EVP_PKEY_CTX *pRecoverCtx = NULL; + unsigned char recovered[512]; + size_t recovered_len = sizeof(recovered); if (EVP_PKEY_bits(signingKey) <= 512 && EVP_MD_size(digest) >= 32) @@ -632,6 +635,62 @@ void TestRsaSignVerify( printf("EVP_PKEY_verify succeeded\n"); } + // + // Verify-Recover with Public Key + // + if (padding != RSA_PKCS1_PSS_PADDING) { + printf("\nTesting EVP_PKEY_verify_recover* Functions\n\n"); + + EVP_PKEY_CTX *pRecoverCtx = EVP_PKEY_CTX_new(verificationKey, NULL); + if (!pRecoverCtx) { + handleOpenSSLError("EVP_PKEY_CTX_new failed"); + goto end; + } + + if (EVP_PKEY_verify_recover_init(pRecoverCtx) <= 0) { + handleOpenSSLError("EVP_PKEY_verify_recover_init failed"); + EVP_PKEY_CTX_free(pRecoverCtx); + goto end; + } + + if (EVP_PKEY_CTX_set_rsa_padding(pRecoverCtx, padding) <= 0) { + handleOpenSSLError("EVP_PKEY_CTX_set_rsa_padding failed"); + EVP_PKEY_CTX_free(pRecoverCtx); + goto end; + } + + if (EVP_PKEY_CTX_set_signature_md(pRecoverCtx, digest) <= 0) { + handleOpenSSLError("EVP_PKEY_CTX_set_signature_md failed"); + EVP_PKEY_CTX_free(pRecoverCtx); + goto end; + } + + unsigned char recovered[256]; // adjust size based on key length + size_t recovered_len = sizeof(recovered); + + if (EVP_PKEY_verify_recover(pRecoverCtx, recovered, &recovered_len, signature, signature_len) <= 0) { + printf("EVP_PKEY_verify_recover failed\n"); + } else { + + printf("Message Digest: (%ld)\n", message_digest_len); + BIO_dump_fp(stdout, (const char *)message_digest, message_digest_len); + + printf("Recovered data: (%ld)\n", recovered_len); + BIO_dump_fp(stdout, (const char *)recovered, recovered_len); + + if (recovered_len == message_digest_len && + memcmp(recovered, message_digest, message_digest_len) == 0) { + printf("Recovery successful\n"); + } else { + handleError("Recovery failed: recovered data does not match original message digest\n"); + } + } + + EVP_PKEY_CTX_free(pRecoverCtx); + } else { + printf("Skipping verify-recover: RSA_PSS padding is not supported\n"); + } + end: if (pSignContext) EVP_PKEY_CTX_free(pSignContext); @@ -639,6 +698,8 @@ void TestRsaSignVerify( EVP_PKEY_CTX_free(pVerifyContext); if (signature) OPENSSL_free(signature); + if (pRecoverCtx) + EVP_PKEY_CTX_free(pRecoverCtx); printf("%s", SeparatorLine); return; } @@ -782,7 +843,7 @@ void TestRsaDigestSignVerify( } else { printf("Signature Verified\n"); } - + end: if (RSASignCtx) EVP_MD_CTX_free(RSASignCtx); diff --git a/SymCryptProvider/src/signature/p_scossl_rsa_signature.c b/SymCryptProvider/src/signature/p_scossl_rsa_signature.c index 205310c0..445c0dc9 100644 --- a/SymCryptProvider/src/signature/p_scossl_rsa_signature.c +++ b/SymCryptProvider/src/signature/p_scossl_rsa_signature.c @@ -15,6 +15,8 @@ extern "C" { #endif +#define SCOSSL_MAX_RSA_MODULUS_SIZE (512) + typedef struct { SCOSSL_PROV_RSA_KEY_CTX *keyCtx; @@ -221,6 +223,12 @@ 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_verify_recover_init(_Inout_ SCOSSL_RSA_SIGN_CTX *ctx, _In_ SCOSSL_PROV_RSA_KEY_CTX *keyCtx, + _In_ const OSSL_PARAM params[]) +{ + return p_scossl_rsa_signverify_init(ctx, keyCtx, params, EVP_PKEY_OP_VERIFYRECOVER); +} + 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) @@ -276,6 +284,7 @@ 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) @@ -313,6 +322,141 @@ static SCOSSL_STATUS p_scossl_rsa_verify(_In_ SCOSSL_RSA_SIGN_CTX *ctx, return SCOSSL_FAILURE; } + +static SCOSSL_STATUS p_scossl_rsa_verify_recover(_In_ SCOSSL_RSA_SIGN_CTX *ctx, + _Out_writes_bytes_(*routlen) unsigned char *rout, size_t *routlen, + size_t routsize, + _In_reads_bytes_(siglen) const unsigned char *sig, size_t siglen) +{ + SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; + SIZE_T cbModulus = 0, cbResult = 0; + int mdnid = ctx->mdInfo == NULL ? NID_undef : ctx->mdInfo->id; + + if (ctx == NULL || ctx->keyCtx == NULL || sig == NULL || routlen == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); + return SCOSSL_FAILURE; + } + + if (ctx->operation != EVP_PKEY_OP_VERIFYRECOVER) + { + ERR_raise(ERR_LIB_PROV, ERR_R_OPERATION_FAIL); + return SCOSSL_FAILURE; + } + + cbModulus = SymCryptRsakeySizeofModulus(ctx->keyCtx->key); + + if (rout == NULL) + { + *routlen = cbModulus; + return SCOSSL_SUCCESS; + } + + if (routsize < cbModulus) + { + ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + return SCOSSL_FAILURE; + } + + if (ctx->mdInfo != NULL) + { + switch (ctx->padding) + { + case RSA_X931_PADDING: + { + unsigned char tbuf[SCOSSL_MAX_RSA_MODULUS_SIZE]; + if (cbModulus > sizeof(tbuf)) { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + return SCOSSL_FAILURE; + } + + scError = SymCryptRsaRawDecrypt( + ctx->keyCtx->key, + sig, + siglen, + SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, + 0, + tbuf, + cbModulus); + cbResult = cbModulus; + + if (scError != SYMCRYPT_NO_ERROR) { + SCOSSL_LOG_SYMCRYPT_ERROR(SCOSSL_ERR_F_RSA_DECRYPT, + "SymCryptRsaRawDecrypt failed", scError); + return SCOSSL_FAILURE; + } + + if (cbResult < 1 || tbuf[cbResult - 1] != RSA_X931_hash_id(mdnid)) { + ERR_raise(ERR_LIB_PROV, PROV_R_ALGORITHM_MISMATCH); + return SCOSSL_FAILURE; + } + + cbResult--; // exclude hash ID byte + + if (cbResult != (SIZE_T)EVP_MD_get_size(ctx->md)) { + ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH, + "Should be %d, but got %zu", + EVP_MD_get_size(ctx->md), cbResult); + return SCOSSL_FAILURE; + } + + if (cbResult > routsize) { + ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + return SCOSSL_FAILURE; + } + + memcpy(rout, tbuf, cbResult); + *routlen = cbResult; + break; + } + + case RSA_PKCS1_PADDING: + { + size_t tmp_len = routsize; + if (!scossl_rsa_pkcs1_verify(ctx->keyCtx->key, mdnid, rout, tmp_len, sig, siglen)) { + ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB); + return SCOSSL_FAILURE; + } + *routlen = tmp_len; + break; + } + + default: + ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE, + "Only X.931 or PKCS#1 v1.5 padding allowed"); + return SCOSSL_FAILURE; + } + } + else + { + if (routsize < cbModulus) { + ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + return SCOSSL_FAILURE; + } + + scError = SymCryptRsaRawDecrypt( + ctx->keyCtx->key, + sig, + siglen, + SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, + 0, + rout, + cbModulus); + cbResult = cbModulus; + + if (scError != SYMCRYPT_NO_ERROR) { + SCOSSL_LOG_SYMCRYPT_ERROR(SCOSSL_ERR_F_RSA_DECRYPT, + "SymCryptRsaRawDecrypt failed", scError); + return SCOSSL_FAILURE; + } + + *routlen = cbResult; + } + + return SCOSSL_SUCCESS; +} + + 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) { @@ -1072,6 +1216,8 @@ const OSSL_DISPATCH p_scossl_rsa_signature_functions[] = { {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_VERIFY_RECOVER_INIT, (void (*)(void))p_scossl_rsa_verify_recover_init}, + {OSSL_FUNC_SIGNATURE_VERIFY_RECOVER, (void (*)(void))p_scossl_rsa_verify_recover}, {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}, From fcc10eaa06c7edd9ea62e0c76910ed828a975814 Mon Sep 17 00:00:00 2001 From: liumegan Date: Sat, 7 Jun 2025 00:29:40 +0000 Subject: [PATCH 2/4] Signature Recover: Sslplay worked. recover framework okay. needs to add function to call RawEncrypt and parse buffer --- SslPlay/SslPlay.cpp | 7 +- .../src/signature/p_scossl_rsa_signature.c | 110 ++++++------------ 2 files changed, 37 insertions(+), 80 deletions(-) diff --git a/SslPlay/SslPlay.cpp b/SslPlay/SslPlay.cpp index 20fc5bbc..d9104355 100644 --- a/SslPlay/SslPlay.cpp +++ b/SslPlay/SslPlay.cpp @@ -649,19 +649,16 @@ void TestRsaSignVerify( if (EVP_PKEY_verify_recover_init(pRecoverCtx) <= 0) { handleOpenSSLError("EVP_PKEY_verify_recover_init failed"); - EVP_PKEY_CTX_free(pRecoverCtx); goto end; } if (EVP_PKEY_CTX_set_rsa_padding(pRecoverCtx, padding) <= 0) { handleOpenSSLError("EVP_PKEY_CTX_set_rsa_padding failed"); - EVP_PKEY_CTX_free(pRecoverCtx); goto end; } if (EVP_PKEY_CTX_set_signature_md(pRecoverCtx, digest) <= 0) { handleOpenSSLError("EVP_PKEY_CTX_set_signature_md failed"); - EVP_PKEY_CTX_free(pRecoverCtx); goto end; } @@ -669,7 +666,7 @@ void TestRsaSignVerify( size_t recovered_len = sizeof(recovered); if (EVP_PKEY_verify_recover(pRecoverCtx, recovered, &recovered_len, signature, signature_len) <= 0) { - printf("EVP_PKEY_verify_recover failed\n"); + handleError("EVP_PKEY_verify_recover failed\n"); } else { printf("Message Digest: (%ld)\n", message_digest_len); @@ -685,8 +682,6 @@ void TestRsaSignVerify( handleError("Recovery failed: recovered data does not match original message digest\n"); } } - - EVP_PKEY_CTX_free(pRecoverCtx); } else { printf("Skipping verify-recover: RSA_PSS padding is not supported\n"); } diff --git a/SymCryptProvider/src/signature/p_scossl_rsa_signature.c b/SymCryptProvider/src/signature/p_scossl_rsa_signature.c index 445c0dc9..a01314fa 100644 --- a/SymCryptProvider/src/signature/p_scossl_rsa_signature.c +++ b/SymCryptProvider/src/signature/p_scossl_rsa_signature.c @@ -319,120 +319,80 @@ static SCOSSL_STATUS p_scossl_rsa_verify(_In_ SCOSSL_RSA_SIGN_CTX *ctx, ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE); } - return SCOSSL_FAILURE; + return SCOSSL_FAILURE; } - static SCOSSL_STATUS p_scossl_rsa_verify_recover(_In_ SCOSSL_RSA_SIGN_CTX *ctx, _Out_writes_bytes_(*routlen) unsigned char *rout, size_t *routlen, size_t routsize, _In_reads_bytes_(siglen) const unsigned char *sig, size_t siglen) { SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; - SIZE_T cbModulus = 0, cbResult = 0; - int mdnid = ctx->mdInfo == NULL ? NID_undef : ctx->mdInfo->id; + SIZE_T cbModulus = 0; - if (ctx == NULL || ctx->keyCtx == NULL || sig == NULL || routlen == NULL) - { + if (ctx == NULL || ctx->keyCtx == NULL || sig == NULL || routlen == NULL) { ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); return SCOSSL_FAILURE; } - if (ctx->operation != EVP_PKEY_OP_VERIFYRECOVER) - { + if (ctx->operation != EVP_PKEY_OP_VERIFYRECOVER) { ERR_raise(ERR_LIB_PROV, ERR_R_OPERATION_FAIL); return SCOSSL_FAILURE; } cbModulus = SymCryptRsakeySizeofModulus(ctx->keyCtx->key); + printf("\n###### Megan: cbModulus = %lu, routsize = %lu, *routlen = %lu, siglen = %lu\n", + cbModulus, routsize, *routlen, siglen); - if (rout == NULL) - { + printf("sig = "); + for (size_t i = 0; i < siglen; i++) { + printf("%02x", sig[i]); + } + printf("\n"); + + if (rout == NULL) { *routlen = cbModulus; return SCOSSL_SUCCESS; } - if (routsize < cbModulus) - { + if (routsize < cbModulus) { ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); return SCOSSL_FAILURE; } - if (ctx->mdInfo != NULL) - { - switch (ctx->padding) - { - case RSA_X931_PADDING: - { - unsigned char tbuf[SCOSSL_MAX_RSA_MODULUS_SIZE]; - if (cbModulus > sizeof(tbuf)) { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); - return SCOSSL_FAILURE; - } + if (ctx->md != NULL) { + switch (ctx->padding) { + case RSA_PKCS1_PADDING: + printf("\n###### Megan: PKCS1 verify-recover path, routsize = %lu, cbModulus = %lu\n", routsize, cbModulus); - scError = SymCryptRsaRawDecrypt( + // Perform public key operation to recover encoded DigestInfo + scError = SymCryptRsaRawEncrypt( ctx->keyCtx->key, sig, siglen, SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, 0, - tbuf, - cbModulus); - cbResult = cbModulus; + rout, + cbModulus + ); if (scError != SYMCRYPT_NO_ERROR) { - SCOSSL_LOG_SYMCRYPT_ERROR(SCOSSL_ERR_F_RSA_DECRYPT, - "SymCryptRsaRawDecrypt failed", scError); - return SCOSSL_FAILURE; - } - - if (cbResult < 1 || tbuf[cbResult - 1] != RSA_X931_hash_id(mdnid)) { - ERR_raise(ERR_LIB_PROV, PROV_R_ALGORITHM_MISMATCH); - return SCOSSL_FAILURE; - } - - cbResult--; // exclude hash ID byte - - if (cbResult != (SIZE_T)EVP_MD_get_size(ctx->md)) { - ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH, - "Should be %d, but got %zu", - EVP_MD_get_size(ctx->md), cbResult); - return SCOSSL_FAILURE; - } - - if (cbResult > routsize) { - ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + printf("\n###### Megan: SymCryptRsaRawEncrypt (verify-recover) failed 0x%x\n", scError); + SCOSSL_LOG_SYMCRYPT_ERROR(SCOSSL_ERR_F_RSA_ENCRYPT, + "SymCryptRsaRawEncrypt failed", scError); return SCOSSL_FAILURE; } - memcpy(rout, tbuf, cbResult); - *routlen = cbResult; + *routlen = cbModulus; break; - } - - case RSA_PKCS1_PADDING: - { - size_t tmp_len = routsize; - if (!scossl_rsa_pkcs1_verify(ctx->keyCtx->key, mdnid, rout, tmp_len, sig, siglen)) { - ERR_raise(ERR_LIB_PROV, ERR_R_RSA_LIB); - return SCOSSL_FAILURE; - } - *routlen = tmp_len; - break; - } default: ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE, - "Only X.931 or PKCS#1 v1.5 padding allowed"); - return SCOSSL_FAILURE; - } - } - else - { - if (routsize < cbModulus) { - ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + "Only PKCS#1 v1.5 padding allowed"); return SCOSSL_FAILURE; } + } else { + printf("\n###### Megan: raw decrypt path (no digest specified)\n"); scError = SymCryptRsaRawDecrypt( ctx->keyCtx->key, @@ -441,22 +401,24 @@ static SCOSSL_STATUS p_scossl_rsa_verify_recover(_In_ SCOSSL_RSA_SIGN_CTX *ctx, SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, 0, rout, - cbModulus); - cbResult = cbModulus; + cbModulus + ); if (scError != SYMCRYPT_NO_ERROR) { + printf("\n###### Megan: SymCryptRsaRawDecrypt failed 0x%x\n", scError); SCOSSL_LOG_SYMCRYPT_ERROR(SCOSSL_ERR_F_RSA_DECRYPT, - "SymCryptRsaRawDecrypt failed", scError); + "SymCryptRsaRawDecrypt failed", scError); return SCOSSL_FAILURE; } - *routlen = cbResult; + *routlen = cbModulus; } return SCOSSL_SUCCESS; } + 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) { From 38ba776d0b310f4126cca7e5d866a52371180ec5 Mon Sep 17 00:00:00 2001 From: liumegan Date: Fri, 13 Jun 2025 00:21:40 +0000 Subject: [PATCH 3/4] recover: worked partially --- .../src/signature/p_scossl_rsa_signature.c | 152 +++++++++++++++++- 1 file changed, 145 insertions(+), 7 deletions(-) diff --git a/SymCryptProvider/src/signature/p_scossl_rsa_signature.c b/SymCryptProvider/src/signature/p_scossl_rsa_signature.c index cf2920a4..19728aac 100644 --- a/SymCryptProvider/src/signature/p_scossl_rsa_signature.c +++ b/SymCryptProvider/src/signature/p_scossl_rsa_signature.c @@ -321,6 +321,144 @@ static SCOSSL_STATUS p_scossl_rsa_verify(_In_ SCOSSL_RSA_SIGN_CTX *ctx, return SCOSSL_FAILURE; } +#define SSL_SIG_LENGTH 36 + +static SCOSSL_STATUS scossl_rsa_verify_recover( + _In_ SCOSSL_RSA_SIGN_CTX *ctx, + _Out_writes_bytes_(*routlen) unsigned char *rout, + size_t *routlen, + _In_reads_bytes_(siglen) const unsigned char *sig, + size_t siglen) +{ + PBYTE decrypted = NULL; + PBYTE encoded = NULL; + SIZE_T encodedLen = 0; + int digestLen = 0; + const unsigned char *digest = NULL; + SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; + SCOSSL_STATUS ret = SCOSSL_FAILURE; + SIZE_T cbModulus = 0; + + if (ctx == NULL || ctx->keyCtx->key == NULL || routlen == NULL || sig == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); + return SCOSSL_FAILURE; + } + + cbModulus = SymCryptRsakeySizeofModulus(ctx->keyCtx->key); + + if (siglen != cbModulus) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DATA); + return SCOSSL_FAILURE; + } + + decrypted = OPENSSL_zalloc(cbModulus); + if (decrypted == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return SCOSSL_FAILURE; + } + + // Perform public key operation to recover encoded DigestInfo + scError = SymCryptRsaRawEncrypt( + ctx->keyCtx->key, + sig, + siglen, + SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, + 0, + decrypted, + cbModulus + ); + + if (scError != SYMCRYPT_NO_ERROR) { + printf("\n###### Megan: SymCryptRsaRawEncrypt (verify-recover) failed 0x%x\n", scError); + SCOSSL_LOG_SYMCRYPT_ERROR(SCOSSL_ERR_F_RSA_ENCRYPT, + "SymCryptRsaRawEncrypt failed", scError); + return SCOSSL_FAILURE; + } +#if 0 + // Special case: TLS MD5+SHA1 + if (ctx->mdInfo->id == NID_md5_sha1) { + if (modSize != SSL_SIG_LENGTH) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH); + goto cleanup; + } + + if (rout != NULL) { + memcpy(rout, decrypted, SSL_SIG_LENGTH); + *routlen = SSL_SIG_LENGTH; + } else { + if (*routlen != SSL_SIG_LENGTH) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH); + goto cleanup; + } + if (memcmp(rout, decrypted, SSL_SIG_LENGTH) != 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISMATCHING_DOMAIN_PARAMETERS); + goto cleanup; + } + } + SCOSSL_PROV_LOG_ERROR(SCOSSL_ERR_R_NOT_FIPS_ALGORITHM, "Using hash algorithm MD5+SHA1 which is not FIPS compliant"); + OPENSSL_clear_free(decrypted, modSize); + return SCOSSL_SUCCESS; + } + + // Special case: MDC2 + if (ctx->mdInfo->id == NID_mdc2 && + modSize == 18 && + decrypted[0] == 0x04 && decrypted[1] == 0x10) { + if (rout != NULL) { + memcpy(rout, decrypted + 2, 16); + *routlen = 16; + } else { + if (*routlen != 16) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH); + goto cleanup; + } + if (memcmp(rout, decrypted + 2, 16) != 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISMATCHING_DOMAIN_PARAMETERS); + goto cleanup; + } + } + SCOSSL_PROV_LOG_ERROR(SCOSSL_ERR_R_NOT_FIPS_ALGORITHM, "Using hash algorithm MDC2 which is not FIPS compliant"); + OPENSSL_clear_free(decrypted, modSize); + return SCOSSL_SUCCESS; + } +#endif + // General case: PKCS#1 v1.5 + printf("\n###### Megan: SymCryptRsaRawEncrypt (verify-recover) is good, cbModulus is %ld, in General case: PKCS#1 v1.5\n", cbModulus); + digestLen = scossl_get_expected_hash_length(ctx->mdInfo->id); + printf("\n##### digestLen is %d", digestLen); + if (digestLen <= 0) { + ERR_raise(ERR_LIB_RSA, RSA_R_UNKNOWN_ALGORITHM_TYPE); + goto cleanup; + } + + if (rout != NULL) { + if (*routlen < (size_t)digestLen) { + *routlen = digestLen; + ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + goto cleanup; + } + digest = decrypted + cbModulus - digestLen; + } else { + digest = rout; + } +printf("\n##### Digest bytes: "); +for (int i = 0; i < digestLen; i++) { + printf("%02x", digest[i]); +} +printf("\n"); + + if (rout != NULL) { + memcpy(rout, digest, digestLen); + *routlen = digestLen; + } + + ret = SCOSSL_SUCCESS; + +cleanup: + OPENSSL_clear_free(encoded, encodedLen); + OPENSSL_clear_free(decrypted, cbModulus); + return ret; +} static SCOSSL_STATUS p_scossl_rsa_verify_recover(_In_ SCOSSL_RSA_SIGN_CTX *ctx, _Out_writes_bytes_(*routlen) unsigned char *rout, size_t *routlen, @@ -364,7 +502,7 @@ static SCOSSL_STATUS p_scossl_rsa_verify_recover(_In_ SCOSSL_RSA_SIGN_CTX *ctx, switch (ctx->padding) { case RSA_PKCS1_PADDING: printf("\n###### Megan: PKCS1 verify-recover path, routsize = %lu, cbModulus = %lu\n", routsize, cbModulus); - +/* // Perform public key operation to recover encoded DigestInfo scError = SymCryptRsaRawEncrypt( ctx->keyCtx->key, @@ -379,13 +517,13 @@ static SCOSSL_STATUS p_scossl_rsa_verify_recover(_In_ SCOSSL_RSA_SIGN_CTX *ctx, if (scError != SYMCRYPT_NO_ERROR) { printf("\n###### Megan: SymCryptRsaRawEncrypt (verify-recover) failed 0x%x\n", scError); SCOSSL_LOG_SYMCRYPT_ERROR(SCOSSL_ERR_F_RSA_ENCRYPT, - "SymCryptRsaRawEncrypt failed", scError); + "SymCryptRsaRawEncrypt failed 0x%x", scError); return SCOSSL_FAILURE; } - - *routlen = cbModulus; - break; - + printf("\n###### Megan: SymCryptRsaRawEncrypt (verify-recover) is good, cbModulus is %ld\n", cbModulus); + *routlen = cbModulus; + return scossl_rsa_pkcs1_verify(ctx->keyCtx->key, mdnid, rout, cbModulus, sig, siglen); */ + return scossl_rsa_verify_recover(ctx, rout, routlen, sig, siglen); default: ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE, "Only PKCS#1 v1.5 padding allowed"); @@ -407,7 +545,7 @@ static SCOSSL_STATUS p_scossl_rsa_verify_recover(_In_ SCOSSL_RSA_SIGN_CTX *ctx, if (scError != SYMCRYPT_NO_ERROR) { printf("\n###### Megan: SymCryptRsaRawDecrypt failed 0x%x\n", scError); SCOSSL_LOG_SYMCRYPT_ERROR(SCOSSL_ERR_F_RSA_DECRYPT, - "SymCryptRsaRawDecrypt failed", scError); + "SymCryptRsaRawDecrypt failed 0x%x", scError); return SCOSSL_FAILURE; } From ea0da29512dcd5f8540bb8bd7c6cbca1d6310008 Mon Sep 17 00:00:00 2001 From: liumegan Date: Fri, 13 Jun 2025 17:33:02 +0000 Subject: [PATCH 4/4] SigVerifyRecover: code mostly working, need review and cleanup --- .../src/signature/p_scossl_rsa_signature.c | 48 ++++++------------- 1 file changed, 15 insertions(+), 33 deletions(-) diff --git a/SymCryptProvider/src/signature/p_scossl_rsa_signature.c b/SymCryptProvider/src/signature/p_scossl_rsa_signature.c index 19728aac..44f20ff0 100644 --- a/SymCryptProvider/src/signature/p_scossl_rsa_signature.c +++ b/SymCryptProvider/src/signature/p_scossl_rsa_signature.c @@ -345,7 +345,7 @@ static SCOSSL_STATUS scossl_rsa_verify_recover( } cbModulus = SymCryptRsakeySizeofModulus(ctx->keyCtx->key); - +printf("\n###### Megan: Entering scossl_rsa_verify_recover()\n"); if (siglen != cbModulus) { ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DATA); return SCOSSL_FAILURE; @@ -374,14 +374,14 @@ static SCOSSL_STATUS scossl_rsa_verify_recover( "SymCryptRsaRawEncrypt failed", scError); return SCOSSL_FAILURE; } -#if 0 - // Special case: TLS MD5+SHA1 +printf("\n###### Megan: SymCryptRsaRawEncrypt (verify-recover) is good\n"); + // Special case: TLS MD5+SHA1 !!!!!! this one doesn't have test case !!!!!!!!!!! if (ctx->mdInfo->id == NID_md5_sha1) { - if (modSize != SSL_SIG_LENGTH) { + if (cbModulus != SSL_SIG_LENGTH) { ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH); goto cleanup; } - +printf("\n###### Megan: SymCryptRsaRawEncrypt (verify-recover) is good, cbModulus is %ld, in TLS MD5+SHA1 case\n", cbModulus); if (rout != NULL) { memcpy(rout, decrypted, SSL_SIG_LENGTH); *routlen = SSL_SIG_LENGTH; @@ -396,14 +396,15 @@ static SCOSSL_STATUS scossl_rsa_verify_recover( } } SCOSSL_PROV_LOG_ERROR(SCOSSL_ERR_R_NOT_FIPS_ALGORITHM, "Using hash algorithm MD5+SHA1 which is not FIPS compliant"); - OPENSSL_clear_free(decrypted, modSize); + OPENSSL_clear_free(decrypted, cbModulus); return SCOSSL_SUCCESS; } - // Special case: MDC2 + // Special case: MDC2 !!!!!! this one doesn't have test case !!!!!!!!!!! if (ctx->mdInfo->id == NID_mdc2 && - modSize == 18 && + cbModulus == 18 && decrypted[0] == 0x04 && decrypted[1] == 0x10) { + printf("\n###### Megan: SymCryptRsaRawEncrypt (verify-recover) is good, cbModulus is %ld, in MDC2 case\n", cbModulus); if (rout != NULL) { memcpy(rout, decrypted + 2, 16); *routlen = 16; @@ -418,10 +419,10 @@ static SCOSSL_STATUS scossl_rsa_verify_recover( } } SCOSSL_PROV_LOG_ERROR(SCOSSL_ERR_R_NOT_FIPS_ALGORITHM, "Using hash algorithm MDC2 which is not FIPS compliant"); - OPENSSL_clear_free(decrypted, modSize); + OPENSSL_clear_free(decrypted, cbModulus); return SCOSSL_SUCCESS; } -#endif + // General case: PKCS#1 v1.5 printf("\n###### Megan: SymCryptRsaRawEncrypt (verify-recover) is good, cbModulus is %ld, in General case: PKCS#1 v1.5\n", cbModulus); digestLen = scossl_get_expected_hash_length(ctx->mdInfo->id); @@ -492,8 +493,9 @@ static SCOSSL_STATUS p_scossl_rsa_verify_recover(_In_ SCOSSL_RSA_SIGN_CTX *ctx, *routlen = cbModulus; return SCOSSL_SUCCESS; } - +//!!!!!!!!!!!!!!!!!!!! issue here, why there is a test case with cbModulus is 257, and routsize is 256? !!!!!!!!!!!!!!! if (routsize < cbModulus) { + printf("\n###### Megan: cbModulus %ld > routsize %lu\n", cbModulus, routsize); ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); return SCOSSL_FAILURE; } @@ -501,30 +503,10 @@ static SCOSSL_STATUS p_scossl_rsa_verify_recover(_In_ SCOSSL_RSA_SIGN_CTX *ctx, if (ctx->md != NULL) { switch (ctx->padding) { case RSA_PKCS1_PADDING: - printf("\n###### Megan: PKCS1 verify-recover path, routsize = %lu, cbModulus = %lu\n", routsize, cbModulus); -/* - // Perform public key operation to recover encoded DigestInfo - scError = SymCryptRsaRawEncrypt( - ctx->keyCtx->key, - sig, - siglen, - SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, - 0, - rout, - cbModulus - ); - - if (scError != SYMCRYPT_NO_ERROR) { - printf("\n###### Megan: SymCryptRsaRawEncrypt (verify-recover) failed 0x%x\n", scError); - SCOSSL_LOG_SYMCRYPT_ERROR(SCOSSL_ERR_F_RSA_ENCRYPT, - "SymCryptRsaRawEncrypt failed 0x%x", scError); - return SCOSSL_FAILURE; - } - printf("\n###### Megan: SymCryptRsaRawEncrypt (verify-recover) is good, cbModulus is %ld\n", cbModulus); - *routlen = cbModulus; - return scossl_rsa_pkcs1_verify(ctx->keyCtx->key, mdnid, rout, cbModulus, sig, siglen); */ + printf("\n###### Megan: call scossl_rsa_verify_recover(), routsize = %lu, cbModulus = %lu\n", routsize, cbModulus); return scossl_rsa_verify_recover(ctx, rout, routlen, sig, siglen); default: + printf("\n###### Megan: Only PKCS#1 v1.5 padding allowed, routsize = %lu, cbModulus = %lu\n", routsize, cbModulus); ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE, "Only PKCS#1 v1.5 padding allowed"); return SCOSSL_FAILURE;