Skip to content

Commit f540d19

Browse files
committed
pkcs7: add RSA-PSS support for SignedData
Add full RSA-PSS (RSASSA-PSS) support to PKCS#7 SignedData encoding and verification. This change enables SignerInfo.signatureAlgorithm to use id-RSASSA-PSS with explicit RSASSA-PSS-params (hash, MGF1, salt length), as required by RFC 4055 and CMS profiles. Key changes: - Add RSA-PSS encode and verify paths for PKCS7 SignedData - Encode full RSASSA-PSS AlgorithmIdentifier parameters - Decode RSA-PSS parameters from SignerInfo for verification - Treat RSA-PSS like ECDSA (sign raw digest, not DigestInfo) - Fix certificate signatureAlgorithm parameter length handling - Add API test coverage for RSA-PSS SignedData This resolves failures when using RSA-PSS signer certificates (e.g. -173 invalid signature algorithm) and maintains backward compatibility with RSA PKCS#1 v1.5 and ECDSA. Signed-off-by: Sameeh Jubran <sameeh@wolfssl.com>
1 parent 49ed1fa commit f540d19

File tree

13 files changed

+938
-141
lines changed

13 files changed

+938
-141
lines changed

.github/workflows/os-check.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ jobs:
5353
'--enable-opensslall --enable-opensslextra CPPFLAGS=-DWC_RNG_SEED_CB',
5454
'--enable-opensslall --enable-opensslextra
5555
CPPFLAGS=''-DWC_RNG_SEED_CB -DWOLFSSL_NO_GETPID'' ',
56+
# PKCS#7 with RSA-PSS (CMS RSASSA-PSS signers)
57+
'--enable-pkcs7 CPPFLAGS=-DWC_RSA_PSS',
5658
'--enable-opensslextra CPPFLAGS=''-DWOLFSSL_NO_CA_NAMES'' ',
5759
'--enable-opensslextra=x509small',
5860
'CPPFLAGS=''-DWOLFSSL_EXTRA'' ',

