Merge pull request #1859 from SparkiDev/pkcs7-cons
Support constructed OCTET_STRING in PKCS#7 signed data
This commit is contained in:
commit
42fecee77b
@ -376,6 +376,8 @@ void wc_PKCS7_Free(PKCS7* pkcs7)
|
||||
if (pkcs7->der != NULL)
|
||||
XFREE(pkcs7->der, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
#endif
|
||||
if (pkcs7->contentDynamic != NULL)
|
||||
XFREE(pkcs7->contentDynamic, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
|
||||
if (pkcs7->isDynamic) {
|
||||
pkcs7->isDynamic = 0;
|
||||
@ -1903,15 +1905,18 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf,
|
||||
word32 idx, contentType, hashOID, sigOID, totalSz;
|
||||
int length, version, ret;
|
||||
byte* content = NULL;
|
||||
byte* contentDynamic = NULL;
|
||||
byte* sig = NULL;
|
||||
byte* cert = NULL;
|
||||
byte* signedAttrib = NULL;
|
||||
int contentSz = 0, sigSz = 0, certSz = 0, signedAttribSz = 0;
|
||||
word32 localIdx;
|
||||
word32 localIdx, start;
|
||||
byte degenerate;
|
||||
#ifdef ASN_BER_TO_DER
|
||||
byte* der;
|
||||
#endif
|
||||
int multiPart = 0, keepContent;
|
||||
int contentLen;
|
||||
|
||||
if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0)
|
||||
return BAD_FUNC_ARG;
|
||||
@ -2011,43 +2016,127 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf,
|
||||
if (ret == 0 && GetLength(pkiMsg, &localIdx, &length, totalSz) <= 0)
|
||||
ret = ASN_PARSE_E;
|
||||
|
||||
if (ret == 0 && pkiMsg[localIdx++] != ASN_OCTET_STRING)
|
||||
ret = ASN_PARSE_E;
|
||||
if (ret == 0 && pkiMsg[localIdx] == (ASN_OCTET_STRING | ASN_CONSTRUCTED)) {
|
||||
multiPart = 1;
|
||||
|
||||
if (ret == 0 && GetLength(pkiMsg, &localIdx, &length, totalSz) < 0)
|
||||
ret = ASN_PARSE_E;
|
||||
localIdx++;
|
||||
/* Get length of all OCTET_STRINGs. */
|
||||
if (GetLength(pkiMsg, &localIdx, &contentLen, totalSz) < 0)
|
||||
ret = ASN_PARSE_E;
|
||||
|
||||
/* Save the inner data as the content. */
|
||||
if (ret == 0 && length > 0) {
|
||||
contentSz = length;
|
||||
/* Check whether there is one OCTET_STRING inside. */
|
||||
start = localIdx;
|
||||
if (ret == 0 && pkiMsg[localIdx++] != ASN_OCTET_STRING)
|
||||
ret = ASN_PARSE_E;
|
||||
|
||||
/* support using header and footer without content */
|
||||
if (pkiMsg2 && pkiMsg2Sz > 0 && hashBuf && hashSz > 0) {
|
||||
/* Content not provided, use provided pkiMsg2 footer */
|
||||
content = NULL;
|
||||
localIdx = 0;
|
||||
if (contentSz != (int)pkcs7->contentSz) {
|
||||
WOLFSSL_MSG("Data signed does not match contentSz provided");
|
||||
return BUFFER_E;
|
||||
if (ret == 0 && GetLength(pkiMsg, &localIdx, &length, totalSz) < 0)
|
||||
ret = ASN_PARSE_E;
|
||||
|
||||
if (ret == 0) {
|
||||
/* Use single OCTET_STRING directly. */
|
||||
if (localIdx - start + length == (word32)contentLen)
|
||||
multiPart = 0;
|
||||
localIdx = start;
|
||||
}
|
||||
}
|
||||
if (ret == 0 && multiPart) {
|
||||
int i = 0;
|
||||
keepContent = !(pkiMsg2 && pkiMsg2Sz > 0 && hashBuf && hashSz > 0);
|
||||
|
||||
if (keepContent) {
|
||||
/* Create a buffer to hold content of OCTET_STRINGs. */
|
||||
pkcs7->contentDynamic = XMALLOC(contentLen, pkcs7->heap,
|
||||
DYNAMIC_TYPE_PKCS7);
|
||||
if (pkcs7->contentDynamic == NULL)
|
||||
ret = MEMORY_E;
|
||||
}
|
||||
|
||||
start = localIdx;
|
||||
/* Use the data from each OCTET_STRING. */
|
||||
while (ret == 0 && localIdx < start + contentLen) {
|
||||
if (pkiMsg[localIdx++] != ASN_OCTET_STRING)
|
||||
ret = ASN_PARSE_E;
|
||||
|
||||
if (ret == 0 && GetLength(pkiMsg, &localIdx, &length, totalSz) < 0)
|
||||
ret = ASN_PARSE_E;
|
||||
if (ret == 0 && length + localIdx > start + contentLen)
|
||||
ret = ASN_PARSE_E;
|
||||
|
||||
if (ret == 0) {
|
||||
if (keepContent) {
|
||||
XMEMCPY(pkcs7->contentDynamic + i, pkiMsg + localIdx,
|
||||
length);
|
||||
}
|
||||
i += length;
|
||||
localIdx += length;
|
||||
}
|
||||
}
|
||||
|
||||
length = i;
|
||||
if (ret == 0 && length > 0) {
|
||||
contentSz = length;
|
||||
|
||||
/* support using header and footer without content */
|
||||
if (pkiMsg2 && pkiMsg2Sz > 0 && hashBuf && hashSz > 0) {
|
||||
/* Content not provided, use provided pkiMsg2 footer */
|
||||
content = NULL;
|
||||
localIdx = 0;
|
||||
if (contentSz != (int)pkcs7->contentSz) {
|
||||
WOLFSSL_MSG("Data signed does not match contentSz provided");
|
||||
return BUFFER_E;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Content pointer for calculating hashes later */
|
||||
content = pkcs7->contentDynamic;
|
||||
pkiMsg2 = pkiMsg;
|
||||
pkiMsg2Sz = pkiMsgSz;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Content pointer for calculating hashes later */
|
||||
content = &pkiMsg[localIdx];
|
||||
localIdx += length;
|
||||
|
||||
pkiMsg2 = pkiMsg;
|
||||
pkiMsg2Sz = pkiMsgSz;
|
||||
}
|
||||
}
|
||||
else {
|
||||
pkiMsg2 = pkiMsg;
|
||||
if (ret == 0 && !multiPart) {
|
||||
if (pkiMsg[localIdx++] != ASN_OCTET_STRING)
|
||||
ret = ASN_PARSE_E;
|
||||
|
||||
if (ret == 0 && GetLength(pkiMsg, &localIdx, &length, totalSz) < 0)
|
||||
ret = ASN_PARSE_E;
|
||||
|
||||
/* Save the inner data as the content. */
|
||||
if (ret == 0 && length > 0) {
|
||||
contentSz = length;
|
||||
|
||||
/* support using header and footer without content */
|
||||
if (pkiMsg2 && pkiMsg2Sz > 0 && hashBuf && hashSz > 0) {
|
||||
/* Content not provided, use provided pkiMsg2 footer */
|
||||
content = NULL;
|
||||
localIdx = 0;
|
||||
if (contentSz != (int)pkcs7->contentSz) {
|
||||
WOLFSSL_MSG("Data signed does not match contentSz provided");
|
||||
return BUFFER_E;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Content pointer for calculating hashes later */
|
||||
content = &pkiMsg[localIdx];
|
||||
localIdx += length;
|
||||
|
||||
pkiMsg2 = pkiMsg;
|
||||
pkiMsg2Sz = pkiMsgSz;
|
||||
}
|
||||
}
|
||||
else {
|
||||
pkiMsg2 = pkiMsg;
|
||||
}
|
||||
}
|
||||
|
||||
/* update idx if successful */
|
||||
if (ret == 0) {
|
||||
if (ret == 0)
|
||||
idx = localIdx;
|
||||
}
|
||||
else
|
||||
pkiMsg2 = pkiMsg;
|
||||
|
||||
/* If getting the content info failed with non degenerate then return the
|
||||
* error case. Otherwise with a degenerate it is ok if the content
|
||||
@ -2082,8 +2171,10 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf,
|
||||
#ifdef ASN_BER_TO_DER
|
||||
der = pkcs7->der;
|
||||
#endif
|
||||
contentDynamic = pkcs7->contentDynamic;
|
||||
/* This will reset PKCS7 structure and then set the certificate */
|
||||
wc_PKCS7_InitWithCert(pkcs7, cert, certSz);
|
||||
pkcs7->contentDynamic = contentDynamic;
|
||||
#ifdef ASN_BER_TO_DER
|
||||
pkcs7->der = der;
|
||||
#endif
|
||||
|
@ -102,6 +102,7 @@ typedef struct PKCS7 {
|
||||
WC_RNG* rng;
|
||||
PKCS7Attrib* signedAttribs;
|
||||
byte* content; /* inner content, not owner */
|
||||
byte* contentDynamic; /* content if constructed OCTET_STRING */
|
||||
byte* singleCert; /* recipient cert, DER, not owner */
|
||||
const byte* issuer; /* issuer name of singleCert */
|
||||
byte* privateKey; /* private key, DER, not owner */
|
||||
|
Loading…
x
Reference in New Issue
Block a user