Skip to content

Commit 85bab19

Browse files
Merge pull request #7845 from ColtonWilley/pkcs7_digest_absent_params
Add option for absent hash params in PKCS7
2 parents 0d84597 + 0a5ebaf commit 85bab19

5 files changed

Lines changed: 258 additions & 32 deletions

File tree

tests/api.c

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38789,6 +38789,167 @@ static int test_wc_PKCS7_EncodeSignedData(void)
3878938789
return EXPECT_RESULT();
3879038790
} /* END test_wc_PKCS7_EncodeSignedData */
3879138791

38792+
static int test_wc_PKCS7_EncodeSignedData_absent(void)
38793+
{
38794+
EXPECT_DECLS;
38795+
#if defined(HAVE_PKCS7)
38796+
PKCS7* pkcs7 = NULL;
38797+
WC_RNG rng;
38798+
byte output[FOURK_BUF];
38799+
word32 outputSz = (word32)sizeof(output);
38800+
int withParamsLen = 0;
38801+
int withoutParamsLen = 0;
38802+
byte data[] = "Test data to encode.";
38803+
#ifndef NO_RSA
38804+
#if defined(USE_CERT_BUFFERS_2048)
38805+
byte key[sizeof(client_key_der_2048)];
38806+
byte cert[sizeof(client_cert_der_2048)];
38807+
word32 keySz = (word32)sizeof(key);
38808+
word32 certSz = (word32)sizeof(cert);
38809+
XMEMSET(key, 0, keySz);
38810+
XMEMSET(cert, 0, certSz);
38811+
XMEMCPY(key, client_key_der_2048, keySz);
38812+
XMEMCPY(cert, client_cert_der_2048, certSz);
38813+
#elif defined(USE_CERT_BUFFERS_1024)
38814+
byte key[sizeof_client_key_der_1024];
38815+
byte cert[sizeof(sizeof_client_cert_der_1024)];
38816+
word32 keySz = (word32)sizeof(key);
38817+
word32 certSz = (word32)sizeof(cert);
38818+
XMEMSET(key, 0, keySz);
38819+
XMEMSET(cert, 0, certSz);
38820+
XMEMCPY(key, client_key_der_1024, keySz);
38821+
XMEMCPY(cert, client_cert_der_1024, certSz);
38822+
#else
38823+
unsigned char cert[ONEK_BUF];
38824+
unsigned char key[ONEK_BUF];
38825+
XFILE fp = XBADFILE;
38826+
int certSz;
38827+
int keySz;
38828+
38829+
ExpectTrue((fp = XFOPEN("./certs/1024/client-cert.der", "rb")) !=
38830+
XBADFILE);
38831+
ExpectIntGT(certSz = (int)XFREAD(cert, 1, sizeof_client_cert_der_1024,
38832+
fp), 0);
38833+
if (fp != XBADFILE) {
38834+
XFCLOSE(fp);
38835+
fp = XBADFILE;
38836+
}
38837+
38838+
ExpectTrue((fp = XFOPEN("./certs/1024/client-key.der", "rb")) !=
38839+
XBADFILE);
38840+
ExpectIntGT(keySz = (int)XFREAD(key, 1, sizeof_client_key_der_1024, fp),
38841+
0);
38842+
if (fp != XBADFILE)
38843+
XFCLOSE(fp);
38844+
#endif
38845+
#elif defined(HAVE_ECC)
38846+
#if defined(USE_CERT_BUFFERS_256)
38847+
unsigned char cert[sizeof(cliecc_cert_der_256)];
38848+
unsigned char key[sizeof(ecc_clikey_der_256)];
38849+
int certSz = (int)sizeof(cert);
38850+
int keySz = (int)sizeof(key);
38851+
XMEMSET(cert, 0, certSz);
38852+
XMEMSET(key, 0, keySz);
38853+
XMEMCPY(cert, cliecc_cert_der_256, certSz);
38854+
XMEMCPY(key, ecc_clikey_der_256, keySz);
38855+
#else
38856+
unsigned char cert[ONEK_BUF];
38857+
unsigned char key[ONEK_BUF];
38858+
XFILE fp = XBADFILE;
38859+
int certSz;
38860+
int keySz;
38861+
38862+
ExpectTrue((fp = XFOPEN("./certs/client-ecc-cert.der", "rb")) !=
38863+
XBADFILE);
38864+
ExpectIntGT(certSz = (int)XFREAD(cert, 1, ONEK_BUF, fp), 0);
38865+
if (fp != XBADFILE) {
38866+
XFCLOSE(fp);
38867+
fp = XBADFILE;
38868+
}
38869+
38870+
ExpectTrue((fp = XFOPEN("./certs/client-ecc-key.der", "rb")) !=
38871+
XBADFILE);
38872+
ExpectIntGT(keySz = (int)XFREAD(key, 1, ONEK_BUF, fp), 0);
38873+
if (fp != XBADFILE)
38874+
XFCLOSE(fp);
38875+
#endif
38876+
#endif
38877+
38878+
XMEMSET(&rng, 0, sizeof(WC_RNG));
38879+
38880+
XMEMSET(output, 0, outputSz);
38881+
ExpectIntEQ(wc_InitRng(&rng), 0);
38882+
38883+
/* First generate and verify with NULL params */
38884+
ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId));
38885+
ExpectIntEQ(wc_PKCS7_Init(pkcs7, HEAP_HINT, INVALID_DEVID), 0);
38886+
ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, cert, certSz), 0);
38887+
38888+
if (pkcs7 != NULL) {
38889+
pkcs7->content = data;
38890+
pkcs7->contentSz = (word32)sizeof(data);
38891+
pkcs7->privateKey = key;
38892+
pkcs7->privateKeySz = (word32)sizeof(key);
38893+
pkcs7->encryptOID = RSAk;
38894+
#ifdef NO_SHA
38895+
pkcs7->hashOID = SHA256h;
38896+
#else
38897+
pkcs7->hashOID = SHAh;
38898+
#endif
38899+
pkcs7->rng = &rng;
38900+
}
38901+
38902+
withParamsLen = wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz);
38903+
ExpectIntGT(withParamsLen, 0);
38904+
wc_PKCS7_Free(pkcs7);
38905+
pkcs7 = NULL;
38906+
38907+
ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId));
38908+
ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, 0), 0);
38909+
ExpectIntEQ(wc_PKCS7_VerifySignedData(pkcs7, output, withParamsLen), 0);
38910+
wc_PKCS7_Free(pkcs7);
38911+
pkcs7 = NULL;
38912+
38913+
XMEMSET(output, 0, outputSz);
38914+
38915+
/* Now generate again without params */
38916+
ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId));
38917+
ExpectIntEQ(wc_PKCS7_Init(pkcs7, HEAP_HINT, INVALID_DEVID), 0);
38918+
ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, cert, certSz), 0);
38919+
38920+
if (pkcs7 != NULL) {
38921+
pkcs7->content = data;
38922+
pkcs7->contentSz = (word32)sizeof(data);
38923+
pkcs7->privateKey = key;
38924+
pkcs7->privateKeySz = (word32)sizeof(key);
38925+
pkcs7->encryptOID = RSAk;
38926+
#ifdef NO_SHA
38927+
pkcs7->hashOID = SHA256h;
38928+
#else
38929+
pkcs7->hashOID = SHAh;
38930+
#endif
38931+
pkcs7->rng = &rng;
38932+
pkcs7->hashParamsAbsent = TRUE;
38933+
}
38934+
38935+
withoutParamsLen = wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz);
38936+
ExpectIntGT(withoutParamsLen, 0);
38937+
wc_PKCS7_Free(pkcs7);
38938+
pkcs7 = NULL;
38939+
38940+
ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId));
38941+
ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, 0), 0);
38942+
ExpectIntEQ(wc_PKCS7_VerifySignedData(pkcs7, output, withoutParamsLen), 0);
38943+
38944+
/* Both are valid PKCS7 with non-zero len, ensure without is shorter */
38945+
ExpectIntLT(withoutParamsLen, withParamsLen);
38946+
38947+
wc_PKCS7_Free(pkcs7);
38948+
DoExpectIntEQ(wc_FreeRng(&rng), 0);
38949+
38950+
#endif
38951+
return EXPECT_RESULT();
38952+
}
3879238953

