Merge pull request #1859 from SparkiDev/pkcs7-cons

Support constructed OCTET_STRING in PKCS#7 signed data
This commit is contained in:
toddouska 2018-10-22 14:52:50 -07:00 committed by GitHub
commit 42fecee77b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 117 additions and 25 deletions

View File

@ -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

View File

@ -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 */