From 2063fa502fd240314f140ea8ad36126982f1d7ee Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Wed, 30 Oct 2019 17:27:38 -0600 Subject: [PATCH 1/3] add CMS RSA sign callback for raw digest --- wolfcrypt/src/pkcs7.c | 54 ++++++++++++++++++++++++++++++++------- wolfssl/wolfcrypt/pkcs7.h | 17 ++++++++++++ 2 files changed, 62 insertions(+), 9 deletions(-) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 0b0626f5d..03ec334cd 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -1982,8 +1982,12 @@ static int wc_PKCS7_SignedDataBuildSignature(PKCS7* pkcs7, ESD* esd) { int ret = 0; -#ifdef HAVE_ECC +#if defined(HAVE_ECC) || \ + (defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && !defined(NO_RSA)) int hashSz = 0; +#endif +#if defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && !defined(NO_RSA) + int hashOID; #endif word32 digestInfoSz = MAX_PKCS7_DIGEST_SZ; #ifdef WOLFSSL_SMALL_STACK @@ -2014,11 +2018,37 @@ static int wc_PKCS7_SignedDataBuildSignature(PKCS7* pkcs7, return ret; } +#if defined(HAVE_ECC) || \ + (defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && !defined(NO_RSA)) + /* get digest size from hash type */ + hashSz = wc_HashGetDigestSize(esd->hashType); + if (hashSz < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return hashSz; + } +#endif + /* sign digestInfo */ switch (pkcs7->publicKeyOID) { #ifndef NO_RSA case RSAk: + #ifdef HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK + if (pkcs7->rsaSignRawDigestCb != NULL) { + /* get hash OID */ + hashOID = wc_HashGetOID(esd->hashType); + + /* user signing plain digest, build DigestInfo themselves */ + ret = pkcs7->rsaSignRawDigestCb(pkcs7, + esd->contentAttribsDigest, hashSz, + esd->encContentDigest, sizeof(esd->encContentDigest), + pkcs7->privateKey, pkcs7->privateKeySz, pkcs7->devId, + hashOID); + break; + } + #endif ret = wc_PKCS7_RsaSign(pkcs7, digestInfo, digestInfoSz, esd); break; #endif @@ -2027,14 +2057,6 @@ static int wc_PKCS7_SignedDataBuildSignature(PKCS7* pkcs7, case ECDSAk: /* CMS with ECDSA does not sign DigestInfo structure * like PKCS#7 with RSA does */ - hashSz = wc_HashGetDigestSize(esd->hashType); - if (hashSz < 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return hashSz; - } - ret = wc_PKCS7_EcdsaSign(pkcs7, esd->contentAttribsDigest, hashSz, esd); break; @@ -3032,6 +3054,20 @@ int wc_PKCS7_EncodeSignedEncryptedCompressedFPD(PKCS7* pkcs7, byte* encryptKey, #ifndef NO_RSA +#ifdef HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK +/* register raw RSA sign digest callback */ +int wc_PKCS7_SetRsaSignRawDigestCb(PKCS7* pkcs7, CallbackRsaSignRawDigest cb) +{ + if (pkcs7 == NULL || cb == NULL) { + return BAD_FUNC_ARG; + } + + pkcs7->rsaSignRawDigestCb = cb; + + return 0; +} +#endif + /* returns size of signature put into out, negative on error */ static int wc_PKCS7_RsaVerify(PKCS7* pkcs7, byte* sig, int sigSz, byte* hash, word32 hashSz) diff --git a/wolfssl/wolfcrypt/pkcs7.h b/wolfssl/wolfcrypt/pkcs7.h index 32bfec845..6d327d447 100644 --- a/wolfssl/wolfcrypt/pkcs7.h +++ b/wolfssl/wolfcrypt/pkcs7.h @@ -220,6 +220,14 @@ typedef int (*CallbackWrapCEK)(PKCS7* pkcs7, byte* cek, word32 cekSz, byte* out, word32 outSz, int keyWrapAlgo, int type, int dir); +#if defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && !defined(NO_RSA) +/* RSA sign raw digest callback, user builds DigestInfo */ +typedef int (*CallbackRsaSignRawDigest)(PKCS7* pkcs7, byte* digest, + word32 digestSz, byte* out, word32 outSz, + byte* privateKey, word32 privateKeySz, + int devId, int hashOID); +#endif + /* Public Structure Warning: * Existing members must not be changed to maintain backwards compatibility! */ @@ -318,6 +326,10 @@ struct PKCS7 { word32 signatureSz; word32 plainDigestSz; word32 pkcs7DigestSz; + +#if defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && !defined(NO_RSA) + CallbackRsaSignRawDigest rsaSignRawDigestCb; +#endif /* !! NEW DATA MEMBERS MUST BE ADDED AT END !! */ }; @@ -439,6 +451,11 @@ WOLFSSL_API int wc_PKCS7_AddRecipient_ORI(PKCS7* pkcs7, CallbackOriEncrypt cb, WOLFSSL_API int wc_PKCS7_SetWrapCEKCb(PKCS7* pkcs7, CallbackWrapCEK wrapCEKCb); +#if defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && !defined(NO_RSA) +WOLFSSL_API int wc_PKCS7_SetRsaSignRawDigestCb(PKCS7* pkcs7, + CallbackRsaSignRawDigest cb); +#endif + /* CMS/PKCS#7 EnvelopedData */ WOLFSSL_API int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz); From be97444d24b95219ad10fb86f6b780fdf12f341e Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Wed, 30 Oct 2019 18:09:57 -0600 Subject: [PATCH 2/3] add api test for wc_PKCS7_SetRsaSignRawDigestCb() --- tests/api.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/tests/api.c b/tests/api.c index 91b2e9346..a0d3ade07 100644 --- a/tests/api.c +++ b/tests/api.c @@ -16670,6 +16670,71 @@ static void test_wc_PKCS7_EncodeData (void) } /* END test_wc_PKCS7_EncodeData */ +#if defined(HAVE_PKCS7) && defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && \ + !defined(NO_RSA) && !defined(NO_SHA256) +/* RSA sign raw digest callback */ +static int rsaSignRawDigestCb(PKCS7* pkcs7, byte* digest, word32 digestSz, + byte* out, word32 outSz, byte* privateKey, + word32 privateKeySz, int devid, int hashOID) +{ + /* specific DigestInfo ASN.1 encoding prefix for a SHA2565 digest */ + byte digInfoEncoding[] = { + 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, + 0x00, 0x04, 0x20 + }; + + int ret; + byte digestInfo[ONEK_BUF]; + byte sig[FOURK_BUF]; + word32 digestInfoSz = 0; + word32 idx = 0; + RsaKey rsa; + + /* SHA-256 required only for this example callback due to above + * digInfoEncoding[] */ + if (pkcs7 == NULL || digest == NULL || out == NULL || + (sizeof(digestInfo) < sizeof(digInfoEncoding) + digestSz) || + (hashOID != SHA256h)) { + return -1; + } + + /* build DigestInfo */ + XMEMCPY(digestInfo, digInfoEncoding, sizeof(digInfoEncoding)); + digestInfoSz += sizeof(digInfoEncoding); + XMEMCPY(digestInfo + digestInfoSz, digest, digestSz); + digestInfoSz += digestSz; + + /* set up RSA key */ + ret = wc_InitRsaKey_ex(&rsa, pkcs7->heap, devid); + if (ret != 0) { + return ret; + } + + ret = wc_RsaPrivateKeyDecode(privateKey, &idx, &rsa, privateKeySz); + + /* sign DigestInfo */ + if (ret == 0) { + ret = wc_RsaSSL_Sign(digestInfo, digestInfoSz, sig, sizeof(sig), + &rsa, pkcs7->rng); + if (ret > 0) { + if (ret > (int)outSz) { + /* output buffer too small */ + ret = -1; + } else { + /* success, ret holds sig size */ + XMEMCPY(out, sig, ret); + } + } + } + + wc_FreeRsaKey(&rsa); + + return ret; +} +#endif + + /* * Testing wc_PKCS7_EncodeSignedData() */ @@ -16781,6 +16846,26 @@ static void test_wc_PKCS7_EncodeSignedData(void) pkcs7->hashOID = 0; /* bad hashOID */ AssertIntEQ(wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz), BAD_FUNC_ARG); +#if defined(HAVE_PKCS7) && defined(HAVE_PKCS7_RSA_RAW_SIGN_CALLBACK) && \ + !defined(NO_RSA) && !defined(NO_SHA256) + /* test RSA sign raw digest callback, if using RSA and compiled in. + * Example callback assumes SHA-256, so only run test if compiled in. */ + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, cert, certSz), 0); + + pkcs7->content = data; + pkcs7->contentSz = (word32)sizeof(data); + pkcs7->privateKey = key; + pkcs7->privateKeySz = (word32)sizeof(key); + pkcs7->encryptOID = RSAk; + pkcs7->hashOID = SHA256h; + pkcs7->rng = &rng; + + AssertIntEQ(wc_PKCS7_SetRsaSignRawDigestCb(pkcs7, rsaSignRawDigestCb), 0); + + AssertIntGT(wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz), 0); +#endif + printf(resultFmt, passed); wc_PKCS7_Free(pkcs7); @@ -16789,6 +16874,7 @@ static void test_wc_PKCS7_EncodeSignedData(void) #endif } /* END test_wc_PKCS7_EncodeSignedData */ + /* * Testing wc_PKCS7_EncodeSignedData_ex() and wc_PKCS7_VerifySignedData_ex() */ From 6081bdaad612a3dedd5a1f9fc51e1d69efe5c7c6 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Fri, 6 Dec 2019 12:00:33 -0700 Subject: [PATCH 3/3] free PKCS7 before creating new in API test --- tests/api.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/api.c b/tests/api.c index a0d3ade07..885143723 100644 --- a/tests/api.c +++ b/tests/api.c @@ -16850,6 +16850,7 @@ static void test_wc_PKCS7_EncodeSignedData(void) !defined(NO_RSA) && !defined(NO_SHA256) /* test RSA sign raw digest callback, if using RSA and compiled in. * Example callback assumes SHA-256, so only run test if compiled in. */ + wc_PKCS7_Free(pkcs7); AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, cert, certSz), 0);