Skip to content

Commit

Permalink
Merge pull request #7845 from ColtonWilley/pkcs7_digest_absent_params
Browse files Browse the repository at this point in the history
Add option for absent hash params in PKCS7
  • Loading branch information
JacobBarthelmeh authored Aug 9, 2024
2 parents 0d84597 + 0a5ebaf commit 85bab19
Show file tree
Hide file tree
Showing 5 changed files with 258 additions and 32 deletions.
162 changes: 162 additions & 0 deletions tests/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -38789,6 +38789,167 @@ static int test_wc_PKCS7_EncodeSignedData(void)
return EXPECT_RESULT();
} /* END test_wc_PKCS7_EncodeSignedData */

static int test_wc_PKCS7_EncodeSignedData_absent(void)
{
EXPECT_DECLS;
#if defined(HAVE_PKCS7)
PKCS7* pkcs7 = NULL;
WC_RNG rng;
byte output[FOURK_BUF];
word32 outputSz = (word32)sizeof(output);
int withParamsLen = 0;
int withoutParamsLen = 0;
byte data[] = "Test data to encode.";
#ifndef NO_RSA
#if defined(USE_CERT_BUFFERS_2048)
byte key[sizeof(client_key_der_2048)];
byte cert[sizeof(client_cert_der_2048)];
word32 keySz = (word32)sizeof(key);
word32 certSz = (word32)sizeof(cert);
XMEMSET(key, 0, keySz);
XMEMSET(cert, 0, certSz);
XMEMCPY(key, client_key_der_2048, keySz);
XMEMCPY(cert, client_cert_der_2048, certSz);
#elif defined(USE_CERT_BUFFERS_1024)
byte key[sizeof_client_key_der_1024];
byte cert[sizeof(sizeof_client_cert_der_1024)];
word32 keySz = (word32)sizeof(key);
word32 certSz = (word32)sizeof(cert);
XMEMSET(key, 0, keySz);
XMEMSET(cert, 0, certSz);
XMEMCPY(key, client_key_der_1024, keySz);
XMEMCPY(cert, client_cert_der_1024, certSz);
#else
unsigned char cert[ONEK_BUF];
unsigned char key[ONEK_BUF];
XFILE fp = XBADFILE;
int certSz;
int keySz;

ExpectTrue((fp = XFOPEN("./certs/1024/client-cert.der", "rb")) !=
XBADFILE);
ExpectIntGT(certSz = (int)XFREAD(cert, 1, sizeof_client_cert_der_1024,
fp), 0);
if (fp != XBADFILE) {
XFCLOSE(fp);
fp = XBADFILE;
}

ExpectTrue((fp = XFOPEN("./certs/1024/client-key.der", "rb")) !=
XBADFILE);
ExpectIntGT(keySz = (int)XFREAD(key, 1, sizeof_client_key_der_1024, fp),
0);
if (fp != XBADFILE)
XFCLOSE(fp);
#endif
#elif defined(HAVE_ECC)
#if defined(USE_CERT_BUFFERS_256)
unsigned char cert[sizeof(cliecc_cert_der_256)];
unsigned char key[sizeof(ecc_clikey_der_256)];
int certSz = (int)sizeof(cert);
int keySz = (int)sizeof(key);
XMEMSET(cert, 0, certSz);
XMEMSET(key, 0, keySz);
XMEMCPY(cert, cliecc_cert_der_256, certSz);
XMEMCPY(key, ecc_clikey_der_256, keySz);
#else
unsigned char cert[ONEK_BUF];
unsigned char key[ONEK_BUF];
XFILE fp = XBADFILE;
int certSz;
int keySz;

ExpectTrue((fp = XFOPEN("./certs/client-ecc-cert.der", "rb")) !=
XBADFILE);
ExpectIntGT(certSz = (int)XFREAD(cert, 1, ONEK_BUF, fp), 0);
if (fp != XBADFILE) {
XFCLOSE(fp);
fp = XBADFILE;
}

ExpectTrue((fp = XFOPEN("./certs/client-ecc-key.der", "rb")) !=
XBADFILE);
ExpectIntGT(keySz = (int)XFREAD(key, 1, ONEK_BUF, fp), 0);
if (fp != XBADFILE)
XFCLOSE(fp);
#endif
#endif

XMEMSET(&rng, 0, sizeof(WC_RNG));

XMEMSET(output, 0, outputSz);
ExpectIntEQ(wc_InitRng(&rng), 0);

/* First generate and verify with NULL params */
ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId));
ExpectIntEQ(wc_PKCS7_Init(pkcs7, HEAP_HINT, INVALID_DEVID), 0);
ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, cert, certSz), 0);