doc/dox_comments/header_files/cryptocb.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,18 @@
5252
}
5353
}
5454
#endif
55+
#if defined(WC_RSA_PSS) && !defined(NO_RSA)
56+
if (info->pk.type == WC_PK_TYPE_RSA_PSS) {
57+
/* RSA-PSS sign/verify (e.g. PKCS#7 SignedData, X.509).
58+
* Uses info->pk.rsa (in/inLen = digest, out/outLen = signature,
59+
* key, rng). With WOLF_CRYPTO_CB_RSA_PAD, info->pk.rsa.padding
60+
* supplies hash and salt length. */
61+
ret = wc_RsaFunction(info->pk.rsa.in, info->pk.rsa.inLen,
62+
info->pk.rsa.out, info->pk.rsa.outLen, info->pk.rsa.type,
63+
info->pk.rsa.key, info->pk.rsa.rng);
64+
break;
65+
}
66+
#endif
5567
#ifdef HAVE_ECC
5668
if (info->pk.type == WC_PK_TYPE_ECDSA_SIGN) {
5769
// ECDSA

doc/dox_comments/header_files/doxygen_pages.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
<li>\ref MD5</li>
5252
<li>\ref Password</li>
5353
<li>\ref PKCS7</li>
54+
<li>\ref PKCS7_RSA_PSS</li>
5455
<li>\ref PKCS11</li>
5556
<li>\ref Poly1305</li>
5657
<li>\ref RIPEMD</li>
@@ -97,4 +98,13 @@
9798
\sa wc_CryptoCb_AesSetKey
9899
\sa \ref Crypto Callbacks
99100
*/
101+
/*!
102+
\page PKCS7_RSA_PSS PKCS#7 RSA-PSS (CMS)
103+
PKCS#7 SignedData supports RSA-PSS signers (CMS RSASSA-PSS). When WC_RSA_PSS
104+
is defined, use wc_PKCS7_InitWithCert with a signer certificate that has
105+
RSA-PSS (id-RSASSA-PSS) and set hashOID and optional rng; encode produces
106+
full RSASSA-PSS-params (hashAlgorithm, mgfAlgorithm, saltLength,
107+
trailerField). Verify accepts NULL, empty, or absent parameters with
108+
RFC defaults. See \ref PKCS7 for the main API.
109+
*/
100110

doc/dox_comments/header_files/pkcs7.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ int wc_PKCS7_EncodeData(wc_PKCS7* pkcs7, byte* output,
147147
148148
\brief This function builds the PKCS7 signed data content type, encoding
149149
the PKCS7 structure into a buffer containing a parsable PKCS7
150-
signed data packet.
150+
signed data packet. For RSA-PSS signers (WC_RSA_PSS), see \ref PKCS7_RSA_PSS.
151151
152152
\return Success On successfully encoding the PKCS7 data into the buffer,
153153
returns the index parsed up to in the PKCS7 structure. This index also

examples/configs/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Example wolfSSL configuration file templates for use when autoconf is not availa
2323
* `user_settings_openssl_compat.h`: OpenSSL compatibility layer for drop-in replacement. Enables OPENSSL_ALL and related APIs.
2424
* `user_settings_baremetal.h`: Bare metal configuration. No filesystem, static memory only, minimal footprint.
2525
* `user_settings_rsa_only.h`: RSA-only configuration (no ECC). For legacy systems requiring RSA cipher suites.
26-
* `user_settings_pkcs7.h`: PKCS#7/CMS configuration for signing and encryption. S/MIME, firmware signing.
26+
* `user_settings_pkcs7.h`: PKCS#7/CMS configuration for signing and encryption. S/MIME, firmware signing. For RSA-PSS SignedData (CMS RSASSA-PSS), define `WC_RSA_PSS`; see doxygen \ref PKCS7_RSA_PSS.
2727
* `user_settings_ca.h`: Certificate Authority / PKI operations. Certificate generation, signing, CRL, OCSP.
2828
* `user_settings_wolfboot_keytools.h`: wolfBoot key generation and signing tool. Supports ECC, RSA, ED25519, ED448, and post-quantum (ML-DSA/Dilithium, LMS, XMSS).
2929
* `user_settings_wolfssh.h`: Minimum options for building wolfSSH. See comment at top for ./configure used to generate.

examples/configs/user_settings_pkcs7.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ extern "C" {
115115
#undef NO_RSA
116116
#define WOLFSSL_KEY_GEN
117117
#define WC_RSA_NO_PADDING
118+
#define WC_RSA_PSS /* RSA-PSS SignedData (id-RSASSA-PSS); see PKCS7_RSA_PSS */
118119
#else
119120
#define NO_RSA
120121
#endif

tests/api/test_pkcs7.c

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -947,6 +947,92 @@ int test_wc_PKCS7_EncodeSignedData(void)
947947
} /* END test_wc_PKCS7_EncodeSignedData */
948948

949949

950+
/*
951+
* Testing wc_PKCS7_EncodeSignedData() with RSA-PSS signer certificate.
952+
* Uses certs/rsapss/client-rsapss.der and client-rsapss-priv.der.
953+
* Requires both encode and round-trip verify to succeed.
954+
*/
955+
#if defined(HAVE_PKCS7) && defined(WC_RSA_PSS) && !defined(NO_RSA) && \
956+
!defined(NO_FILESYSTEM) && !defined(NO_SHA256)
957+
int test_wc_PKCS7_EncodeSignedData_RSA_PSS(void)
958+
{
959+
EXPECT_DECLS;
960+
PKCS7* pkcs7 = NULL;
961+
WC_RNG rng;
962+
byte output[FOURK_BUF];
963+
byte cert[FOURK_BUF];
964+
byte key[FOURK_BUF];
965+
word32 outputSz = (word32)sizeof(output);
966+
word32 certSz = 0;
967+
word32 keySz = 0;
968+
XFILE fp = XBADFILE;
969+
byte data[] = "Test data for RSA-PSS SignedData.";
970+
971+
XMEMSET(&rng, 0, sizeof(WC_RNG));
972+
XMEMSET(output, 0, outputSz);
973+
XMEMSET(cert, 0, sizeof(cert));
974+
XMEMSET(key, 0, sizeof(key));
975+
976+
ExpectIntEQ(wc_InitRng(&rng), 0);
977+
ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId));
978+
ExpectIntEQ(wc_PKCS7_Init(pkcs7, HEAP_HINT, INVALID_DEVID), 0);
979+
980+
ExpectTrue((fp = XFOPEN("./certs/rsapss/client-rsapss.der", "rb")) != XBADFILE);
981+
ExpectIntGT(certSz = (word32)XFREAD(cert, 1, sizeof(cert), fp), 0);
982+
if (fp != XBADFILE) {
983+
XFCLOSE(fp);
984+
fp = XBADFILE;
985+
}
986+
987+
ExpectTrue((fp = XFOPEN("./certs/rsapss/client-rsapss-priv.der", "rb")) != XBADFILE);
988+
ExpectIntGT(keySz = (word32)XFREAD(key, 1, sizeof(key), fp), 0);
989+
if (fp != XBADFILE)
990+
XFCLOSE(fp);
991+
992+
ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, cert, certSz), 0);
993+
994+
#ifdef WC_RSA_PSS
995+
/* Force RSA-PSS so SignerInfo uses id-RSASSA-PSS (cert may use RSA in subjectPublicKeyInfo) */
996+
pkcs7->publicKeyOID = RSAPSSk;
997+
#endif
998+
999+
pkcs7->content = data;
1000+
pkcs7->contentSz = (word32)sizeof(data);
1001+
pkcs7->contentOID = DATA;
1002+
pkcs7->hashOID = SHA256h;
1003+
pkcs7->encryptOID = RSAk;
1004+
pkcs7->privateKey = key;
1005+
pkcs7->privateKeySz = keySz;
1006+
pkcs7->rng = &rng;
1007+
pkcs7->signedAttribs = NULL;
1008+
pkcs7->signedAttribsSz = 0;
1009+
1010+
/* EncodeSignedData with RSA-PSS cert: require encode and verify success */
1011+
{
1012+
int outLen = wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz);
1013+
ExpectIntGT(outLen, 0);
1014+
if (outLen > 0) {
1015+
int verifyRet = wc_PKCS7_VerifySignedData(pkcs7, output, (word32)outLen);
1016+
ExpectIntEQ(verifyRet, 0);
1017+
1018+
/* Verify decoded RSASSA-PSS parameters match what we encoded:
1019+
* hashAlgorithm = SHA-256
1020+
* maskGenAlgorithm = MGF1-SHA-256
1021+
* saltLength = 32 (== SHA-256 digest length) */
1022+
ExpectIntEQ(pkcs7->pssHashType, (int)WC_HASH_TYPE_SHA256);
1023+
ExpectIntEQ(pkcs7->pssMgf, WC_MGF1SHA256);
1024+
ExpectIntEQ(pkcs7->pssSaltLen, 32);
1025+
}
1026+
}
1027+
1028+
wc_PKCS7_Free(pkcs7);
1029+
DoExpectIntEQ(wc_FreeRng(&rng), 0);
1030+
1031+
return EXPECT_RESULT();
1032+
} /* END test_wc_PKCS7_EncodeSignedData_RSA_PSS */
1033+
#endif
1034+
1035+
9501036
/*
9511037
* Testing wc_PKCS7_EncodeSignedData_ex() and wc_PKCS7_VerifySignedData_ex()
9521038
*/

