michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* michael@0: ** secutil.c - various functions used by security stuff michael@0: ** michael@0: */ michael@0: michael@0: /* pkcs #7 -related functions */ michael@0: michael@0: michael@0: #include "secutil.h" michael@0: #include "secpkcs7.h" michael@0: #include "secoid.h" michael@0: #include michael@0: #include michael@0: michael@0: #ifdef XP_UNIX michael@0: #include michael@0: #endif michael@0: michael@0: /* for SEC_TraverseNames */ michael@0: #include "cert.h" michael@0: #include "prtypes.h" michael@0: #include "prtime.h" michael@0: michael@0: #include "prlong.h" michael@0: #include "secmod.h" michael@0: #include "pk11func.h" michael@0: #include "prerror.h" michael@0: michael@0: michael@0: michael@0: michael@0: /* michael@0: ** PKCS7 Support michael@0: */ michael@0: michael@0: /* forward declaration */ michael@0: int michael@0: sv_PrintPKCS7ContentInfo(FILE *, SEC_PKCS7ContentInfo *, char *); michael@0: michael@0: michael@0: void michael@0: sv_PrintAsHex(FILE *out, SECItem *data, char *m) michael@0: { michael@0: unsigned i; michael@0: michael@0: if (m) fprintf(out, "%s", m); michael@0: michael@0: for (i = 0; i < data->len; i++) { michael@0: if (i < data->len - 1) { michael@0: fprintf(out, "%02x:", data->data[i]); michael@0: } else { michael@0: fprintf(out, "%02x\n", data->data[i]); michael@0: break; michael@0: } michael@0: } michael@0: } michael@0: michael@0: void michael@0: sv_PrintInteger(FILE *out, SECItem *i, char *m) michael@0: { michael@0: int iv; michael@0: michael@0: if (i->len > 4) { michael@0: sv_PrintAsHex(out, i, m); michael@0: } else { michael@0: iv = DER_GetInteger(i); michael@0: fprintf(out, "%s%d (0x%x)\n", m, iv, iv); michael@0: } michael@0: } michael@0: michael@0: michael@0: int michael@0: sv_PrintTime(FILE *out, SECItem *t, char *m) michael@0: { michael@0: PRExplodedTime printableTime; michael@0: PRTime time; michael@0: char *timeString; michael@0: int rv; michael@0: michael@0: rv = DER_DecodeTimeChoice(&time, t); michael@0: if (rv) return rv; michael@0: michael@0: /* Convert to local time */ michael@0: PR_ExplodeTime(time, PR_LocalTimeParameters, &printableTime); michael@0: michael@0: timeString = (char *)PORT_Alloc(256); michael@0: michael@0: if ( timeString ) { michael@0: if (PR_FormatTime( timeString, 256, "%a %b %d %H:%M:%S %Y", &printableTime )) { michael@0: fprintf(out, "%s%s\n", m, timeString); michael@0: } michael@0: PORT_Free(timeString); michael@0: return 0; michael@0: } michael@0: return SECFailure; michael@0: } michael@0: michael@0: int michael@0: sv_PrintValidity(FILE *out, CERTValidity *v, char *m) michael@0: { michael@0: int rv; michael@0: michael@0: fprintf(out, "%s", m); michael@0: rv = sv_PrintTime(out, &v->notBefore, "notBefore="); michael@0: if (rv) return rv; michael@0: fprintf(out, "%s", m); michael@0: sv_PrintTime(out, &v->notAfter, "notAfter="); michael@0: return rv; michael@0: } michael@0: michael@0: void michael@0: sv_PrintObjectID(FILE *out, SECItem *oid, char *m) michael@0: { michael@0: const char *name; michael@0: SECOidData *oiddata; michael@0: michael@0: oiddata = SECOID_FindOID(oid); michael@0: if (oiddata == NULL) { michael@0: sv_PrintAsHex(out, oid, m); michael@0: return; michael@0: } michael@0: name = oiddata->desc; michael@0: michael@0: if (m != NULL) michael@0: fprintf(out, "%s", m); michael@0: fprintf(out, "%s\n", name); michael@0: } michael@0: michael@0: void michael@0: sv_PrintAlgorithmID(FILE *out, SECAlgorithmID *a, char *m) michael@0: { michael@0: sv_PrintObjectID(out, &a->algorithm, m); michael@0: michael@0: if ((a->parameters.len != 2) || michael@0: (PORT_Memcmp(a->parameters.data, "\005\000", 2) != 0)) { michael@0: /* Print args to algorithm */ michael@0: sv_PrintAsHex(out, &a->parameters, "Args="); michael@0: } michael@0: } michael@0: michael@0: void michael@0: sv_PrintAttribute(FILE *out, SEC_PKCS7Attribute *attr, char *m) michael@0: { michael@0: SECItem *value; michael@0: int i; michael@0: char om[100]; michael@0: michael@0: fprintf(out, "%s", m); michael@0: michael@0: /* michael@0: * XXX Make this smarter; look at the type field and then decode michael@0: * and print the value(s) appropriately! michael@0: */ michael@0: sv_PrintObjectID(out, &(attr->type), "type="); michael@0: if (attr->values != NULL) { michael@0: i = 0; michael@0: while ((value = attr->values[i]) != NULL) { michael@0: sprintf(om, "%svalue[%d]=%s", m, i++, attr->encoded ? "(encoded)" : ""); michael@0: if (attr->encoded || attr->typeTag == NULL) { michael@0: sv_PrintAsHex(out, value, om); michael@0: } else { michael@0: switch (attr->typeTag->offset) { michael@0: default: michael@0: sv_PrintAsHex(out, value, om); michael@0: break; michael@0: case SEC_OID_PKCS9_CONTENT_TYPE: michael@0: sv_PrintObjectID(out, value, om); michael@0: break; michael@0: case SEC_OID_PKCS9_SIGNING_TIME: michael@0: sv_PrintTime(out, value, om); michael@0: break; michael@0: } michael@0: } michael@0: } michael@0: } michael@0: } michael@0: michael@0: void michael@0: sv_PrintName(FILE *out, CERTName *name, char *msg) michael@0: { michael@0: char *str; michael@0: michael@0: str = CERT_NameToAscii(name); michael@0: fprintf(out, "%s%s\n", msg, str); michael@0: PORT_Free(str); michael@0: } michael@0: michael@0: michael@0: #if 0 michael@0: /* michael@0: ** secu_PrintPKCS7EncContent michael@0: ** Prints a SEC_PKCS7EncryptedContentInfo (without decrypting it) michael@0: */ michael@0: void michael@0: secu_PrintPKCS7EncContent(FILE *out, SEC_PKCS7EncryptedContentInfo *src, michael@0: char *m, int level) michael@0: { michael@0: if (src->contentTypeTag == NULL) michael@0: src->contentTypeTag = SECOID_FindOID(&(src->contentType)); michael@0: michael@0: secu_Indent(out, level); michael@0: fprintf(out, "%s:\n", m); michael@0: secu_Indent(out, level + 1); michael@0: fprintf(out, "Content Type: %s\n", michael@0: (src->contentTypeTag != NULL) ? src->contentTypeTag->desc michael@0: : "Unknown"); michael@0: sv_PrintAlgorithmID(out, &(src->contentEncAlg), michael@0: "Content Encryption Algorithm"); michael@0: sv_PrintAsHex(out, &(src->encContent), michael@0: "Encrypted Content", level+1); michael@0: } michael@0: michael@0: /* michael@0: ** secu_PrintRecipientInfo michael@0: ** Prints a PKCS7RecipientInfo type michael@0: */ michael@0: void michael@0: secu_PrintRecipientInfo(FILE *out, SEC_PKCS7RecipientInfo *info, char *m, michael@0: int level) michael@0: { michael@0: secu_Indent(out, level); fprintf(out, "%s:\n", m); michael@0: sv_PrintInteger(out, &(info->version), "Version"); michael@0: michael@0: sv_PrintName(out, &(info->issuerAndSN->issuer), "Issuer"); michael@0: sv_PrintInteger(out, &(info->issuerAndSN->serialNumber), michael@0: "Serial Number"); michael@0: michael@0: /* Parse and display encrypted key */ michael@0: sv_PrintAlgorithmID(out, &(info->keyEncAlg), michael@0: "Key Encryption Algorithm"); michael@0: sv_PrintAsHex(out, &(info->encKey), "Encrypted Key", level + 1); michael@0: } michael@0: #endif michael@0: michael@0: /* michael@0: ** secu_PrintSignerInfo michael@0: ** Prints a PKCS7SingerInfo type michael@0: */ michael@0: void michael@0: sv_PrintSignerInfo(FILE *out, SEC_PKCS7SignerInfo *info, char *m) michael@0: { michael@0: SEC_PKCS7Attribute *attr; michael@0: int iv; michael@0: michael@0: fprintf(out, "%s", m); michael@0: sv_PrintInteger(out, &(info->version), "version="); michael@0: michael@0: fprintf(out, "%s", m); michael@0: sv_PrintName(out, &(info->issuerAndSN->issuer), "issuerName="); michael@0: fprintf(out, "%s", m); michael@0: sv_PrintInteger(out, &(info->issuerAndSN->serialNumber), michael@0: "serialNumber="); michael@0: michael@0: fprintf(out, "%s", m); michael@0: sv_PrintAlgorithmID(out, &(info->digestAlg), "digestAlgorithm="); michael@0: michael@0: if (info->authAttr != NULL) { michael@0: char mm[120]; michael@0: michael@0: iv = 0; michael@0: while (info->authAttr[iv] != NULL) iv++; michael@0: fprintf(out, "%sauthenticatedAttributes=%d\n", m, iv); michael@0: iv = 0; michael@0: while ((attr = info->authAttr[iv]) != NULL) { michael@0: sprintf(mm, "%sattribute[%d].", m, iv++); michael@0: sv_PrintAttribute(out, attr, mm); michael@0: } michael@0: } michael@0: michael@0: /* Parse and display signature */ michael@0: fprintf(out, "%s", m); michael@0: sv_PrintAlgorithmID(out, &(info->digestEncAlg), "digestEncryptionAlgorithm="); michael@0: fprintf(out, "%s", m); michael@0: sv_PrintAsHex(out, &(info->encDigest), "encryptedDigest="); michael@0: michael@0: if (info->unAuthAttr != NULL) { michael@0: char mm[120]; michael@0: michael@0: iv = 0; michael@0: while (info->unAuthAttr[iv] != NULL) iv++; michael@0: fprintf(out, "%sunauthenticatedAttributes=%d\n", m, iv); michael@0: iv = 0; michael@0: while ((attr = info->unAuthAttr[iv]) != NULL) { michael@0: sprintf(mm, "%sattribute[%d].", m, iv++); michael@0: sv_PrintAttribute(out, attr, mm); michael@0: } michael@0: } michael@0: } michael@0: michael@0: void michael@0: sv_PrintRSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m) michael@0: { michael@0: fprintf(out, "%s", m); michael@0: sv_PrintInteger(out, &pk->u.rsa.modulus, "modulus="); michael@0: fprintf(out, "%s", m); michael@0: sv_PrintInteger(out, &pk->u.rsa.publicExponent, "exponent="); michael@0: } michael@0: michael@0: void michael@0: sv_PrintDSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m) michael@0: { michael@0: fprintf(out, "%s", m); michael@0: sv_PrintInteger(out, &pk->u.dsa.params.prime, "prime="); michael@0: fprintf(out, "%s", m); michael@0: sv_PrintInteger(out, &pk->u.dsa.params.subPrime, "subprime="); michael@0: fprintf(out, "%s", m); michael@0: sv_PrintInteger(out, &pk->u.dsa.params.base, "base="); michael@0: fprintf(out, "%s", m); michael@0: sv_PrintInteger(out, &pk->u.dsa.publicValue, "publicValue="); michael@0: } michael@0: michael@0: int michael@0: sv_PrintSubjectPublicKeyInfo(FILE *out, PLArenaPool *arena, michael@0: CERTSubjectPublicKeyInfo *i, char *msg) michael@0: { michael@0: SECKEYPublicKey *pk; michael@0: int rv; michael@0: char mm[200]; michael@0: michael@0: sprintf(mm, "%s.publicKeyAlgorithm=", msg); michael@0: sv_PrintAlgorithmID(out, &i->algorithm, mm); michael@0: michael@0: pk = (SECKEYPublicKey*) PORT_ZAlloc(sizeof(SECKEYPublicKey)); michael@0: if (!pk) return PORT_GetError(); michael@0: michael@0: DER_ConvertBitString(&i->subjectPublicKey); michael@0: switch(SECOID_FindOIDTag(&i->algorithm.algorithm)) { michael@0: case SEC_OID_PKCS1_RSA_ENCRYPTION: michael@0: rv = SEC_ASN1DecodeItem(arena, pk, michael@0: SEC_ASN1_GET(SECKEY_RSAPublicKeyTemplate), michael@0: &i->subjectPublicKey); michael@0: if (rv) return rv; michael@0: sprintf(mm, "%s.rsaPublicKey.", msg); michael@0: sv_PrintRSAPublicKey(out, pk, mm); michael@0: break; michael@0: case SEC_OID_ANSIX9_DSA_SIGNATURE: michael@0: rv = SEC_ASN1DecodeItem(arena, pk, michael@0: SEC_ASN1_GET(SECKEY_DSAPublicKeyTemplate), michael@0: &i->subjectPublicKey); michael@0: if (rv) return rv; michael@0: sprintf(mm, "%s.dsaPublicKey.", msg); michael@0: sv_PrintDSAPublicKey(out, pk, mm); michael@0: break; michael@0: default: michael@0: fprintf(out, "%s=bad SPKI algorithm type\n", msg); michael@0: return 0; michael@0: } michael@0: michael@0: return 0; michael@0: } michael@0: michael@0: SECStatus michael@0: sv_PrintInvalidDateExten (FILE *out, SECItem *value, char *msg) michael@0: { michael@0: SECItem decodedValue; michael@0: SECStatus rv; michael@0: PRTime invalidTime; michael@0: char *formattedTime = NULL; michael@0: michael@0: decodedValue.data = NULL; michael@0: rv = SEC_ASN1DecodeItem (NULL, &decodedValue, michael@0: SEC_ASN1_GET(SEC_GeneralizedTimeTemplate), michael@0: value); michael@0: if (rv == SECSuccess) { michael@0: rv = DER_GeneralizedTimeToTime(&invalidTime, &decodedValue); michael@0: if (rv == SECSuccess) { michael@0: formattedTime = CERT_GenTime2FormattedAscii(invalidTime, "%a %b %d %H:%M:%S %Y"); michael@0: fprintf (out, "%s: %s\n", msg, formattedTime); michael@0: PORT_Free (formattedTime); michael@0: } michael@0: } michael@0: PORT_Free (decodedValue.data); michael@0: michael@0: return (rv); michael@0: } michael@0: michael@0: int michael@0: sv_PrintExtensions(FILE *out, CERTCertExtension **extensions, char *msg) michael@0: { michael@0: SECOidTag oidTag; michael@0: michael@0: if (extensions) { michael@0: michael@0: while ( *extensions ) { michael@0: SECItem *tmpitem; michael@0: michael@0: fprintf(out, "%sname=", msg); michael@0: michael@0: tmpitem = &(*extensions)->id; michael@0: sv_PrintObjectID(out, tmpitem, NULL); michael@0: michael@0: tmpitem = &(*extensions)->critical; michael@0: if ( tmpitem->len ) michael@0: fprintf(out, "%scritical=%s\n", msg, michael@0: (tmpitem->data && tmpitem->data[0])? "True": "False"); michael@0: michael@0: oidTag = SECOID_FindOIDTag (&((*extensions)->id)); michael@0: michael@0: fprintf(out, "%s", msg); michael@0: tmpitem = &((*extensions)->value); michael@0: if (oidTag == SEC_OID_X509_INVALID_DATE) michael@0: sv_PrintInvalidDateExten (out, tmpitem,"invalidExt"); michael@0: else michael@0: sv_PrintAsHex(out,tmpitem, "data="); michael@0: michael@0: /*fprintf(out, "\n");*/ michael@0: extensions++; michael@0: } michael@0: } michael@0: michael@0: return 0; michael@0: } michael@0: michael@0: /* callers of this function must make sure that the CERTSignedCrl michael@0: from which they are extracting the CERTCrl has been fully-decoded. michael@0: Otherwise it will not have the entries even though the CRL may have michael@0: some */ michael@0: void michael@0: sv_PrintCRLInfo(FILE *out, CERTCrl *crl, char *m) michael@0: { michael@0: CERTCrlEntry *entry; michael@0: int iv; michael@0: char om[100]; michael@0: michael@0: fprintf(out, "%s", m); michael@0: sv_PrintAlgorithmID(out, &(crl->signatureAlg), "signatureAlgorithm="); michael@0: fprintf(out, "%s", m); michael@0: sv_PrintName(out, &(crl->name), "name="); michael@0: fprintf(out, "%s", m); michael@0: sv_PrintTime(out, &(crl->lastUpdate), "lastUpdate="); michael@0: fprintf(out, "%s", m); michael@0: sv_PrintTime(out, &(crl->nextUpdate), "nextUpdate="); michael@0: michael@0: if (crl->entries != NULL) { michael@0: iv = 0; michael@0: while ((entry = crl->entries[iv]) != NULL) { michael@0: fprintf(out, "%sentry[%d].", m, iv); michael@0: sv_PrintInteger(out, &(entry->serialNumber), "serialNumber="); michael@0: fprintf(out, "%sentry[%d].", m, iv); michael@0: sv_PrintTime(out, &(entry->revocationDate), "revocationDate="); michael@0: sprintf(om, "%sentry[%d].signedCRLEntriesExtensions.", m, iv++); michael@0: sv_PrintExtensions(out, entry->extensions, om); michael@0: } michael@0: } michael@0: sprintf(om, "%ssignedCRLEntriesExtensions.", m); michael@0: sv_PrintExtensions(out, crl->extensions, om); michael@0: } michael@0: michael@0: michael@0: int michael@0: sv_PrintCertificate(FILE *out, SECItem *der, char *m, int level) michael@0: { michael@0: PLArenaPool *arena = NULL; michael@0: CERTCertificate *c; michael@0: int rv; michael@0: int iv; michael@0: char mm[200]; michael@0: michael@0: /* Decode certificate */ michael@0: c = (CERTCertificate*) PORT_ZAlloc(sizeof(CERTCertificate)); michael@0: if (!c) return PORT_GetError(); michael@0: michael@0: arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); michael@0: if (!arena) return SEC_ERROR_NO_MEMORY; michael@0: michael@0: rv = SEC_ASN1DecodeItem(arena, c, SEC_ASN1_GET(CERT_CertificateTemplate), michael@0: der); michael@0: if (rv) { michael@0: PORT_FreeArena(arena, PR_FALSE); michael@0: return rv; michael@0: } michael@0: michael@0: /* Pretty print it out */ michael@0: iv = DER_GetInteger(&c->version); michael@0: fprintf(out, "%sversion=%d (0x%x)\n", m, iv + 1, iv); michael@0: sprintf(mm, "%sserialNumber=", m); michael@0: sv_PrintInteger(out, &c->serialNumber, mm); michael@0: sprintf(mm, "%ssignatureAlgorithm=", m); michael@0: sv_PrintAlgorithmID(out, &c->signature, mm); michael@0: sprintf(mm, "%sissuerName=", m); michael@0: sv_PrintName(out, &c->issuer, mm); michael@0: sprintf(mm, "%svalidity.", m); michael@0: sv_PrintValidity(out, &c->validity, mm); michael@0: sprintf(mm, "%ssubject=", m); michael@0: sv_PrintName(out, &c->subject, mm); michael@0: sprintf(mm, "%ssubjectPublicKeyInfo", m); michael@0: rv = sv_PrintSubjectPublicKeyInfo(out, arena, &c->subjectPublicKeyInfo, mm); michael@0: if (rv) { michael@0: PORT_FreeArena(arena, PR_FALSE); michael@0: return rv; michael@0: } michael@0: sprintf(mm, "%ssignedExtensions.", m); michael@0: sv_PrintExtensions(out, c->extensions, mm); michael@0: michael@0: PORT_FreeArena(arena, PR_FALSE); michael@0: return 0; michael@0: } michael@0: michael@0: int michael@0: sv_PrintSignedData(FILE *out, SECItem *der, char *m, SECU_PPFunc inner) michael@0: { michael@0: PLArenaPool *arena = NULL; michael@0: CERTSignedData *sd; michael@0: int rv; michael@0: michael@0: /* Strip off the signature */ michael@0: sd = (CERTSignedData*) PORT_ZAlloc(sizeof(CERTSignedData)); michael@0: if (!sd) return PORT_GetError(); michael@0: michael@0: arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); michael@0: if (!arena) return SEC_ERROR_NO_MEMORY; michael@0: michael@0: rv = SEC_ASN1DecodeItem(arena, sd, SEC_ASN1_GET(CERT_SignedDataTemplate), michael@0: der); michael@0: if (rv) { michael@0: PORT_FreeArena(arena, PR_FALSE); michael@0: return rv; michael@0: } michael@0: michael@0: /* fprintf(out, "%s:\n", m); */ michael@0: PORT_Strcat(m, "data."); michael@0: michael@0: rv = (*inner)(out, &sd->data, m, 0); michael@0: if (rv) { michael@0: PORT_FreeArena(arena, PR_FALSE); michael@0: return rv; michael@0: } michael@0: michael@0: m[PORT_Strlen(m) - 5] = 0; michael@0: fprintf(out, "%s", m); michael@0: sv_PrintAlgorithmID(out, &sd->signatureAlgorithm, "signatureAlgorithm="); michael@0: DER_ConvertBitString(&sd->signature); michael@0: fprintf(out, "%s", m); michael@0: sv_PrintAsHex(out, &sd->signature, "signature="); michael@0: michael@0: PORT_FreeArena(arena, PR_FALSE); michael@0: return 0; michael@0: michael@0: } michael@0: michael@0: michael@0: /* michael@0: ** secu_PrintPKCS7Signed michael@0: ** Pretty print a PKCS7 signed data type (up to version 1). michael@0: */ michael@0: int michael@0: sv_PrintPKCS7Signed(FILE *out, SEC_PKCS7SignedData *src) michael@0: { michael@0: SECAlgorithmID *digAlg; /* digest algorithms */ michael@0: SECItem *aCert; /* certificate */ michael@0: CERTSignedCrl *aCrl; /* certificate revocation list */ michael@0: SEC_PKCS7SignerInfo *sigInfo; /* signer information */ michael@0: int rv, iv; michael@0: char om[120]; michael@0: michael@0: sv_PrintInteger(out, &(src->version), "pkcs7.version="); michael@0: michael@0: /* Parse and list digest algorithms (if any) */ michael@0: if (src->digestAlgorithms != NULL) { michael@0: iv = 0; michael@0: while (src->digestAlgorithms[iv] != NULL) michael@0: iv++; michael@0: fprintf(out, "pkcs7.digestAlgorithmListLength=%d\n", iv); michael@0: iv = 0; michael@0: while ((digAlg = src->digestAlgorithms[iv]) != NULL) { michael@0: sprintf(om, "pkcs7.digestAlgorithm[%d]=", iv++); michael@0: sv_PrintAlgorithmID(out, digAlg, om); michael@0: } michael@0: } michael@0: michael@0: /* Now for the content */ michael@0: rv = sv_PrintPKCS7ContentInfo(out, &(src->contentInfo), michael@0: "pkcs7.contentInformation="); michael@0: if (rv != 0) return rv; michael@0: michael@0: /* Parse and list certificates (if any) */ michael@0: if (src->rawCerts != NULL) { michael@0: iv = 0; michael@0: while (src->rawCerts[iv] != NULL) michael@0: iv++; michael@0: fprintf(out, "pkcs7.certificateListLength=%d\n", iv); michael@0: michael@0: iv = 0; michael@0: while ((aCert = src->rawCerts[iv]) != NULL) { michael@0: sprintf(om, "certificate[%d].", iv++); michael@0: rv = sv_PrintSignedData(out, aCert, om, sv_PrintCertificate); michael@0: if (rv) return rv; michael@0: } michael@0: } michael@0: michael@0: /* Parse and list CRL's (if any) */ michael@0: if (src->crls != NULL) { michael@0: iv = 0; michael@0: while (src->crls[iv] != NULL) iv++; michael@0: fprintf(out, "pkcs7.signedRevocationLists=%d\n", iv); michael@0: iv = 0; michael@0: while ((aCrl = src->crls[iv]) != NULL) { michael@0: sprintf(om, "signedRevocationList[%d].", iv); michael@0: fprintf(out, "%s", om); michael@0: sv_PrintAlgorithmID(out, &aCrl->signatureWrap.signatureAlgorithm, michael@0: "signatureAlgorithm="); michael@0: DER_ConvertBitString(&aCrl->signatureWrap.signature); michael@0: fprintf(out, "%s", om); michael@0: sv_PrintAsHex(out, &aCrl->signatureWrap.signature, "signature="); michael@0: sprintf(om, "certificateRevocationList[%d].", iv); michael@0: sv_PrintCRLInfo(out, &aCrl->crl, om); michael@0: iv++; michael@0: } michael@0: } michael@0: michael@0: /* Parse and list signatures (if any) */ michael@0: if (src->signerInfos != NULL) { michael@0: iv = 0; michael@0: while (src->signerInfos[iv] != NULL) michael@0: iv++; michael@0: fprintf(out, "pkcs7.signerInformationListLength=%d\n", iv); michael@0: iv = 0; michael@0: while ((sigInfo = src->signerInfos[iv]) != NULL) { michael@0: sprintf(om, "signerInformation[%d].", iv++); michael@0: sv_PrintSignerInfo(out, sigInfo, om); michael@0: } michael@0: } michael@0: michael@0: return 0; michael@0: } michael@0: michael@0: #if 0 michael@0: /* michael@0: ** secu_PrintPKCS7Enveloped michael@0: ** Pretty print a PKCS7 enveloped data type (up to version 1). michael@0: */ michael@0: void michael@0: secu_PrintPKCS7Enveloped(FILE *out, SEC_PKCS7EnvelopedData *src, michael@0: char *m, int level) michael@0: { michael@0: SEC_PKCS7RecipientInfo *recInfo; /* pointer for signer information */ michael@0: int iv; michael@0: char om[100]; michael@0: michael@0: secu_Indent(out, level); fprintf(out, "%s:\n", m); michael@0: sv_PrintInteger(out, &(src->version), "Version", level + 1); michael@0: michael@0: /* Parse and list recipients (this is not optional) */ michael@0: if (src->recipientInfos != NULL) { michael@0: secu_Indent(out, level + 1); michael@0: fprintf(out, "Recipient Information List:\n"); michael@0: iv = 0; michael@0: while ((recInfo = src->recipientInfos[iv++]) != NULL) { michael@0: sprintf(om, "Recipient Information (%x)", iv); michael@0: secu_PrintRecipientInfo(out, recInfo, om, level + 2); michael@0: } michael@0: } michael@0: michael@0: secu_PrintPKCS7EncContent(out, &src->encContentInfo, michael@0: "Encrypted Content Information", level + 1); michael@0: } michael@0: michael@0: /* michael@0: ** secu_PrintPKCS7SignedEnveloped michael@0: ** Pretty print a PKCS7 singed and enveloped data type (up to version 1). michael@0: */ michael@0: int michael@0: secu_PrintPKCS7SignedAndEnveloped(FILE *out, michael@0: SEC_PKCS7SignedAndEnvelopedData *src, michael@0: char *m, int level) michael@0: { michael@0: SECAlgorithmID *digAlg; /* pointer for digest algorithms */ michael@0: SECItem *aCert; /* pointer for certificate */ michael@0: CERTSignedCrl *aCrl; /* pointer for certificate revocation list */ michael@0: SEC_PKCS7SignerInfo *sigInfo; /* pointer for signer information */ michael@0: SEC_PKCS7RecipientInfo *recInfo; /* pointer for recipient information */ michael@0: int rv, iv; michael@0: char om[100]; michael@0: michael@0: secu_Indent(out, level); fprintf(out, "%s:\n", m); michael@0: sv_PrintInteger(out, &(src->version), "Version", level + 1); michael@0: michael@0: /* Parse and list recipients (this is not optional) */ michael@0: if (src->recipientInfos != NULL) { michael@0: secu_Indent(out, level + 1); michael@0: fprintf(out, "Recipient Information List:\n"); michael@0: iv = 0; michael@0: while ((recInfo = src->recipientInfos[iv++]) != NULL) { michael@0: sprintf(om, "Recipient Information (%x)", iv); michael@0: secu_PrintRecipientInfo(out, recInfo, om, level + 2); michael@0: } michael@0: } michael@0: michael@0: /* Parse and list digest algorithms (if any) */ michael@0: if (src->digestAlgorithms != NULL) { michael@0: secu_Indent(out, level + 1); fprintf(out, "Digest Algorithm List:\n"); michael@0: iv = 0; michael@0: while ((digAlg = src->digestAlgorithms[iv++]) != NULL) { michael@0: sprintf(om, "Digest Algorithm (%x)", iv); michael@0: sv_PrintAlgorithmID(out, digAlg, om); michael@0: } michael@0: } michael@0: michael@0: secu_PrintPKCS7EncContent(out, &src->encContentInfo, michael@0: "Encrypted Content Information", level + 1); michael@0: michael@0: /* Parse and list certificates (if any) */ michael@0: if (src->rawCerts != NULL) { michael@0: secu_Indent(out, level + 1); fprintf(out, "Certificate List:\n"); michael@0: iv = 0; michael@0: while ((aCert = src->rawCerts[iv++]) != NULL) { michael@0: sprintf(om, "Certificate (%x)", iv); michael@0: rv = SECU_PrintSignedData(out, aCert, om, level + 2, michael@0: SECU_PrintCertificate); michael@0: if (rv) michael@0: return rv; michael@0: } michael@0: } michael@0: michael@0: /* Parse and list CRL's (if any) */ michael@0: if (src->crls != NULL) { michael@0: secu_Indent(out, level + 1); michael@0: fprintf(out, "Signed Revocation Lists:\n"); michael@0: iv = 0; michael@0: while ((aCrl = src->crls[iv++]) != NULL) { michael@0: sprintf(om, "Signed Revocation List (%x)", iv); michael@0: secu_Indent(out, level + 2); fprintf(out, "%s:\n", om); michael@0: sv_PrintAlgorithmID(out, &aCrl->signatureWrap.signatureAlgorithm, michael@0: "Signature Algorithm"); michael@0: DER_ConvertBitString(&aCrl->signatureWrap.signature); michael@0: sv_PrintAsHex(out, &aCrl->signatureWrap.signature, "Signature", michael@0: level+3); michael@0: SECU_PrintCRLInfo(out, &aCrl->crl, "Certificate Revocation List", michael@0: level + 3); michael@0: } michael@0: } michael@0: michael@0: /* Parse and list signatures (if any) */ michael@0: if (src->signerInfos != NULL) { michael@0: secu_Indent(out, level + 1); michael@0: fprintf(out, "Signer Information List:\n"); michael@0: iv = 0; michael@0: while ((sigInfo = src->signerInfos[iv++]) != NULL) { michael@0: sprintf(om, "Signer Information (%x)", iv); michael@0: secu_PrintSignerInfo(out, sigInfo, om, level + 2); michael@0: } michael@0: } michael@0: michael@0: return 0; michael@0: } michael@0: michael@0: /* michael@0: ** secu_PrintPKCS7Encrypted michael@0: ** Pretty print a PKCS7 encrypted data type (up to version 1). michael@0: */ michael@0: void michael@0: secu_PrintPKCS7Encrypted(FILE *out, SEC_PKCS7EncryptedData *src, michael@0: char *m, int level) michael@0: { michael@0: secu_Indent(out, level); fprintf(out, "%s:\n", m); michael@0: sv_PrintInteger(out, &(src->version), "Version", level + 1); michael@0: michael@0: secu_PrintPKCS7EncContent(out, &src->encContentInfo, michael@0: "Encrypted Content Information", level + 1); michael@0: } michael@0: michael@0: /* michael@0: ** secu_PrintPKCS7Digested michael@0: ** Pretty print a PKCS7 digested data type (up to version 1). michael@0: */ michael@0: void michael@0: sv_PrintPKCS7Digested(FILE *out, SEC_PKCS7DigestedData *src) michael@0: { michael@0: secu_Indent(out, level); fprintf(out, "%s:\n", m); michael@0: sv_PrintInteger(out, &(src->version), "Version", level + 1); michael@0: michael@0: sv_PrintAlgorithmID(out, &src->digestAlg, "Digest Algorithm"); michael@0: sv_PrintPKCS7ContentInfo(out, &src->contentInfo, "Content Information", michael@0: level + 1); michael@0: sv_PrintAsHex(out, &src->digest, "Digest", level + 1); michael@0: } michael@0: michael@0: #endif michael@0: michael@0: /* michael@0: ** secu_PrintPKCS7ContentInfo michael@0: ** Takes a SEC_PKCS7ContentInfo type and sends the contents to the michael@0: ** appropriate function michael@0: */ michael@0: int michael@0: sv_PrintPKCS7ContentInfo(FILE *out, SEC_PKCS7ContentInfo *src, char *m) michael@0: { michael@0: const char *desc; michael@0: SECOidTag kind; michael@0: int rv; michael@0: michael@0: if (src->contentTypeTag == NULL) michael@0: src->contentTypeTag = SECOID_FindOID(&(src->contentType)); michael@0: michael@0: if (src->contentTypeTag == NULL) { michael@0: desc = "Unknown"; michael@0: kind = SEC_OID_PKCS7_DATA; michael@0: } else { michael@0: desc = src->contentTypeTag->desc; michael@0: kind = src->contentTypeTag->offset; michael@0: } michael@0: michael@0: fprintf(out, "%s%s\n", m, desc); michael@0: michael@0: if (src->content.data == NULL) { michael@0: fprintf(out, "pkcs7.data=\n"); michael@0: return 0; michael@0: } michael@0: michael@0: rv = 0; michael@0: switch (kind) { michael@0: case SEC_OID_PKCS7_SIGNED_DATA: /* Signed Data */ michael@0: rv = sv_PrintPKCS7Signed(out, src->content.signedData); michael@0: break; michael@0: michael@0: case SEC_OID_PKCS7_ENVELOPED_DATA: /* Enveloped Data */ michael@0: fprintf(out, "pkcs7EnvelopedData=\n"); michael@0: /*sv_PrintPKCS7Enveloped(out, src->content.envelopedData);*/ michael@0: break; michael@0: michael@0: case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: /* Signed and Enveloped */ michael@0: fprintf(out, "pkcs7SignedEnvelopedData=\n"); michael@0: /*rv = sv_PrintPKCS7SignedAndEnveloped(out, michael@0: src->content.signedAndEnvelopedData);*/ michael@0: break; michael@0: michael@0: case SEC_OID_PKCS7_DIGESTED_DATA: /* Digested Data */ michael@0: fprintf(out, "pkcs7DigestedData=\n"); michael@0: /*sv_PrintPKCS7Digested(out, src->content.digestedData);*/ michael@0: break; michael@0: michael@0: case SEC_OID_PKCS7_ENCRYPTED_DATA: /* Encrypted Data */ michael@0: fprintf(out, "pkcs7EncryptedData=\n"); michael@0: /*sv_PrintPKCS7Encrypted(out, src->content.encryptedData);*/ michael@0: break; michael@0: michael@0: default: michael@0: fprintf(out, "pkcs7UnknownData=\n"); michael@0: /*sv_PrintAsHex(out, src->content.data);*/ michael@0: break; michael@0: } michael@0: michael@0: return rv; michael@0: } michael@0: michael@0: michael@0: int michael@0: SV_PrintPKCS7ContentInfo(FILE *out, SECItem *der) michael@0: { michael@0: SEC_PKCS7ContentInfo *cinfo; michael@0: int rv = -1; michael@0: michael@0: cinfo = SEC_PKCS7DecodeItem(der, NULL, NULL, NULL, NULL, NULL, NULL, NULL); michael@0: michael@0: if (cinfo != NULL) { michael@0: rv = sv_PrintPKCS7ContentInfo(out, cinfo, "pkcs7.contentInfo="); michael@0: SEC_PKCS7DestroyContentInfo(cinfo); michael@0: } michael@0: michael@0: return rv; michael@0: } michael@0: /* michael@0: ** End of PKCS7 functions michael@0: */