From 441bcbb680c7504923538e26423e1ba5c617927e Mon Sep 17 00:00:00 2001 From: Sameeh Jubran Date: Tue, 3 Mar 2026 13:57:04 +0200 Subject: [PATCH] Add RSA-PSS certificate support for PKCS7 EnvelopedData KTRI RSA-PSS signed certificates contain a valid RSA public key that can be used for key transport, but wc_PKCS7_AddRecipient_KTRI and the EnvelopedData/AuthEnvelopedData encode paths rejected them because they only checked for RSAk. Allow RSAPSSk to fall through to the RSAk key transport path, and always use RSAk as the KeyEncryptionAlgorithmIdentifier since the operation is RSA encryption, not RSA-PSS signing. Signed-off-by: Sameeh Jubran --- tests/api/test_pkcs7.c | 79 ++++++++++++++++++++++++++++++++++++++++++ tests/api/test_pkcs7.h | 15 ++++++++ wolfcrypt/src/pkcs7.c | 17 +++++++-- 3 files changed, 108 insertions(+), 3 deletions(-) diff --git a/tests/api/test_pkcs7.c b/tests/api/test_pkcs7.c index 5f3644869f..4d272a0247 100644 --- a/tests/api/test_pkcs7.c +++ b/tests/api/test_pkcs7.c @@ -1039,6 +1039,85 @@ int test_wc_PKCS7_EncodeSignedData_RSA_PSS(void) #endif +/* + * Testing wc_PKCS7_EncodeEnvelopedData() with RSA-PSS signed certificate + * for KTRI key transport. Uses certs/rsapss/client-rsapss.der. + * Requires encode and round-trip decode to succeed. + */ +#if defined(HAVE_PKCS7) && defined(WC_RSA_PSS) && !defined(NO_RSA) && \ + !defined(NO_FILESYSTEM) && !defined(NO_SHA256) && \ + !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_256) +int test_wc_PKCS7_EnvelopedData_KTRI_RSA_PSS(void) +{ + EXPECT_DECLS; + PKCS7* pkcs7 = NULL; + byte encrypted[FOURK_BUF]; + byte decrypted[FOURK_BUF]; + byte cert[FOURK_BUF]; + byte key[FOURK_BUF]; + word32 certSz = 0; + word32 keySz = 0; + XFILE fp = XBADFILE; + byte data[] = "Test data for RSA-PSS EnvelopedData KTRI."; + int encryptedSz = 0, decryptedSz = 0; + + XMEMSET(cert, 0, sizeof(cert)); + XMEMSET(key, 0, sizeof(key)); + + /* Load RSA-PSS client cert */ + ExpectTrue((fp = XFOPEN("./certs/rsapss/client-rsapss.der", "rb")) + != XBADFILE); + if (fp != XBADFILE) { + ExpectIntGT(certSz = (word32)XFREAD(cert, 1, sizeof(cert), fp), 0); + XFCLOSE(fp); + fp = XBADFILE; + } + + /* Load RSA-PSS client private key */ + ExpectTrue((fp = XFOPEN("./certs/rsapss/client-rsapss-priv.der", "rb")) + != XBADFILE); + if (fp != XBADFILE) { + ExpectIntGT(keySz = (word32)XFREAD(key, 1, sizeof(key), fp), 0); + XFCLOSE(fp); + fp = XBADFILE; + } + + /* Encode EnvelopedData with KTRI using RSA-PSS cert */ + ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId)); + ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, cert, certSz), 0); + if (pkcs7 != NULL) { + pkcs7->content = data; + pkcs7->contentSz = (word32)sizeof(data); + pkcs7->contentOID = DATA; + pkcs7->encryptOID = AES256CBCb; + } + + ExpectIntGT(encryptedSz = wc_PKCS7_EncodeEnvelopedData(pkcs7, + encrypted, sizeof(encrypted)), 0); + wc_PKCS7_Free(pkcs7); + pkcs7 = NULL; + + /* Decode EnvelopedData */ + ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId)); + ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, cert, certSz), 0); + if (pkcs7 != NULL) { + pkcs7->privateKey = key; + pkcs7->privateKeySz = keySz; + } + + ExpectIntGT(decryptedSz = wc_PKCS7_DecodeEnvelopedData(pkcs7, + encrypted, (word32)encryptedSz, + decrypted, sizeof(decrypted)), 0); + ExpectIntEQ(decryptedSz, (int)sizeof(data)); + ExpectIntEQ(XMEMCMP(decrypted, data, sizeof(data)), 0); + + wc_PKCS7_Free(pkcs7); + + return EXPECT_RESULT(); +} /* END test_wc_PKCS7_EnvelopedData_KTRI_RSA_PSS */ +#endif + + /* * Testing wc_PKCS7_EncodeSignedData_ex() and wc_PKCS7_VerifySignedData_ex() */ diff --git a/tests/api/test_pkcs7.h b/tests/api/test_pkcs7.h index c55307cacc..21e923011b 100644 --- a/tests/api/test_pkcs7.h +++ b/tests/api/test_pkcs7.h @@ -33,6 +33,11 @@ int test_wc_PKCS7_EncodeSignedData(void); !defined(NO_FILESYSTEM) && !defined(NO_SHA256) int test_wc_PKCS7_EncodeSignedData_RSA_PSS(void); #endif +#if defined(HAVE_PKCS7) && defined(WC_RSA_PSS) && !defined(NO_RSA) && \ + !defined(NO_FILESYSTEM) && !defined(NO_SHA256) && \ + !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_256) +int test_wc_PKCS7_EnvelopedData_KTRI_RSA_PSS(void); +#endif int test_wc_PKCS7_EncodeSignedData_ex(void); int test_wc_PKCS7_VerifySignedData_RSA(void); int test_wc_PKCS7_VerifySignedData_ECC(void); @@ -67,6 +72,15 @@ int test_wc_PKCS7_VerifySignedData_PKCS7ContentSeq(void); #define TEST_PKCS7_RSA_PSS_SD_DECL #endif +#if defined(HAVE_PKCS7) && defined(WC_RSA_PSS) && !defined(NO_RSA) && \ + !defined(NO_FILESYSTEM) && !defined(NO_SHA256) && \ + !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_256) +#define TEST_PKCS7_RSA_PSS_ED_DECL \ + TEST_DECL_GROUP("pkcs7_ed", test_wc_PKCS7_EnvelopedData_KTRI_RSA_PSS), +#else +#define TEST_PKCS7_RSA_PSS_ED_DECL +#endif + #define TEST_PKCS7_SIGNED_DATA_DECLS \ TEST_DECL_GROUP("pkcs7_sd", test_wc_PKCS7_InitWithCert), \ TEST_DECL_GROUP("pkcs7_sd", test_wc_PKCS7_EncodeData), \ @@ -83,6 +97,7 @@ int test_wc_PKCS7_VerifySignedData_PKCS7ContentSeq(void); #define TEST_PKCS7_ENCRYPTED_DATA_DECLS \ TEST_DECL_GROUP("pkcs7_ed", test_wc_PKCS7_DecodeEnvelopedData_stream), \ TEST_DECL_GROUP("pkcs7_ed", test_wc_PKCS7_EncodeDecodeEnvelopedData), \ + TEST_PKCS7_RSA_PSS_ED_DECL \ TEST_DECL_GROUP("pkcs7_ed", test_wc_PKCS7_SetAESKeyWrapUnwrapCb), \ TEST_DECL_GROUP("pkcs7_ed", test_wc_PKCS7_GetEnvelopedDataKariRid), \ TEST_DECL_GROUP("pkcs7_ed", test_wc_PKCS7_EncodeEncryptedData), \ diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 643bc4b154..04c9adb645 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -8344,7 +8344,11 @@ int wc_PKCS7_AddRecipient_KTRI(wc_PKCS7* pkcs7, const byte* cert, word32 certSz, pkcs7->publicKeyOID = decoded->keyOID; /* KeyEncryptionAlgorithmIdentifier, only support RSA now */ - if (pkcs7->publicKeyOID != RSAk) { + if (pkcs7->publicKeyOID != RSAk +#ifdef WC_RSA_PSS + && pkcs7->publicKeyOID != RSAPSSk +#endif + ) { FreeDecodedCert(decoded); WC_FREE_VAR_EX(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); WC_FREE_VAR_EX(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); @@ -8354,8 +8358,7 @@ int wc_PKCS7_AddRecipient_KTRI(wc_PKCS7* pkcs7, const byte* cert, word32 certSz, return ALGO_ID_E; } - keyEncAlgSz = (int)SetAlgoID((int)pkcs7->publicKeyOID, keyAlgArray, - oidKeyType, 0); + keyEncAlgSz = (int)SetAlgoID(RSAk, keyAlgArray, oidKeyType, 0); if (keyEncAlgSz == 0) { FreeDecodedCert(decoded); WC_FREE_VAR_EX(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); @@ -10230,6 +10233,10 @@ int wc_PKCS7_EncodeEnvelopedData(wc_PKCS7* pkcs7, byte* output, word32 outputSz) if (pkcs7->singleCert != NULL && pkcs7->singleCertSz > 0) { switch (pkcs7->publicKeyOID) { #ifndef NO_RSA + #ifdef WC_RSA_PSS + case RSAPSSk: + FALL_THROUGH; + #endif case RSAk: ret = wc_PKCS7_AddRecipient_KTRI(pkcs7, pkcs7->singleCert, pkcs7->singleCertSz, 0); @@ -13547,6 +13554,10 @@ int wc_PKCS7_EncodeAuthEnvelopedData(wc_PKCS7* pkcs7, byte* output, if (pkcs7->singleCert != NULL && pkcs7->singleCertSz > 0) { switch (pkcs7->publicKeyOID) { #ifndef NO_RSA + #ifdef WC_RSA_PSS + case RSAPSSk: + FALL_THROUGH; + #endif case RSAk: ret = wc_PKCS7_AddRecipient_KTRI(pkcs7, pkcs7->singleCert, pkcs7->singleCertSz, 0);