diff --git a/tests/api.c b/tests/api.c index de041f8f6a..0e8ae3a811 100644 --- a/tests/api.c +++ b/tests/api.c @@ -51094,6 +51094,36 @@ static int test_wc_PKCS7_signed_enveloped(void) pkcs7 = NULL; #endif /* !NO_PKCS7_STREAM */ #endif + + { + /* arbitrary custom SKID */ + const byte customSKID[] = { + 0x40, 0x25, 0x77, 0x56 + }; + + ExpectIntEQ(wc_InitRng(&rng), 0); + sigSz = FOURK_BUF * 2; + ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId)); + if (pkcs7 != NULL) { + ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, cert, (word32)certSz), 0); + pkcs7->content = cert; + pkcs7->contentSz = (word32)certSz; + pkcs7->contentOID = DATA; + pkcs7->privateKey = key; + pkcs7->privateKeySz = (word32)keySz; + pkcs7->encryptOID = RSAk; + pkcs7->hashOID = SHA256h; + pkcs7->rng = &rng; + ExpectIntEQ(wc_PKCS7_SetSignerIdentifierType(pkcs7, CMS_SKID), 0); + ExpectIntEQ(wc_PKCS7_SetCustomSKID(pkcs7, customSKID, + sizeof(customSKID)), 0); + ExpectIntGT((sigSz = wc_PKCS7_EncodeSignedData(pkcs7, sig, + (word32)sigSz)), 0); + } + wc_PKCS7_Free(pkcs7); + pkcs7 = NULL; + wc_FreeRng(&rng); + } #endif /* HAVE_PKCS7 && !NO_RSA && !NO_AES */ return EXPECT_RESULT(); } diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 602e0c29ad..b77e9de171 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -1376,6 +1376,12 @@ void wc_PKCS7_Free(PKCS7* pkcs7) pkcs7->cachedEncryptedContentSz = 0; } + if (pkcs7->customSKID) { + XFREE(pkcs7->customSKID, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + pkcs7->customSKID = NULL; + pkcs7->customSKIDSz = 0; + } + if (pkcs7->isDynamic) { pkcs7->isDynamic = 0; XFREE(pkcs7, pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -2816,6 +2822,15 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, keyIdSize = KEYID_SIZE; #endif + /* use custom SKID if set */ + if (pkcs7->customSKIDSz > 0) { + if (pkcs7->customSKID == NULL) { + WOLFSSL_MSG("Bad custom SKID setup, size > 0 and was NULL"); + return BAD_FUNC_ARG; + } + keyIdSize = pkcs7->customSKIDSz; + } + #ifdef WOLFSSL_SMALL_STACK signedDataOid = (byte *)XMALLOC(MAX_OID_SZ, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); if (signedDataOid == NULL) { @@ -3264,8 +3279,15 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL, esd->issuerSKID, esd->issuerSKIDSz); idx += (int)esd->issuerSKIDSz; - wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL, + + if (pkcs7->customSKID) { + wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL, + pkcs7->customSKID, (word32)keyIdSize); + } + else { + wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL, pkcs7->issuerSubjKeyId, (word32)keyIdSize); + } idx += keyIdSize; } else if (pkcs7->sidType == DEGENERATE_SID) { /* no signer infos in degenerate case */ @@ -3418,6 +3440,40 @@ int wc_PKCS7_EncodeSignedData_ex(PKCS7* pkcs7, const byte* hashBuf, return ret; } + +/* Sets a custom SKID in PKCS7 struct, used before calling an encode operation + * Returns 0 on success, negative upon error. */ +int wc_PKCS7_SetCustomSKID(PKCS7* pkcs7, const byte* in, word16 inSz) +{ + int ret = 0; + + if (pkcs7 == NULL || (in == NULL && inSz > 0)) { + return BAD_FUNC_ARG; + } + + if (in == NULL) { + if (pkcs7->customSKID != NULL) { + XFREE(pkcs7->customSKID, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + } + pkcs7->customSKIDSz = 0; + pkcs7->customSKID = NULL; + } + else { + pkcs7->customSKID = (byte*)XMALLOC(inSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (pkcs7->customSKID == NULL) { + ret = MEMORY_E; + } + else { + XMEMCPY(pkcs7->customSKID, in, inSz); + pkcs7->customSKIDSz = inSz; + } + } + + return ret; +} + + /* Toggle detached signature mode on/off for PKCS#7/CMS SignedData content type. * By default wolfCrypt includes the data to be signed in the SignedData * bundle. This data can be omitted in the case when a detached signature is @@ -9589,8 +9645,9 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) } #ifndef ASN_BER_TO_DER - if (output == NULL || outputSz == 0) + if (output == NULL || outputSz == 0) { return BAD_FUNC_ARG; + } #else /* if both output and callback are not set then error out */ if ((output == NULL || outputSz == 0) && (pkcs7->streamOutCb == NULL)) { diff --git a/wolfssl/wolfcrypt/pkcs7.h b/wolfssl/wolfcrypt/pkcs7.h index 85b1a1faee..0a4631997f 100644 --- a/wolfssl/wolfcrypt/pkcs7.h +++ b/wolfssl/wolfcrypt/pkcs7.h @@ -359,6 +359,14 @@ struct PKCS7 { word16 contentCRLF:1; /* have content line endings been converted to CRLF */ word16 contentIsPkcs7Type:1; /* eContent follows PKCS#7 RFC not CMS */ word16 hashParamsAbsent:1; + + /* RFC 5280 section-4.2.1.2 lists a possible method for creating the SKID as + * a SHA1 hash of the public key, but leaves it open to other methods as + * long as it is a unique ID. This allows for setting a custom SKID when + * creating PKCS7 bundles*/ + byte* customSKID; + word16 customSKIDSz; + /* !! NEW DATA MEMBERS MUST BE ADDED AT END !! */ }; @@ -387,6 +395,8 @@ WOLFSSL_API int wc_PKCS7_EncodeData(PKCS7* pkcs7, byte* output, word32 outputSz); /* CMS/PKCS#7 SignedData */ +WOLFSSL_API int wc_PKCS7_SetCustomSKID(PKCS7* pkcs7, const byte* in, + word16 inSz); WOLFSSL_API int wc_PKCS7_SetDetached(PKCS7* pkcs7, word16 flag); WOLFSSL_API int wc_PKCS7_NoDefaultSignedAttribs(PKCS7* pkcs7); WOLFSSL_API int wc_PKCS7_SetDefaultSignedAttribs(PKCS7* pkcs7, word16 flag);