Merge pull request #1859 from SparkiDev/pkcs7-cons

Support constructed OCTET_STRING in PKCS#7 signed data
pull/1891/head
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) if (pkcs7->der != NULL)
XFREE(pkcs7->der, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(pkcs7->der, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
#endif #endif
if (pkcs7->contentDynamic != NULL)
XFREE(pkcs7->contentDynamic, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
if (pkcs7->isDynamic) { if (pkcs7->isDynamic) {
pkcs7->isDynamic = 0; pkcs7->isDynamic = 0;
@ -1903,15 +1905,18 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf,
word32 idx, contentType, hashOID, sigOID, totalSz; word32 idx, contentType, hashOID, sigOID, totalSz;
int length, version, ret; int length, version, ret;
byte* content = NULL; byte* content = NULL;
byte* contentDynamic = NULL;
byte* sig = NULL; byte* sig = NULL;
byte* cert = NULL; byte* cert = NULL;
byte* signedAttrib = NULL; byte* signedAttrib = NULL;
int contentSz = 0, sigSz = 0, certSz = 0, signedAttribSz = 0; int contentSz = 0, sigSz = 0, certSz = 0, signedAttribSz = 0;
word32 localIdx; word32 localIdx, start;
byte degenerate; byte degenerate;
#ifdef ASN_BER_TO_DER #ifdef ASN_BER_TO_DER
byte* der; byte* der;
#endif #endif
int multiPart = 0, keepContent;
int contentLen;
if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0) if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0)
return BAD_FUNC_ARG; 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) if (ret == 0 && GetLength(pkiMsg, &localIdx, &length, totalSz) <= 0)
ret = ASN_PARSE_E; ret = ASN_PARSE_E;
if (ret == 0 && pkiMsg[localIdx++] != ASN_OCTET_STRING) if (ret == 0 && pkiMsg[localIdx] == (ASN_OCTET_STRING | ASN_CONSTRUCTED)) {
ret = ASN_PARSE_E; multiPart = 1;
if (ret == 0 && GetLength(pkiMsg, &localIdx, &length, totalSz) < 0) localIdx++;
ret = ASN_PARSE_E; /* Get length of all OCTET_STRINGs. */
if (GetLength(pkiMsg, &localIdx, &contentLen, totalSz) < 0)
ret = ASN_PARSE_E;
/* Save the inner data as the content. */ /* Check whether there is one OCTET_STRING inside. */
if (ret == 0 && length > 0) { start = localIdx;
contentSz = length; if (ret == 0 && pkiMsg[localIdx++] != ASN_OCTET_STRING)
ret = ASN_PARSE_E;
/* support using header and footer without content */ if (ret == 0 && GetLength(pkiMsg, &localIdx, &length, totalSz) < 0)
if (pkiMsg2 && pkiMsg2Sz > 0 && hashBuf && hashSz > 0) { ret = ASN_PARSE_E;
/* Content not provided, use provided pkiMsg2 footer */
content = NULL; if (ret == 0) {
localIdx = 0; /* Use single OCTET_STRING directly. */
if (contentSz != (int)pkcs7->contentSz) { if (localIdx - start + length == (word32)contentLen)
WOLFSSL_MSG("Data signed does not match contentSz provided"); multiPart = 0;
return BUFFER_E; 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 { else {
/* Content pointer for calculating hashes later */
content = &pkiMsg[localIdx];
localIdx += length;
pkiMsg2 = pkiMsg; pkiMsg2 = pkiMsg;
pkiMsg2Sz = pkiMsgSz;
} }
} }
else { if (ret == 0 && !multiPart) {
pkiMsg2 = pkiMsg; 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 */ /* update idx if successful */
if (ret == 0) { if (ret == 0)
idx = localIdx; idx = localIdx;
} else
pkiMsg2 = pkiMsg;
/* If getting the content info failed with non degenerate then return the /* If getting the content info failed with non degenerate then return the
* error case. Otherwise with a degenerate it is ok if the content * 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 #ifdef ASN_BER_TO_DER
der = pkcs7->der; der = pkcs7->der;
#endif #endif
contentDynamic = pkcs7->contentDynamic;
/* This will reset PKCS7 structure and then set the certificate */ /* This will reset PKCS7 structure and then set the certificate */
wc_PKCS7_InitWithCert(pkcs7, cert, certSz); wc_PKCS7_InitWithCert(pkcs7, cert, certSz);
pkcs7->contentDynamic = contentDynamic;
#ifdef ASN_BER_TO_DER #ifdef ASN_BER_TO_DER
pkcs7->der = der; pkcs7->der = der;
#endif #endif

View File

@ -102,6 +102,7 @@ typedef struct PKCS7 {
WC_RNG* rng; WC_RNG* rng;
PKCS7Attrib* signedAttribs; PKCS7Attrib* signedAttribs;
byte* content; /* inner content, not owner */ byte* content; /* inner content, not owner */
byte* contentDynamic; /* content if constructed OCTET_STRING */
byte* singleCert; /* recipient cert, DER, not owner */ byte* singleCert; /* recipient cert, DER, not owner */
const byte* issuer; /* issuer name of singleCert */ const byte* issuer; /* issuer name of singleCert */
byte* privateKey; /* private key, DER, not owner */ byte* privateKey; /* private key, DER, not owner */