if (pkcs7 != NULL) {
pkcs7->content = data;
pkcs7->contentSz = (word32)sizeof(data);
pkcs7->privateKey = key;
pkcs7->privateKeySz = (word32)sizeof(key);
pkcs7->encryptOID = RSAk;
#ifdef NO_SHA
pkcs7->hashOID = SHA256h;
#else
pkcs7->hashOID = SHAh;
#endif
pkcs7->rng = &rng;
}

withParamsLen = wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz);
ExpectIntGT(withParamsLen, 0);
wc_PKCS7_Free(pkcs7);
pkcs7 = NULL;

ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId));
ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, 0), 0);
ExpectIntEQ(wc_PKCS7_VerifySignedData(pkcs7, output, withParamsLen), 0);
wc_PKCS7_Free(pkcs7);
pkcs7 = NULL;

XMEMSET(output, 0, outputSz);

/* Now generate again without params */
ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId));
ExpectIntEQ(wc_PKCS7_Init(pkcs7, HEAP_HINT, INVALID_DEVID), 0);
ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, cert, certSz), 0);

if (pkcs7 != NULL) {
pkcs7->content = data;
pkcs7->contentSz = (word32)sizeof(data);
pkcs7->privateKey = key;
pkcs7->privateKeySz = (word32)sizeof(key);
pkcs7->encryptOID = RSAk;
#ifdef NO_SHA
pkcs7->hashOID = SHA256h;
#else
pkcs7->hashOID = SHAh;
#endif
pkcs7->rng = &rng;
pkcs7->hashParamsAbsent = TRUE;
}

withoutParamsLen = wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz);
ExpectIntGT(withoutParamsLen, 0);
wc_PKCS7_Free(pkcs7);
pkcs7 = NULL;

ExpectNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, testDevId));
ExpectIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, 0), 0);
ExpectIntEQ(wc_PKCS7_VerifySignedData(pkcs7, output, withoutParamsLen), 0);

/* Both are valid PKCS7 with non-zero len, ensure without is shorter */
ExpectIntLT(withoutParamsLen, withParamsLen);

wc_PKCS7_Free(pkcs7);
DoExpectIntEQ(wc_FreeRng(&rng), 0);

#endif
return EXPECT_RESULT();
}

/*
* Testing wc_PKCS7_EncodeSignedData_ex() and wc_PKCS7_VerifySignedData_ex()
Expand Down Expand Up @@ -84809,6 +84970,7 @@ TEST_CASE testCases[] = {
TEST_DECL(test_wc_PKCS7_EncodeData),
TEST_DECL(test_wc_PKCS7_EncodeSignedData),
TEST_DECL(test_wc_PKCS7_EncodeSignedData_ex),
TEST_DECL(test_wc_PKCS7_EncodeSignedData_absent),
TEST_DECL(test_wc_PKCS7_VerifySignedData_RSA),
TEST_DECL(test_wc_PKCS7_VerifySignedData_ECC),
TEST_DECL(test_wc_PKCS7_EncodeDecodeEnvelopedData),
Expand Down
90 changes: 71 additions & 19 deletions wolfcrypt/src/asn.c
Original file line number Diff line number Diff line change
Expand Up @@ -6061,22 +6061,8 @@ enum {
#define algoIdASN_Length (sizeof(algoIdASN) / sizeof(ASNItem))
#endif

/* Get the OID id/sum from the BER encoding of an algorithm identifier.
*
* NULL tag is skipped if present.
*
* @param [in] input Buffer holding BER encoded data.
* @param [in, out] inOutIdx On in, start of algorithm identifier.
* On out, start of ASN.1 item after algorithm id.
* @param [out] oid Id of OID in algorithm identifier data.
* @param [in] oidType Type of OID to expect.
* @param [in] maxIdx Maximum index of data in buffer.
* @return 0 on success.
* @return ASN_PARSE_E when encoding is invalid.
* @return ASN_UNKNOWN_OID_E when the OID cannot be verified.
*/
int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid,
word32 oidType, word32 maxIdx)
static int GetAlgoIdImpl(const byte* input, word32* inOutIdx, word32* oid,
word32 oidType, word32 maxIdx, byte *absentParams)
{
#ifndef WOLFSSL_ASN_TEMPLATE
int length;
Expand All @@ -6102,6 +6088,10 @@ int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid,
ret = GetASNNull(input, &idx, maxIdx);
if (ret != 0)
return ret;

if (absentParams != NULL) {
*absentParams = FALSE;
}
}
}
}
Expand All @@ -6126,13 +6116,49 @@ int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid,
if (ret == 0) {
/* Return the OID id/sum. */
*oid = dataASN[ALGOIDASN_IDX_OID].data.oid.sum;

if ((absentParams != NULL) &&
(dataASN[ALGOIDASN_IDX_NULL].tag == ASN_TAG_NULL)) {
*absentParams = FALSE;
}
}

