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