diff --git a/SymCryptProvider/src/keymgmt/p_scossl_rsa_keymgmt.c b/SymCryptProvider/src/keymgmt/p_scossl_rsa_keymgmt.c index 04d2ca6b..1ded4a35 100644 --- a/SymCryptProvider/src/keymgmt/p_scossl_rsa_keymgmt.c +++ b/SymCryptProvider/src/keymgmt/p_scossl_rsa_keymgmt.c @@ -955,6 +955,69 @@ static BOOL p_scossl_rsa_keymgmt_has(_In_ SCOSSL_PROV_RSA_KEY_CTX *keyCtx, int s return ret; } +static SCOSSL_STATUS p_scossl_rsa_keymgmt_validate(_In_ SCOSSL_PROV_RSA_KEY_CTX *keyCtx, int selection) +{ + SCOSSL_STATUS success = SCOSSL_SUCCESS; + UINT64 pubExp = 0; + PBYTE pbModulus = NULL; + PBYTE pbPrivateExponent = NULL; + SYMCRYPT_ERROR scError; + + UINT32 cbModulus = SymCryptRsakeySizeofModulus(keyCtx->key); +printf("\n Megan is here #####################"); + if (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) + { + pbModulus = OPENSSL_malloc(cbModulus); + if (pbModulus == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return SCOSSL_FAILURE; + } + + scError = SymCryptRsakeyGetValue( + keyCtx->key, + pbModulus, cbModulus, + &pubExp, 1, + NULL, NULL, 0, + SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, + 0); + OPENSSL_free(pbModulus); + + if (scError != SYMCRYPT_NO_ERROR) + { + SCOSSL_PROV_LOG_SYMCRYPT_ERROR("SymCryptRsakeyGetValue failed", scError); + return SCOSSL_FAILURE; + } + } + + if (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) + { + pbPrivateExponent = OPENSSL_secure_malloc(cbModulus); + if (pbPrivateExponent == NULL) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return SCOSSL_FAILURE; + } + + scError = SymCryptRsakeyGetCrtValue( + keyCtx->key, + NULL, NULL, 0, + NULL, 0, + pbPrivateExponent, cbModulus, + SYMCRYPT_NUMBER_FORMAT_MSB_FIRST, + 0); + OPENSSL_secure_clear_free(pbPrivateExponent, cbModulus); + + if (scError != SYMCRYPT_NO_ERROR) + { + SCOSSL_PROV_LOG_SYMCRYPT_ERROR("SymCryptRsakeyGetCrtValue failed", scError); + return SCOSSL_FAILURE; + } + } + + return success; +} + static BOOL p_scossl_rsa_keymgmt_match(_In_ SCOSSL_PROV_RSA_KEY_CTX *keyCtx1, _In_ SCOSSL_PROV_RSA_KEY_CTX *keyCtx2, int selection) { @@ -1364,6 +1427,7 @@ const OSSL_DISPATCH p_scossl_rsa_keymgmt_functions[] = { {OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*)(void))p_scossl_rsa_keymgmt_get_params}, {OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*)(void))p_scossl_rsa_keymgmt_gettable_params}, {OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))p_scossl_rsa_keymgmt_has}, + {OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))p_scossl_rsa_keymgmt_validate}, {OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))p_scossl_rsa_keymgmt_match}, {OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))p_scossl_rsa_keymgmt_impexp_types}, {OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))p_scossl_rsa_keymgmt_impexp_types}, @@ -1383,6 +1447,7 @@ const OSSL_DISPATCH p_scossl_rsapss_keymgmt_functions[] = { {OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*)(void))p_scossl_rsa_keymgmt_get_params}, {OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*)(void))p_scossl_rsa_keymgmt_gettable_params}, {OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))p_scossl_rsa_keymgmt_has}, + {OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))p_scossl_rsa_keymgmt_validate}, {OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))p_scossl_rsa_keymgmt_match}, {OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))p_scossl_rsa_keymgmt_impexp_types}, {OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))p_scossl_rsa_keymgmt_impexp_types}, diff --git a/test/SslPlay/SslPlay.cpp b/test/SslPlay/SslPlay.cpp index 9ccbe5b4..519bd37a 100644 --- a/test/SslPlay/SslPlay.cpp +++ b/test/SslPlay/SslPlay.cpp @@ -519,6 +519,63 @@ void TestRsaEncryptDecrypt( return; } +#include + +void TestRsaPrivateCheckWithIncompleteKey() +{ + printf("\nTesting EVP_PKEY_private_check with incomplete RSA key\n"); + + BIGNUM *n = NULL, *e = NULL; + RSA *rsa = NULL; + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *check_ctx = NULL; + int ret = 0; + + // Construct public key parts + BN_hex2bn(&n, "C34F"); // Small modulus (for testing only) + e = BN_new(); + BN_set_word(e, RSA_F4); // Common exponent = 65537 + + // Create RSA object and assign only n and e + rsa = RSA_new(); + if (!RSA_set0_key(rsa, n, e, NULL)) { + handleOpenSSLError("RSA_set0_key failed"); + goto end; + } + // Ownership of n and e transferred to RSA, do not free manually + + // Wrap RSA into EVP_PKEY + pkey = EVP_PKEY_new(); + if (!EVP_PKEY_assign_RSA(pkey, rsa)) { + handleOpenSSLError("EVP_PKEY_assign_RSA failed"); + goto end; + } + // Ownership of rsa transferred to pkey, do not free rsa manually + + // Create a context to check private key validity + check_ctx = EVP_PKEY_CTX_new(pkey, NULL); + if (!check_ctx) { + handleOpenSSLError("EVP_PKEY_CTX_new failed"); + goto end; + } + + // Perform the private check (should fail due to missing private parts) + ret = EVP_PKEY_private_check(check_ctx); + if (ret == 1) { + printf("❌ Unexpected success: EVP_PKEY_private_check returned 1\n"); + } else { + printf("✅ Expected failure: EVP_PKEY_private_check returned error\n"); + handleOpenSSLError("EVP_PKEY_private_check failed"); + } + +end: + EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(check_ctx); + // Don't free rsa, n, or e here — they're owned by EVP_PKEY now +} + + + void TestRsaSignVerify( EVP_PKEY *signingKey, EVP_PKEY *verificationKey, @@ -2610,7 +2667,7 @@ int main(int argc, char** argv) TestEcc(); TestDh(); TestHMAC(); - +TestRsaPrivateCheckWithIncompleteKey(); #ifdef SCOSSL_SSHKDF TestSshKdf(); #endif