3879338954
/*
3879438955
* Testing wc_PKCS7_EncodeSignedData_ex() and wc_PKCS7_VerifySignedData_ex()
@@ -84809,6 +84970,7 @@ TEST_CASE testCases[] = {
8480984970
TEST_DECL(test_wc_PKCS7_EncodeData),
8481084971
TEST_DECL(test_wc_PKCS7_EncodeSignedData),
8481184972
TEST_DECL(test_wc_PKCS7_EncodeSignedData_ex),
84973+
TEST_DECL(test_wc_PKCS7_EncodeSignedData_absent),
8481284974
TEST_DECL(test_wc_PKCS7_VerifySignedData_RSA),
8481384975
TEST_DECL(test_wc_PKCS7_VerifySignedData_ECC),
8481484976
TEST_DECL(test_wc_PKCS7_EncodeDecodeEnvelopedData),

wolfcrypt/src/asn.c

Lines changed: 71 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6061,22 +6061,8 @@ enum {
60616061
#define algoIdASN_Length (sizeof(algoIdASN) / sizeof(ASNItem))
60626062
#endif
60636063

6064-
/* Get the OID id/sum from the BER encoding of an algorithm identifier.
6065-
*
6066-
* NULL tag is skipped if present.
6067-
*
6068-
* @param [in] input Buffer holding BER encoded data.
6069-
* @param [in, out] inOutIdx On in, start of algorithm identifier.
6070-
* On out, start of ASN.1 item after algorithm id.
6071-
* @param [out] oid Id of OID in algorithm identifier data.
6072-
* @param [in] oidType Type of OID to expect.
6073-
* @param [in] maxIdx Maximum index of data in buffer.
6074-
* @return 0 on success.
6075-
* @return ASN_PARSE_E when encoding is invalid.
6076-
* @return ASN_UNKNOWN_OID_E when the OID cannot be verified.
6077-
*/
6078-
int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid,
6079-
word32 oidType, word32 maxIdx)
6064+
static int GetAlgoIdImpl(const byte* input, word32* inOutIdx, word32* oid,
6065+
word32 oidType, word32 maxIdx, byte *absentParams)
60806066
{
60816067
#ifndef WOLFSSL_ASN_TEMPLATE
60826068
int length;
@@ -6102,6 +6088,10 @@ int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid,
61026088
ret = GetASNNull(input, &idx, maxIdx);
61036089
if (ret != 0)
61046090
return ret;
6091+
6092+
if (absentParams != NULL) {
6093+
*absentParams = FALSE;
6094+
}
61056095
}
61066096
}
61076097
}
@@ -6126,13 +6116,49 @@ int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid,
61266116
if (ret == 0) {
61276117
/* Return the OID id/sum. */
61286118
*oid = dataASN[ALGOIDASN_IDX_OID].data.oid.sum;
6119+
6120+
if ((absentParams != NULL) &&
6121+
(dataASN[ALGOIDASN_IDX_NULL].tag == ASN_TAG_NULL)) {
6122+
*absentParams = FALSE;
6123+
}
61296124
}
61306125

