| Index: nss/lib/pkcs7/certread.c
|
| ===================================================================
|
| --- nss/lib/pkcs7/certread.c (revision 195639)
|
| +++ nss/lib/pkcs7/certread.c (working copy)
|
| @@ -3,7 +3,6 @@
|
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
| #include "cert.h"
|
| -#include "secpkcs7.h"
|
| #include "base64.h"
|
| #include "secitem.h"
|
| #include "secder.h"
|
| @@ -12,26 +11,137 @@
|
| #include "secerr.h"
|
|
|
| SEC_ASN1_MKSUB(SEC_AnyTemplate)
|
| +SEC_ASN1_MKSUB(SEC_SetOfAnyTemplate)
|
|
|
| -SECStatus
|
| +typedef struct ContentInfoStr ContentInfo;
|
| +typedef struct DegenerateSignedDataStr DegenerateSignedData;
|
| +
|
| +struct ContentInfoStr {
|
| + SECOidTag contentTypeTag; /* local; not part of encoding */
|
| + SECItem contentType;
|
| + union {
|
| + SECItem *data;
|
| + DegenerateSignedData *signedData;
|
| + } content;
|
| +};
|
| +
|
| +struct DegenerateSignedDataStr {
|
| + SECItem version;
|
| + SECItem **digestAlgorithms;
|
| + ContentInfo contentInfo;
|
| + SECItem **certificates;
|
| + SECItem **crls;
|
| + SECItem **signerInfos;
|
| +};
|
| +
|
| +static const SEC_ASN1Template *
|
| +choose_content_template(void *src_or_dest, PRBool encoding);
|
| +
|
| +static const SEC_ASN1TemplateChooserPtr template_chooser
|
| + = choose_content_template;
|
| +
|
| +static const SEC_ASN1Template ContentInfoTemplate[] = {
|
| + { SEC_ASN1_SEQUENCE,
|
| + 0, NULL, sizeof(ContentInfo) },
|
| + { SEC_ASN1_OBJECT_ID,
|
| + offsetof(ContentInfo,contentType) },
|
| + { SEC_ASN1_OPTIONAL | SEC_ASN1_DYNAMIC |
|
| + SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
|
| + offsetof(ContentInfo,content),
|
| + &template_chooser },
|
| + { 0 }
|
| +};
|
| +
|
| +static const SEC_ASN1Template DegenerateSignedDataTemplate[] = {
|
| + { SEC_ASN1_SEQUENCE,
|
| + 0, NULL, sizeof(DegenerateSignedData) },
|
| + { SEC_ASN1_INTEGER,
|
| + offsetof(DegenerateSignedData,version) },
|
| + { SEC_ASN1_SET_OF | SEC_ASN1_XTRN,
|
| + offsetof(DegenerateSignedData,digestAlgorithms),
|
| + SEC_ASN1_SUB(SEC_AnyTemplate) },
|
| + { SEC_ASN1_INLINE,
|
| + offsetof(DegenerateSignedData,contentInfo),
|
| + ContentInfoTemplate },
|
| + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
|
| + SEC_ASN1_XTRN | 0,
|
| + offsetof(DegenerateSignedData,certificates),
|
| + SEC_ASN1_SUB(SEC_SetOfAnyTemplate) },
|
| + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
|
| + SEC_ASN1_XTRN | 1,
|
| + offsetof(DegenerateSignedData,crls),
|
| + SEC_ASN1_SUB(SEC_SetOfAnyTemplate) },
|
| + { SEC_ASN1_SET_OF | SEC_ASN1_XTRN,
|
| + offsetof(DegenerateSignedData,signerInfos),
|
| + SEC_ASN1_SUB(SEC_AnyTemplate) },
|
| + { 0 }
|
| +};
|
| +
|
| +static const SEC_ASN1Template PointerToDegenerateSignedDataTemplate[] = {
|
| + { SEC_ASN1_POINTER, 0, DegenerateSignedDataTemplate }
|
| +};
|
| +
|
| +static SECOidTag
|
| +GetContentTypeTag(ContentInfo *cinfo)
|
| +{
|
| + if (cinfo->contentTypeTag == SEC_OID_UNKNOWN)
|
| + cinfo->contentTypeTag = SECOID_FindOIDTag(&cinfo->contentType);
|
| + return cinfo->contentTypeTag;
|
| +}
|
| +
|
| +static const SEC_ASN1Template *
|
| +choose_content_template(void *src_or_dest, PRBool encoding)
|
| +{
|
| + const SEC_ASN1Template *theTemplate;
|
| + ContentInfo *cinfo;
|
| + SECOidTag kind;
|
| +
|
| + PORT_Assert(src_or_dest != NULL);
|
| + if (src_or_dest == NULL)
|
| + return NULL;
|
| +
|
| + cinfo = (ContentInfo*)src_or_dest;
|
| + kind = GetContentTypeTag(cinfo);
|
| + switch (kind) {
|
| + default:
|
| + theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate);
|
| + break;
|
| + case SEC_OID_PKCS7_DATA:
|
| + theTemplate = SEC_ASN1_GET(SEC_PointerToOctetStringTemplate);
|
| + break;
|
| + case SEC_OID_PKCS7_SIGNED_DATA:
|
| + theTemplate = PointerToDegenerateSignedDataTemplate;
|
| + break;
|
| + }
|
| + return theTemplate;
|
| +}
|
| +
|
| +static SECStatus
|
| SEC_ReadPKCS7Certs(SECItem *pkcs7Item, CERTImportCertificateFunc f, void *arg)
|
| {
|
| - SEC_PKCS7ContentInfo *contentInfo = NULL;
|
| + ContentInfo contentInfo;
|
| SECStatus rv;
|
| SECItem **certs;
|
| int count;
|
| + PRArenaPool *arena;
|
|
|
| - contentInfo = SEC_PKCS7DecodeItem(pkcs7Item, NULL, NULL, NULL, NULL, NULL,
|
| - NULL, NULL);
|
| - if ( contentInfo == NULL ) {
|
| + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
| + if ( arena == NULL ) {
|
| + return SECFailure;
|
| + }
|
| +
|
| + PORT_Memset(&contentInfo, 0, sizeof(contentInfo));
|
| + rv = SEC_ASN1DecodeItem(arena, &contentInfo, ContentInfoTemplate,
|
| + pkcs7Item);
|
| + if ( rv != SECSuccess ) {
|
| goto loser;
|
| }
|
|
|
| - if ( SEC_PKCS7ContentType (contentInfo) != SEC_OID_PKCS7_SIGNED_DATA ) {
|
| + if ( GetContentTypeTag(&contentInfo) != SEC_OID_PKCS7_SIGNED_DATA ) {
|
| goto loser;
|
| }
|
|
|
| - certs = contentInfo->content.signedData->rawCerts;
|
| + certs = contentInfo.content.signedData->certificates;
|
| if ( certs ) {
|
| count = 0;
|
|
|
| @@ -39,7 +149,7 @@
|
| count++;
|
| certs++;
|
| }
|
| - rv = (* f)(arg, contentInfo->content.signedData->rawCerts, count);
|
| + rv = (* f)(arg, contentInfo.content.signedData->certificates, count);
|
| }
|
|
|
| rv = SECSuccess;
|
| @@ -49,8 +159,8 @@
|
| rv = SECFailure;
|
|
|
| done:
|
| - if ( contentInfo ) {
|
| - SEC_PKCS7DestroyContentInfo(contentInfo);
|
| + if ( arena ) {
|
| + PORT_FreeArena(arena, PR_FALSE);
|
| }
|
|
|
| return(rv);
|
| @@ -60,7 +170,7 @@
|
| { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN, 0, SEC_ASN1_SUB(SEC_AnyTemplate) }
|
| };
|
|
|
| -SECStatus
|
| +static SECStatus
|
| SEC_ReadCertSequence(SECItem *certsItem, CERTImportCertificateFunc f, void *arg)
|
| {
|
| SECStatus rv;
|
| @@ -68,26 +178,26 @@
|
| int count;
|
| SECItem **rawCerts = NULL;
|
| PRArenaPool *arena;
|
| - SEC_PKCS7ContentInfo *contentInfo = NULL;
|
| + ContentInfo contentInfo;
|
|
|
| arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
| - if (arena == NULL) {
|
| + if ( arena == NULL ) {
|
| return SECFailure;
|
| }
|
|
|
| - contentInfo = SEC_PKCS7DecodeItem(certsItem, NULL, NULL, NULL, NULL, NULL,
|
| - NULL, NULL);
|
| - if ( contentInfo == NULL ) {
|
| + PORT_Memset(&contentInfo, 0, sizeof(contentInfo));
|
| + rv = SEC_ASN1DecodeItem(arena, &contentInfo, ContentInfoTemplate,
|
| + certsItem);
|
| + if ( rv != SECSuccess ) {
|
| goto loser;
|
| }
|
|
|
| - if ( SEC_PKCS7ContentType (contentInfo) != SEC_OID_NS_TYPE_CERT_SEQUENCE ) {
|
| + if ( GetContentTypeTag(&contentInfo) != SEC_OID_NS_TYPE_CERT_SEQUENCE ) {
|
| goto loser;
|
| }
|
|
|
| -
|
| rv = SEC_QuickDERDecodeItem(arena, &rawCerts, SEC_CertSequenceTemplate,
|
| - contentInfo->content.data);
|
| + contentInfo.content.data);
|
|
|
| if (rv != SECSuccess) {
|
| goto loser;
|
| @@ -111,10 +221,6 @@
|
| rv = SECFailure;
|
|
|
| done:
|
| - if ( contentInfo ) {
|
| - SEC_PKCS7DestroyContentInfo(contentInfo);
|
| - }
|
| -
|
| if ( arena ) {
|
| PORT_FreeArena(arena, PR_FALSE);
|
| }
|
| @@ -168,6 +274,7 @@
|
| * reference in the code below:
|
| * 0x30 0x84 l1 l2 l3 l4 +
|
| * tag 9 o1 o2 o3 o4 o5 o6 o7 o8 o9
|
| + * where 9 is the longest length of the expected oids we are testing.
|
| * 6 + 11 = 17. 17 bytes is clearly too small to code any kind of
|
| * certificate (a 128 bit ECC certificate contains at least an 8 byte
|
| * key and a 16 byte signature, plus coding overhead). Typically a cert
|
| @@ -258,9 +365,11 @@
|
|
|
| switch ( oiddata->offset ) {
|
| case SEC_OID_PKCS7_SIGNED_DATA:
|
| + /* oid: 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02 */
|
| return(SEC_ReadPKCS7Certs(&certitem, f, arg));
|
| break;
|
| case SEC_OID_NS_TYPE_CERT_SEQUENCE:
|
| + /* oid: 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x02, 0x05 */
|
| return(SEC_ReadCertSequence(&certitem, f, arg));
|
| break;
|
| default:
|
|
|