FREE_ASNGETDATA(dataASN, NULL);
return ret;
#endif /* WOLFSSL_ASN_TEMPLATE */
}

/* Get the OID id/sum from the BER encoding of an algorithm identifier.
*
* NULL tag is skipped if present.
*
* @param [in] input Buffer holding BER encoded data.
* @param [in, out] inOutIdx On in, start of algorithm identifier.
* On out, start of ASN.1 item after algorithm id.
* @param [out] oid Id of OID in algorithm identifier data.
* @param [in] oidType Type of OID to expect.
* @param [in] maxIdx Maximum index of data in buffer.
* @return 0 on success.
* @return ASN_PARSE_E when encoding is invalid.
* @return ASN_UNKNOWN_OID_E when the OID cannot be verified.
*/
int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid,
word32 oidType, word32 maxIdx)
{
return GetAlgoIdImpl(input, inOutIdx, oid, oidType, maxIdx, NULL);
}

int GetAlgoIdEx(const byte* input, word32* inOutIdx, word32* oid,
word32 oidType, word32 maxIdx, byte *absentParams)
{
/* Assume absent until proven otherwise */
if (absentParams != NULL) {
*absentParams = TRUE;
}

return GetAlgoIdImpl(input, inOutIdx, oid, oidType, maxIdx, absentParams);
}

#ifndef NO_RSA

#ifdef WC_RSA_PSS
Expand Down Expand Up @@ -16077,7 +16103,7 @@ static WC_INLINE int IsSigAlgoECC(word32 algoOID)
* @return Encoded data size on success.
* @return 0 when dynamic memory allocation fails.
*/
word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz)
static word32 SetAlgoIDImpl(int algoOID, byte* output, int type, int curveSz, byte absentParams)
{
#ifndef WOLFSSL_ASN_TEMPLATE
word32 tagSz, idSz, seqSz, algoSz = 0;
Expand All @@ -16086,9 +16112,10 @@ word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz)
byte seqArray[MAX_SEQ_SZ + 1]; /* add object_id to end */
word32 length = 0;

tagSz = (type == oidHashType ||
tagSz = ((type == oidHashType ||
(type == oidSigType && !IsSigAlgoECC((word32)algoOID)) ||
(type == oidKeyType && algoOID == RSAk)) ? 2U : 0U;
(type == oidKeyType && algoOID == RSAk)) &&
(absentParams == FALSE)) ? 2U : 0U;
algoName = OidFromId((word32)algoOID, (word32)type, &algoSz);
if (algoName == NULL) {
WOLFSSL_MSG("Unknown Algorithm");
Expand Down Expand Up @@ -16144,6 +16171,10 @@ word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz)
/* Don't put out NULL DER item. */
dataASN[ALGOIDASN_IDX_NULL].noOut = 1;
}
/* Override for absent (not NULL) params */
if (TRUE == absentParams) {
dataASN[ALGOIDASN_IDX_NULL].noOut = 1;
}
if (algoOID == DSAk) {
/* Don't include SEQUENCE for DSA keys. */
o = 1;
Expand Down Expand Up @@ -16186,6 +16217,27 @@ word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz)
#endif /* WOLFSSL_ASN_TEMPLATE */
}

/* Encode an algorithm identifier.
*
* [algoOID, type] is unique.
*
* @param [in] algoOID Algorithm identifier.
* @param [out] output Buffer to hold encoding.
* @param [in] type Type of OID being encoded.
* @param [in] curveSz Add extra space for curve data.
* @return Encoded data size on success.
* @return 0 when dynamic memory allocation fails.
*/
word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz)
{
return SetAlgoIDImpl(algoOID, output, type, curveSz, FALSE);
}

word32 SetAlgoIDEx(int algoOID, byte* output, int type, int curveSz, byte absentParams)
{
return SetAlgoIDImpl(algoOID, output, type, curveSz, absentParams);
}

#ifdef WOLFSSL_ASN_TEMPLATE
/* Always encode PKCS#1 v1.5 RSA signature and compare to encoded data. */
/* ASN.1 template for DigestInfo for a PKCS#1 v1.5 RSA signature.
Expand Down
Loading

0 comments on commit 85bab19

Please sign in to comment.