61316126
FREE_ASNGETDATA(dataASN, NULL);
61326127
return ret;
61336128
#endif /* WOLFSSL_ASN_TEMPLATE */
61346129
}
61356130

6131+
/* Get the OID id/sum from the BER encoding of an algorithm identifier.
6132+
*
6133+
* NULL tag is skipped if present.
6134+
*
6135+
* @param [in] input Buffer holding BER encoded data.
6136+
* @param [in, out] inOutIdx On in, start of algorithm identifier.
6137+
* On out, start of ASN.1 item after algorithm id.
6138+
* @param [out] oid Id of OID in algorithm identifier data.
6139+
* @param [in] oidType Type of OID to expect.
6140+
* @param [in] maxIdx Maximum index of data in buffer.
6141+
* @return 0 on success.
6142+
* @return ASN_PARSE_E when encoding is invalid.
6143+
* @return ASN_UNKNOWN_OID_E when the OID cannot be verified.
6144+
*/
6145+
int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid,
6146+
word32 oidType, word32 maxIdx)
6147+
{
6148+
return GetAlgoIdImpl(input, inOutIdx, oid, oidType, maxIdx, NULL);
6149+
}
6150+
6151+
int GetAlgoIdEx(const byte* input, word32* inOutIdx, word32* oid,
6152+
word32 oidType, word32 maxIdx, byte *absentParams)
6153+
{
6154+
/* Assume absent until proven otherwise */
6155+
if (absentParams != NULL) {
6156+
*absentParams = TRUE;
6157+
}
6158+
6159+
return GetAlgoIdImpl(input, inOutIdx, oid, oidType, maxIdx, absentParams);
6160+
}
6161+
61366162
#ifndef NO_RSA
61376163

