/* 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
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
** 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=\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=\n");
/*sv_PrintPKCS7Enveloped(out, src->content.envelopedData);*/
break;
case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA:
/* Signed and Enveloped */
fprintf(out,
"pkcs7SignedEnvelopedData=\n");
/*rv = sv_PrintPKCS7SignedAndEnveloped(out,
src->content.signedAndEnvelopedData);*/
break;
case SEC_OID_PKCS7_DIGESTED_DATA:
/* Digested Data */
fprintf(out,
"pkcs7DigestedData=\n");
/*sv_PrintPKCS7Digested(out, src->content.digestedData);*/
break;
case SEC_OID_PKCS7_ENCRYPTED_DATA:
/* Encrypted Data */
fprintf(out,
"pkcs7EncryptedData=\n");
/*sv_PrintPKCS7Encrypted(out, src->content.encryptedData);*/
break;
default:
fprintf(out,
"pkcs7UnknownData=\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
*/