tests/api/test_pkcs7.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ int test_wc_PKCS7_Init(void);
2929
int test_wc_PKCS7_InitWithCert(void);
3030
int test_wc_PKCS7_EncodeData(void);
3131
int test_wc_PKCS7_EncodeSignedData(void);
32+
#if defined(HAVE_PKCS7) && defined(WC_RSA_PSS) && !defined(NO_RSA) && \
33+
!defined(NO_FILESYSTEM) && !defined(NO_SHA256)
34+
int test_wc_PKCS7_EncodeSignedData_RSA_PSS(void);
35+
#endif
3236
int test_wc_PKCS7_EncodeSignedData_ex(void);
3337
int test_wc_PKCS7_VerifySignedData_RSA(void);
3438
int test_wc_PKCS7_VerifySignedData_ECC(void);
@@ -55,10 +59,19 @@ int test_wc_PKCS7_VerifySignedData_PKCS7ContentSeq(void);
5559
TEST_DECL_GROUP("pkcs7", test_wc_PKCS7_New), \
5660
TEST_DECL_GROUP("pkcs7", test_wc_PKCS7_Init)
5761

62+
#if defined(HAVE_PKCS7) && defined(WC_RSA_PSS) && !defined(NO_RSA) && \
63+
!defined(NO_FILESYSTEM) && !defined(NO_SHA256)
64+
#define TEST_PKCS7_RSA_PSS_SD_DECL \
65+
TEST_DECL_GROUP("pkcs7_sd", test_wc_PKCS7_EncodeSignedData_RSA_PSS),
66+
#else
67+
#define TEST_PKCS7_RSA_PSS_SD_DECL
68+
#endif
69+
5870
#define TEST_PKCS7_SIGNED_DATA_DECLS \
5971
TEST_DECL_GROUP("pkcs7_sd", test_wc_PKCS7_InitWithCert), \
6072
TEST_DECL_GROUP("pkcs7_sd", test_wc_PKCS7_EncodeData), \
6173
TEST_DECL_GROUP("pkcs7_sd", test_wc_PKCS7_EncodeSignedData), \
74+
TEST_PKCS7_RSA_PSS_SD_DECL \
6275
TEST_DECL_GROUP("pkcs7_sd", test_wc_PKCS7_EncodeSignedData_ex), \
6376
TEST_DECL_GROUP("pkcs7_sd", test_wc_PKCS7_VerifySignedData_RSA), \
6477
TEST_DECL_GROUP("pkcs7_sd", test_wc_PKCS7_VerifySignedData_ECC), \

wolfcrypt/src/aes.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits
4747

4848
#include <wolfssl/wolfcrypt/aes.h>
4949

50+
#if defined(__clang__)
51+
#pragma clang diagnostic push
52+
#pragma clang diagnostic ignored "-Wlanguage-extension-token"
53+
#endif
54+
5055
#ifdef WOLFSSL_AESNI
5156
#include <wmmintrin.h>
5257
#include <emmintrin.h>
@@ -17141,5 +17146,8 @@ int wc_AesCtsDecryptFinal(Aes* aes, byte* out, word32* outSz)
1714117146

1714217147
#endif /* WOLFSSL_AES_CTS */
1714317148

17149+
#if defined(__clang__)
17150+
#pragma clang diagnostic pop
17151+
#endif
1714417152

1714517153
#endif /* !NO_AES */

0 commit comments

Comments
 (0)