61386164
#ifdef WC_RSA_PSS
@@ -16077,7 +16103,7 @@ static WC_INLINE int IsSigAlgoECC(word32 algoOID)
1607716103
* @return Encoded data size on success.
1607816104
* @return 0 when dynamic memory allocation fails.
1607916105
*/
16080-
word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz)
16106+
static word32 SetAlgoIDImpl(int algoOID, byte* output, int type, int curveSz, byte absentParams)
1608116107
{
1608216108
#ifndef WOLFSSL_ASN_TEMPLATE
1608316109
word32 tagSz, idSz, seqSz, algoSz = 0;
@@ -16086,9 +16112,10 @@ word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz)
1608616112
byte seqArray[MAX_SEQ_SZ + 1]; /* add object_id to end */
1608716113
word32 length = 0;
1608816114

16089-
tagSz = (type == oidHashType ||
16115+
tagSz = ((type == oidHashType ||
1609016116
(type == oidSigType && !IsSigAlgoECC((word32)algoOID)) ||
16091-
(type == oidKeyType && algoOID == RSAk)) ? 2U : 0U;
16117+
(type == oidKeyType && algoOID == RSAk)) &&
16118+
(absentParams == FALSE)) ? 2U : 0U;
1609216119
algoName = OidFromId((word32)algoOID, (word32)type, &algoSz);
1609316120
if (algoName == NULL) {
1609416121
WOLFSSL_MSG("Unknown Algorithm");
@@ -16144,6 +16171,10 @@ word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz)
1614416171
/* Don't put out NULL DER item. */
1614516172
dataASN[ALGOIDASN_IDX_NULL].noOut = 1;
1614616173
}
16174+
/* Override for absent (not NULL) params */
16175+
if (TRUE == absentParams) {
16176+
dataASN[ALGOIDASN_IDX_NULL].noOut = 1;
16177+
}
1614716178
if (algoOID == DSAk) {
1614816179
/* Don't include SEQUENCE for DSA keys. */
1614916180
o = 1;
@@ -16186,6 +16217,27 @@ word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz)
1618616217
#endif /* WOLFSSL_ASN_TEMPLATE */
1618716218
}
1618816219

16220+
/* Encode an algorithm identifier.
16221+
*
16222+
* [algoOID, type] is unique.
16223+
*
16224+
* @param [in] algoOID Algorithm identifier.
16225+
* @param [out] output Buffer to hold encoding.
16226+
* @param [in] type Type of OID being encoded.
16227+
* @param [in] curveSz Add extra space for curve data.
16228+
* @return Encoded data size on success.
16229+
* @return 0 when dynamic memory allocation fails.
16230+
*/
16231+
word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz)
16232+
{
16233+
return SetAlgoIDImpl(algoOID, output, type, curveSz, FALSE);
16234+
}
16235+
16236+
word32 SetAlgoIDEx(int algoOID, byte* output, int type, int curveSz, byte absentParams)
16237+
{
16238+
return SetAlgoIDImpl(algoOID, output, type, curveSz, absentParams);
16239+
}
16240+
1618916241
#ifdef WOLFSSL_ASN_TEMPLATE
1619016242
/* Always encode PKCS#1 v1.5 RSA signature and compare to encoded data. */
1619116243
/* ASN.1 template for DigestInfo for a PKCS#1 v1.5 RSA signature.

0 commit comments

Comments
 (0)