mirror of https://github.com/wolfSSL/wolfssl
Merge pull request #1349 from JacobBarthelmeh/PKCS7
pkcs7 attribute parsing
This commit is contained in:
commit
08696449f6
|
@ -341,6 +341,87 @@ void wc_PKCS7_Free(PKCS7* pkcs7)
|
|||
}
|
||||
|
||||
|
||||
/* helper function for parsing through attributes and finding a specific one.
|
||||
* returns PKCS7DecodedAttrib pointer on success */
|
||||
static PKCS7DecodedAttrib* findAttrib(PKCS7* pkcs7, const byte* oid, word32 oidSz)
|
||||
{
|
||||
PKCS7DecodedAttrib* list;
|
||||
|
||||
if (pkcs7 == NULL || oid == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* search attributes for pkiStatus */
|
||||
list = pkcs7->decodedAttrib;
|
||||
while (list != NULL) {
|
||||
word32 sz = oidSz;
|
||||
word32 idx = 0;
|
||||
int length = 0;
|
||||
|
||||
if (list->oid[idx++] != ASN_OBJECT_ID) {
|
||||
WOLFSSL_MSG("Bad attribute ASN1 syntax");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (GetLength(list->oid, &idx, &length, list->oidSz) < 0) {
|
||||
WOLFSSL_MSG("Bad attribute length");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sz = (sz < (word32)length)? sz : (word32)length;
|
||||
if (XMEMCMP(oid, list->oid + idx, sz) == 0) {
|
||||
return list;
|
||||
}
|
||||
list = list->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Searches through decoded attributes and returns the value for the first one
|
||||
* matching the oid passed in. Note that this value includes the leading ASN1
|
||||
* syntax. So for a printable string of "3" this would be something like
|
||||
*
|
||||
* 0x13, 0x01, 0x33
|
||||
* ID SIZE "3"
|
||||
*
|
||||
* pkcs7 structure to get value from
|
||||
* oid OID value to search for with attributes
|
||||
* oidSz size of oid buffer
|
||||
* out buffer to hold result
|
||||
* outSz size of out buffer (if out is NULL this is set to needed size and
|
||||
LENGTH_ONLY_E is returned)
|
||||
*
|
||||
* returns size of value on success
|
||||
*/
|
||||
int wc_PKCS7_GetAttributeValue(PKCS7* pkcs7, const byte* oid, word32 oidSz,
|
||||
byte* out, word32* outSz)
|
||||
{
|
||||
PKCS7DecodedAttrib* attrib;
|
||||
|
||||
if (pkcs7 == NULL || oid == NULL || outSz == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
attrib = findAttrib(pkcs7, oid, oidSz);
|
||||
if (attrib == NULL) {
|
||||
return ASN_PARSE_E;
|
||||
}
|
||||
|
||||
if (out == NULL) {
|
||||
*outSz = attrib->valueSz;
|
||||
return LENGTH_ONLY_E;
|
||||
}
|
||||
|
||||
if (*outSz < attrib->valueSz) {
|
||||
return BUFFER_E;
|
||||
}
|
||||
|
||||
XMEMCPY(out, attrib->value, attrib->valueSz);
|
||||
return attrib->valueSz;
|
||||
}
|
||||
|
||||
|
||||
/* build PKCS#7 data content type */
|
||||
int wc_PKCS7_EncodeData(PKCS7* pkcs7, byte* output, word32 outputSz)
|
||||
{
|
||||
|
@ -889,6 +970,11 @@ static int wc_PKCS7_SetHashType(PKCS7* pkcs7, enum wc_HashType* type)
|
|||
|
||||
switch (pkcs7->hashOID) {
|
||||
|
||||
#ifndef NO_MD5
|
||||
case MD5h:
|
||||
*type = WC_HASH_TYPE_MD5;
|
||||
break;
|
||||
#endif
|
||||
#ifndef NO_SHA
|
||||
case SHAh:
|
||||
*type = WC_HASH_TYPE_SHA;
|
||||
|
@ -1647,6 +1733,101 @@ static int wc_PKCS7_SetPublicKeyOID(PKCS7* pkcs7, int sigOID)
|
|||
}
|
||||
|
||||
|
||||
/* Parses through the attributes and adds them to the PKCS7 structure
|
||||
* Creates dynamic attribute structures that are free'd with calling
|
||||
* wc_PKCS7_Free()
|
||||
*
|
||||
* NOTE: An attribute has the ASN1 format of
|
||||
** Sequence
|
||||
****** Object ID
|
||||
****** Set
|
||||
********** {PritnableString, UTCTime, OCTET STRING ...}
|
||||
*
|
||||
* pkcs7 the PKCS7 structure to put the parsed attributes into
|
||||
* in buffer holding all attributes
|
||||
* inSz size of in buffer
|
||||
*
|
||||
* returns the number of attributes parsed on success
|
||||
*/
|
||||
static int wc_PKCS7_ParseAttribs(PKCS7* pkcs7, byte* in, int inSz)
|
||||
{
|
||||
int found = 0;
|
||||
word32 idx = 0;
|
||||
word32 oid;
|
||||
|
||||
if (pkcs7 == NULL || in == NULL || inSz < 0) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
while (idx < (word32)inSz) {
|
||||
int length = 0;
|
||||
int oidIdx;
|
||||
PKCS7DecodedAttrib* attrib;
|
||||
|
||||
if (GetSequence(in, &idx, &length, inSz) < 0)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
attrib = (PKCS7DecodedAttrib*)XMALLOC(sizeof(PKCS7DecodedAttrib),
|
||||
pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
if (attrib == NULL) {
|
||||
return MEMORY_E;
|
||||
}
|
||||
XMEMSET(attrib, 0, sizeof(PKCS7DecodedAttrib));
|
||||
|
||||
oidIdx = idx;
|
||||
if (GetObjectId(in, &idx, &oid, oidIgnoreType, inSz)
|
||||
< 0) {
|
||||
XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
return ASN_PARSE_E;
|
||||
}
|
||||
attrib->oidSz = idx - oidIdx;
|
||||
attrib->oid = (byte*)XMALLOC(attrib->oidSz, pkcs7->heap,
|
||||
DYNAMIC_TYPE_PKCS7);
|
||||
if (attrib->oid == NULL) {
|
||||
XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
return MEMORY_E;
|
||||
}
|
||||
XMEMCPY(attrib->oid, in + oidIdx, attrib->oidSz);
|
||||
|
||||
|
||||
/* Get Set that contains the printable string value */
|
||||
if (GetSet(in, &idx, &length, inSz) < 0) {
|
||||
XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
return ASN_PARSE_E;
|
||||
}
|
||||
|
||||
if ((inSz - idx) < (word32)length) {
|
||||
XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
return ASN_PARSE_E;
|
||||
}
|
||||
|
||||
attrib->valueSz = (word32)length;
|
||||
attrib->value = (byte*)XMALLOC(attrib->valueSz, pkcs7->heap,
|
||||
DYNAMIC_TYPE_PKCS7);
|
||||
if (attrib->value == NULL) {
|
||||
XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
return MEMORY_E;
|
||||
}
|
||||
XMEMCPY(attrib->value, in + idx, attrib->valueSz);
|
||||
idx += length;
|
||||
|
||||
/* store attribute in linked list */
|
||||
if (pkcs7->decodedAttrib != NULL) {
|
||||
attrib->next = pkcs7->decodedAttrib;
|
||||
pkcs7->decodedAttrib = attrib;
|
||||
} else {
|
||||
pkcs7->decodedAttrib = attrib;
|
||||
}
|
||||
found++;
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
/* Finds the certificates in the message and saves it. */
|
||||
int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz)
|
||||
{
|
||||
|
@ -1737,8 +1918,8 @@ int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz)
|
|||
/* Save the inner data as the content. */
|
||||
if (length > 0) {
|
||||
/* Local pointer for calculating hashes later */
|
||||
pkcs7->content = content = &pkiMsg[localIdx];
|
||||
pkcs7->contentSz = contentSz = length;
|
||||
content = &pkiMsg[localIdx];
|
||||
contentSz = length;
|
||||
localIdx += length;
|
||||
}
|
||||
|
||||
|
@ -1777,11 +1958,41 @@ int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz)
|
|||
cert = &pkiMsg[idx];
|
||||
certSz += (certIdx - idx);
|
||||
}
|
||||
|
||||
/* This will reset PKCS7 structure and then set the certificate */
|
||||
wc_PKCS7_InitWithCert(pkcs7, cert, certSz);
|
||||
|
||||
/* iterate through any additional certificates */
|
||||
if (MAX_PKCS7_CERTS > 0) {
|
||||
word32 localIdx;
|
||||
int sz = 0;
|
||||
int i;
|
||||
|
||||
pkcs7->cert[0] = cert;
|
||||
pkcs7->certSz[0] = certSz;
|
||||
certIdx = idx + certSz;
|
||||
|
||||
for (i = 1; i < MAX_PKCS7_CERTS && certIdx + 1 < pkiMsgSz; i++) {
|
||||
localIdx = certIdx;
|
||||
|
||||
if (pkiMsg[certIdx++] == (ASN_CONSTRUCTED | ASN_SEQUENCE)) {
|
||||
if (GetLength(pkiMsg, &certIdx, &sz, pkiMsgSz) < 0)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
pkcs7->cert[i] = &pkiMsg[localIdx];
|
||||
pkcs7->certSz[i] = sz + (certIdx - localIdx);
|
||||
certIdx += sz;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
idx += length;
|
||||
}
|
||||
|
||||
/* set content and size after init of PKCS7 structure */
|
||||
pkcs7->content = content;
|
||||
pkcs7->contentSz = contentSz;
|
||||
|
||||
/* Get the implicit[1] set of crls */
|
||||
if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) {
|
||||
idx++;
|
||||
|
@ -1834,6 +2045,11 @@ int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz)
|
|||
signedAttrib = &pkiMsg[idx];
|
||||
signedAttribSz = length;
|
||||
|
||||
if (wc_PKCS7_ParseAttribs(pkcs7, signedAttrib, signedAttribSz) <0) {
|
||||
WOLFSSL_MSG("Error parsing signed attributes");
|
||||
return ASN_PARSE_E;
|
||||
}
|
||||
|
||||
idx += length;
|
||||
}
|
||||
|
||||
|
@ -4516,9 +4732,8 @@ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz)
|
|||
static int wc_PKCS7_DecodeUnprotectedAttributes(PKCS7* pkcs7, byte* pkiMsg,
|
||||
word32 pkiMsgSz, word32* inOutIdx)
|
||||
{
|
||||
int length, attribLen;
|
||||
word32 oid, savedIdx, idx;
|
||||
PKCS7DecodedAttrib* attrib = NULL;
|
||||
int ret, attribLen;
|
||||
word32 idx;
|
||||
|
||||
if (pkcs7 == NULL || pkiMsg == NULL ||
|
||||
pkiMsgSz == 0 || inOutIdx == NULL)
|
||||
|
@ -4534,67 +4749,8 @@ static int wc_PKCS7_DecodeUnprotectedAttributes(PKCS7* pkcs7, byte* pkiMsg,
|
|||
return ASN_PARSE_E;
|
||||
|
||||
/* loop through attributes */
|
||||
while (attribLen > 0) {
|
||||
|
||||
if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
||||
return ASN_PARSE_E;
|
||||
|
||||
attribLen -= (length + 2); /* TAG + LENGTH + DATA */
|
||||
savedIdx = idx;
|
||||
|
||||
attrib = (PKCS7DecodedAttrib*)XMALLOC(sizeof(PKCS7DecodedAttrib),
|
||||
pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
if (attrib == NULL) {
|
||||
return MEMORY_E;
|
||||
}
|
||||
XMEMSET(attrib, 0, sizeof(PKCS7DecodedAttrib));
|
||||
|
||||
/* save attribute OID bytes and size */
|
||||
if (GetObjectId(pkiMsg, &idx, &oid, oidIgnoreType, pkiMsgSz) < 0) {
|
||||
XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
return ASN_PARSE_E;
|
||||
}
|
||||
|
||||
attrib->oidSz = idx - savedIdx;
|
||||
attrib->oid = (byte*)XMALLOC(attrib->oidSz, pkcs7->heap,
|
||||
DYNAMIC_TYPE_PKCS7);
|
||||
if (attrib->oid == NULL) {
|
||||
XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
return MEMORY_E;
|
||||
}
|
||||
XMEMCPY(attrib->oid, pkiMsg + savedIdx, attrib->oidSz);
|
||||
|
||||
/* save attribute value bytes and size */
|
||||
if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0) {
|
||||
XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
return ASN_PARSE_E;
|
||||
}
|
||||
|
||||
if ((pkiMsgSz - idx) < (word32)length) {
|
||||
XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
return ASN_PARSE_E;
|
||||
}
|
||||
|
||||
attrib->valueSz = (word32)length;
|
||||
attrib->value = (byte*)XMALLOC(attrib->valueSz, pkcs7->heap,
|
||||
DYNAMIC_TYPE_PKCS7);
|
||||
if (attrib->value == NULL) {
|
||||
XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||
return MEMORY_E;
|
||||
}
|
||||
XMEMCPY(attrib->value, pkiMsg + idx, attrib->valueSz);
|
||||
idx += length;
|
||||
|
||||
/* store attribute in linked list */
|
||||
if (pkcs7->decodedAttrib != NULL) {
|
||||
attrib->next = pkcs7->decodedAttrib;
|
||||
pkcs7->decodedAttrib = attrib;
|
||||
} else {
|
||||
pkcs7->decodedAttrib = attrib;
|
||||
}
|
||||
if ((ret = wc_PKCS7_ParseAttribs(pkcs7, pkiMsg + idx, attribLen)) < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
*inOutIdx = idx;
|
||||
|
|
|
@ -16863,12 +16863,48 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz,
|
|||
return -7709;
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
/* check getting signed attributes */
|
||||
#ifndef NO_SHA
|
||||
byte buf[(WC_SHA_DIGEST_SIZE + 1) * 2 + 1];
|
||||
#else
|
||||
byte buf[(WC_SHA256_DIGEST_SIZE + 1) * 2 + 1];
|
||||
#endif
|
||||
byte* oidPt = transIdOid + 2; /* skip object id tag and size */
|
||||
int oidSz = (int)sizeof(transIdOid) - 2;
|
||||
int bufSz = 0;
|
||||
|
||||
if (testVectors[i].signedAttribs != NULL &&
|
||||
wc_PKCS7_GetAttributeValue(&pkcs7, oidPt, oidSz,
|
||||
NULL, (word32*)&bufSz) != LENGTH_ONLY_E) {
|
||||
XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
wc_PKCS7_Free(&pkcs7);
|
||||
return -7710;
|
||||
}
|
||||
|
||||
if (bufSz > (int)sizeof(buf)) {
|
||||
XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
wc_PKCS7_Free(&pkcs7);
|
||||
return -7711;
|
||||
}
|
||||
|
||||
bufSz = wc_PKCS7_GetAttributeValue(&pkcs7, oidPt, oidSz,
|
||||
buf, (word32*)&bufSz);
|
||||
if ((testVectors[i].signedAttribs != NULL && bufSz < 0) ||
|
||||
(testVectors[i].signedAttribs == NULL && bufSz > 0)) {
|
||||
XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
wc_PKCS7_Free(&pkcs7);
|
||||
return -7712;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PKCS7_OUTPUT_TEST_BUNDLES
|
||||
file = fopen("./pkcs7cert.der", "wb");
|
||||
if (!file) {
|
||||
XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
wc_PKCS7_Free(&pkcs7);
|
||||
return -7710;
|
||||
return -7713;
|
||||
}
|
||||
ret = (int)fwrite(pkcs7.singleCert, 1, pkcs7.singleCertSz, file);
|
||||
fclose(file);
|
||||
|
|
|
@ -43,6 +43,11 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Max number of certificates that PKCS7 structure can parse */
|
||||
#ifndef MAX_PKCS7_CERTS
|
||||
#define MAX_PKCS7_CERTS 4
|
||||
#endif
|
||||
|
||||
/* PKCS#7 content types, ref RFC 2315 (Section 14) */
|
||||
enum PKCS7_TYPES {
|
||||
PKCS7_MSG = 650, /* 1.2.840.113549.1.7 */
|
||||
|
@ -100,6 +105,8 @@ typedef struct PKCS7 {
|
|||
int keyAgreeOID; /* key agreement algorithm OID */
|
||||
|
||||
void* heap; /* heap hint for dynamic memory */
|
||||
byte* cert[MAX_PKCS7_CERTS];
|
||||
word32 certSz[MAX_PKCS7_CERTS];
|
||||
byte* singleCert; /* recipient cert, DER, not owner */
|
||||
word32 singleCertSz; /* size of recipient cert buffer, bytes */
|
||||
byte issuerHash[KEYID_SIZE]; /* hash of all alt Names */
|
||||
|
@ -108,7 +115,7 @@ typedef struct PKCS7 {
|
|||
byte issuerSn[MAX_SN_SZ]; /* singleCert's serial number */
|
||||
word32 issuerSnSz; /* length of serial number */
|
||||
|
||||
byte publicKey[512];
|
||||
byte publicKey[MAX_RSA_INT_SZ + MAX_RSA_E_SZ ];/*MAX RSA key size (m + e)*/
|
||||
word32 publicKeySz;
|
||||
word32 publicKeyOID; /* key OID (RSAk, ECDSAk, etc) */
|
||||
byte* privateKey; /* private key, DER, not owner */
|
||||
|
@ -134,6 +141,8 @@ WOLFSSL_API int wc_PKCS7_Init(PKCS7* pkcs7, void* heap, int devId);
|
|||
WOLFSSL_API int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* cert, word32 certSz);
|
||||
WOLFSSL_API void wc_PKCS7_Free(PKCS7* pkcs7);
|
||||
|
||||
WOLFSSL_API int wc_PKCS7_GetAttributeValue(PKCS7* pkcs7, const byte* oid,
|
||||
word32 oidSz, byte* out, word32* outSz);
|
||||
WOLFSSL_API int wc_PKCS7_EncodeData(PKCS7* pkcs7, byte* output,
|
||||
word32 outputSz);
|
||||
WOLFSSL_API int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7,
|
||||
|
|
Loading…
Reference in New Issue