tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

pk7print.c (27026B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 /*
      6 ** secutil.c - various functions used by security stuff
      7 **
      8 */
      9 
     10 /* pkcs #7 -related functions */
     11 
     12 #include "secutil.h"
     13 #include "secpkcs7.h"
     14 #include "secoid.h"
     15 #include <sys/stat.h>
     16 #include <stdarg.h>
     17 
     18 #ifdef XP_UNIX
     19 #include <unistd.h>
     20 #endif
     21 
     22 /* for SEC_TraverseNames */
     23 #include "cert.h"
     24 #include "prtypes.h"
     25 #include "prtime.h"
     26 
     27 #include "prlong.h"
     28 #include "secmod.h"
     29 #include "pk11func.h"
     30 #include "prerror.h"
     31 
     32 /*
     33 ** PKCS7 Support
     34 */
     35 
     36 /* forward declaration */
     37 int
     38 sv_PrintPKCS7ContentInfo(FILE *, SEC_PKCS7ContentInfo *, char *);
     39 
     40 void
     41 sv_PrintAsHex(FILE *out, SECItem *data, char *m)
     42 {
     43    unsigned i;
     44 
     45    if (m)
     46        fprintf(out, "%s", m);
     47 
     48    for (i = 0; i < data->len; i++) {
     49        if (i < data->len - 1) {
     50            fprintf(out, "%02x:", data->data[i]);
     51        } else {
     52            fprintf(out, "%02x\n", data->data[i]);
     53            break;
     54        }
     55    }
     56 }
     57 
     58 void
     59 sv_PrintInteger(FILE *out, SECItem *i, char *m)
     60 {
     61    int iv;
     62 
     63    if (i->len > 4) {
     64        sv_PrintAsHex(out, i, m);
     65    } else {
     66        iv = DER_GetInteger(i);
     67        fprintf(out, "%s%d (0x%x)\n", m, iv, iv);
     68    }
     69 }
     70 
     71 int
     72 sv_PrintTime(FILE *out, SECItem *t, char *m)
     73 {
     74    PRExplodedTime printableTime;
     75    PRTime time;
     76    char *timeString;
     77    int rv;
     78 
     79    rv = DER_DecodeTimeChoice(&time, t);
     80    if (rv)
     81        return rv;
     82 
     83    /* Convert to local time */
     84    PR_ExplodeTime(time, PR_LocalTimeParameters, &printableTime);
     85 
     86    timeString = (char *)PORT_Alloc(256);
     87 
     88    if (timeString) {
     89        if (PR_FormatTime(timeString, 256, "%a %b %d %H:%M:%S %Y", &printableTime)) {
     90            fprintf(out, "%s%s\n", m, timeString);
     91        }
     92        PORT_Free(timeString);
     93        return 0;
     94    }
     95    return SECFailure;
     96 }
     97 
     98 int
     99 sv_PrintValidity(FILE *out, CERTValidity *v, char *m)
    100 {
    101    int rv;
    102 
    103    fprintf(out, "%s", m);
    104    rv = sv_PrintTime(out, &v->notBefore, "notBefore=");
    105    if (rv)
    106        return rv;
    107    fprintf(out, "%s", m);
    108    sv_PrintTime(out, &v->notAfter, "notAfter=");
    109    return rv;
    110 }
    111 
    112 void
    113 sv_PrintObjectID(FILE *out, SECItem *oid, char *m)
    114 {
    115    const char *name;
    116    SECOidData *oiddata;
    117 
    118    oiddata = SECOID_FindOID(oid);
    119    if (oiddata == NULL) {
    120        sv_PrintAsHex(out, oid, m);
    121        return;
    122    }
    123    name = oiddata->desc;
    124 
    125    if (m != NULL)
    126        fprintf(out, "%s", m);
    127    fprintf(out, "%s\n", name);
    128 }
    129 
    130 void
    131 sv_PrintAlgorithmID(FILE *out, SECAlgorithmID *a, char *m)
    132 {
    133    sv_PrintObjectID(out, &a->algorithm, m);
    134 
    135    if ((a->parameters.len != 2) ||
    136        (PORT_Memcmp(a->parameters.data, "\005\000", 2) != 0)) {
    137        /* Print args to algorithm */
    138        sv_PrintAsHex(out, &a->parameters, "Args=");
    139    }
    140 }
    141 
    142 void
    143 sv_PrintAttribute(FILE *out, SEC_PKCS7Attribute *attr, char *m)
    144 {
    145    SECItem *value;
    146    int i;
    147    char om[100];
    148 
    149    fprintf(out, "%s", m);
    150 
    151    /*
    152     * XXX Make this smarter; look at the type field and then decode
    153     * and print the value(s) appropriately!
    154     */
    155    sv_PrintObjectID(out, &(attr->type), "type=");
    156    if (attr->values != NULL) {
    157        i = 0;
    158        while ((value = attr->values[i]) != NULL) {
    159            snprintf(om, sizeof(om), "%svalue[%d]=%s", m, i++, attr->encoded ? "(encoded)" : "");
    160            if (attr->encoded || attr->typeTag == NULL) {
    161                sv_PrintAsHex(out, value, om);
    162            } else {
    163                switch (attr->typeTag->offset) {
    164                    default:
    165                        sv_PrintAsHex(out, value, om);
    166                        break;
    167                    case SEC_OID_PKCS9_CONTENT_TYPE:
    168                        sv_PrintObjectID(out, value, om);
    169                        break;
    170                    case SEC_OID_PKCS9_SIGNING_TIME:
    171                        sv_PrintTime(out, value, om);
    172                        break;
    173                }
    174            }
    175        }
    176    }
    177 }
    178 
    179 void
    180 sv_PrintName(FILE *out, CERTName *name, char *msg)
    181 {
    182    char *str;
    183 
    184    str = CERT_NameToAscii(name);
    185    fprintf(out, "%s%s\n", msg, str);
    186    PORT_Free(str);
    187 }
    188 
    189 #if 0
    190 /*
    191 ** secu_PrintPKCS7EncContent
    192 **   Prints a SEC_PKCS7EncryptedContentInfo (without decrypting it)
    193 */
    194 void
    195 secu_PrintPKCS7EncContent(FILE *out, SEC_PKCS7EncryptedContentInfo *src,
    196              char *m, int level)
    197 {
    198    if (src->contentTypeTag == NULL)
    199    src->contentTypeTag = SECOID_FindOID(&(src->contentType));
    200 
    201    secu_Indent(out, level);
    202    fprintf(out, "%s:\n", m);
    203    secu_Indent(out, level + 1);
    204    fprintf(out, "Content Type: %s\n",
    205        (src->contentTypeTag != NULL) ? src->contentTypeTag->desc
    206                      : "Unknown");
    207    sv_PrintAlgorithmID(out, &(src->contentEncAlg),
    208              "Content Encryption Algorithm");
    209    sv_PrintAsHex(out, &(src->encContent),
    210            "Encrypted Content", level+1);
    211 }
    212 
    213 /*
    214 ** secu_PrintRecipientInfo
    215 **   Prints a PKCS7RecipientInfo type
    216 */
    217 void
    218 secu_PrintRecipientInfo(FILE *out, SEC_PKCS7RecipientInfo *info, char *m,
    219            int level)
    220 {
    221    secu_Indent(out, level); fprintf(out, "%s:\n", m);
    222    sv_PrintInteger(out, &(info->version), "Version");
    223 
    224    sv_PrintName(out, &(info->issuerAndSN->issuer), "Issuer");
    225    sv_PrintInteger(out, &(info->issuerAndSN->serialNumber),
    226              "Serial Number");
    227 
    228    /* Parse and display encrypted key */
    229    sv_PrintAlgorithmID(out, &(info->keyEncAlg),
    230            "Key Encryption Algorithm");
    231    sv_PrintAsHex(out, &(info->encKey), "Encrypted Key", level + 1);
    232 }
    233 #endif
    234 
    235 /*
    236 ** secu_PrintSignerInfo
    237 **   Prints a PKCS7SingerInfo type
    238 */
    239 void
    240 sv_PrintSignerInfo(FILE *out, SEC_PKCS7SignerInfo *info, char *m)
    241 {
    242    SEC_PKCS7Attribute *attr;
    243    int iv;
    244 
    245    fprintf(out, "%s", m);
    246    sv_PrintInteger(out, &(info->version), "version=");
    247 
    248    fprintf(out, "%s", m);
    249    sv_PrintName(out, &(info->issuerAndSN->issuer), "issuerName=");
    250    fprintf(out, "%s", m);
    251    sv_PrintInteger(out, &(info->issuerAndSN->serialNumber),
    252                    "serialNumber=");
    253 
    254    fprintf(out, "%s", m);
    255    sv_PrintAlgorithmID(out, &(info->digestAlg), "digestAlgorithm=");
    256 
    257    if (info->authAttr != NULL) {
    258        char mm[120];
    259 
    260        iv = 0;
    261        while (info->authAttr[iv] != NULL)
    262            iv++;
    263        fprintf(out, "%sauthenticatedAttributes=%d\n", m, iv);
    264        iv = 0;
    265        while ((attr = info->authAttr[iv]) != NULL) {
    266            snprintf(mm, sizeof(mm), "%sattribute[%d].", m, iv++);
    267            sv_PrintAttribute(out, attr, mm);
    268        }
    269    }
    270 
    271    /* Parse and display signature */
    272    fprintf(out, "%s", m);
    273    sv_PrintAlgorithmID(out, &(info->digestEncAlg), "digestEncryptionAlgorithm=");
    274    fprintf(out, "%s", m);
    275    sv_PrintAsHex(out, &(info->encDigest), "encryptedDigest=");
    276 
    277    if (info->unAuthAttr != NULL) {
    278        char mm[120];
    279 
    280        iv = 0;
    281        while (info->unAuthAttr[iv] != NULL)
    282            iv++;
    283        fprintf(out, "%sunauthenticatedAttributes=%d\n", m, iv);
    284        iv = 0;
    285        while ((attr = info->unAuthAttr[iv]) != NULL) {
    286            snprintf(mm, sizeof(mm), "%sattribute[%d].", m, iv++);
    287            sv_PrintAttribute(out, attr, mm);
    288        }
    289    }
    290 }
    291 
    292 void
    293 sv_PrintRSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m)
    294 {
    295    fprintf(out, "%s", m);
    296    sv_PrintInteger(out, &pk->u.rsa.modulus, "modulus=");
    297    fprintf(out, "%s", m);
    298    sv_PrintInteger(out, &pk->u.rsa.publicExponent, "exponent=");
    299 }
    300 
    301 void
    302 sv_PrintDSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m)
    303 {
    304    fprintf(out, "%s", m);
    305    sv_PrintInteger(out, &pk->u.dsa.params.prime, "prime=");
    306    fprintf(out, "%s", m);
    307    sv_PrintInteger(out, &pk->u.dsa.params.subPrime, "subprime=");
    308    fprintf(out, "%s", m);
    309    sv_PrintInteger(out, &pk->u.dsa.params.base, "base=");
    310    fprintf(out, "%s", m);
    311    sv_PrintInteger(out, &pk->u.dsa.publicValue, "publicValue=");
    312 }
    313 
    314 void
    315 sv_PrintECDSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m)
    316 {
    317    SECItem curve = { siBuffer, NULL, 0 };
    318    if ((pk->u.ec.DEREncodedParams.len > 2) &&
    319        (pk->u.ec.DEREncodedParams.data[0] == 0x06)) {
    320        /* strip to just the oid for the curve */
    321        curve.len = pk->u.ec.DEREncodedParams.data[1];
    322        curve.data = pk->u.ec.DEREncodedParams.data + 2;
    323        /* don't overflow the buffer */
    324        curve.len = PR_MIN(curve.len, pk->u.ec.DEREncodedParams.len - 2);
    325        fprintf(out, "%s", m);
    326        sv_PrintObjectID(out, &curve, "curve=");
    327    }
    328    fprintf(out, "%s", m);
    329    sv_PrintInteger(out, &pk->u.ec.publicValue, "publicValue=");
    330 }
    331 
    332 int
    333 sv_PrintSubjectPublicKeyInfo(FILE *out, PLArenaPool *arena,
    334                             CERTSubjectPublicKeyInfo *i, char *msg)
    335 {
    336    SECKEYPublicKey pk;
    337    int rv;
    338    char mm[200];
    339 
    340    snprintf(mm, sizeof(mm), "%s.publicKeyAlgorithm=", msg);
    341    sv_PrintAlgorithmID(out, &i->algorithm, mm);
    342 
    343    DER_ConvertBitString(&i->subjectPublicKey);
    344    switch (SECOID_FindOIDTag(&i->algorithm.algorithm)) {
    345        case SEC_OID_PKCS1_RSA_ENCRYPTION:
    346        case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
    347            rv = SEC_ASN1DecodeItem(arena, &pk,
    348                                    SEC_ASN1_GET(SECKEY_RSAPublicKeyTemplate),
    349                                    &i->subjectPublicKey);
    350            if (rv)
    351                return rv;
    352            snprintf(mm, sizeof(mm), "%s.rsaPublicKey.", msg);
    353            sv_PrintRSAPublicKey(out, &pk, mm);
    354            break;
    355        case SEC_OID_ANSIX9_DSA_SIGNATURE:
    356            rv = SEC_ASN1DecodeItem(arena, &pk,
    357                                    SEC_ASN1_GET(SECKEY_DSAPublicKeyTemplate),
    358                                    &i->subjectPublicKey);
    359            if (rv)
    360                return rv;
    361 #ifdef notdef
    362            /* SECKEY_PQGParamsTemplate is not yet exported form NSS */
    363            rv = SEC_ASN1DecodeItem(arena, &pk.u.dsa.params,
    364                                    SEC_ASN1_GET(SECKEY_PQGParamsTemplate),
    365                                    &i->algorithm.parameters);
    366            if (rv)
    367                return rv;
    368 #endif
    369            snprintf(mm, sizeof(mm), "%s.dsaPublicKey.", msg);
    370            sv_PrintDSAPublicKey(out, &pk, mm);
    371            break;
    372        case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
    373            rv = SECITEM_CopyItem(arena, &pk.u.ec.DEREncodedParams,
    374                                  &i->algorithm.parameters);
    375            if (rv)
    376                return rv;
    377            rv = SECITEM_CopyItem(arena, &pk.u.ec.publicValue,
    378                                  &i->subjectPublicKey);
    379            if (rv)
    380                return rv;
    381            snprintf(mm, sizeof(mm), "%s.ecdsaPublicKey.", msg);
    382            sv_PrintECDSAPublicKey(out, &pk, mm);
    383            break;
    384        default:
    385            fprintf(out, "%s=bad SPKI algorithm type\n", msg);
    386            return 0;
    387    }
    388 
    389    return 0;
    390 }
    391 
    392 SECStatus
    393 sv_PrintInvalidDateExten(FILE *out, SECItem *value, char *msg)
    394 {
    395    SECItem decodedValue;
    396    SECStatus rv;
    397    PRTime invalidTime;
    398    char *formattedTime = NULL;
    399 
    400    decodedValue.data = NULL;
    401    rv = SEC_ASN1DecodeItem(NULL, &decodedValue,
    402                            SEC_ASN1_GET(SEC_GeneralizedTimeTemplate),
    403                            value);
    404    if (rv == SECSuccess) {
    405        rv = DER_GeneralizedTimeToTime(&invalidTime, &decodedValue);
    406        if (rv == SECSuccess) {
    407            formattedTime = CERT_GenTime2FormattedAscii(invalidTime, "%a %b %d %H:%M:%S %Y");
    408            fprintf(out, "%s: %s\n", msg, formattedTime);
    409            PORT_Free(formattedTime);
    410        }
    411    }
    412    PORT_Free(decodedValue.data);
    413 
    414    return (rv);
    415 }
    416 
    417 int
    418 sv_PrintExtensions(FILE *out, CERTCertExtension **extensions, char *msg)
    419 {
    420    SECOidTag oidTag;
    421 
    422    if (extensions) {
    423 
    424        while (*extensions) {
    425            SECItem *tmpitem;
    426 
    427            fprintf(out, "%sname=", msg);
    428 
    429            tmpitem = &(*extensions)->id;
    430            sv_PrintObjectID(out, tmpitem, NULL);
    431 
    432            tmpitem = &(*extensions)->critical;
    433            if (tmpitem->len)
    434                fprintf(out, "%scritical=%s\n", msg,
    435                        (tmpitem->data && tmpitem->data[0]) ? "True" : "False");
    436 
    437            oidTag = SECOID_FindOIDTag(&((*extensions)->id));
    438 
    439            fprintf(out, "%s", msg);
    440            tmpitem = &((*extensions)->value);
    441            if (oidTag == SEC_OID_X509_INVALID_DATE)
    442                sv_PrintInvalidDateExten(out, tmpitem, "invalidExt");
    443            else
    444                sv_PrintAsHex(out, tmpitem, "data=");
    445 
    446            /*fprintf(out, "\n");*/
    447            extensions++;
    448        }
    449    }
    450 
    451    return 0;
    452 }
    453 
    454 /* callers of this function must make sure that the CERTSignedCrl
    455   from which they are extracting the CERTCrl has been fully-decoded.
    456   Otherwise it will not have the entries even though the CRL may have
    457   some */
    458 void
    459 sv_PrintCRLInfo(FILE *out, CERTCrl *crl, char *m)
    460 {
    461    CERTCrlEntry *entry;
    462    int iv;
    463    char om[100];
    464 
    465    fprintf(out, "%s", m);
    466    sv_PrintAlgorithmID(out, &(crl->signatureAlg), "signatureAlgorithm=");
    467    fprintf(out, "%s", m);
    468    sv_PrintName(out, &(crl->name), "name=");
    469    fprintf(out, "%s", m);
    470    sv_PrintTime(out, &(crl->lastUpdate), "lastUpdate=");
    471    fprintf(out, "%s", m);
    472    sv_PrintTime(out, &(crl->nextUpdate), "nextUpdate=");
    473 
    474    if (crl->entries != NULL) {
    475        iv = 0;
    476        while ((entry = crl->entries[iv]) != NULL) {
    477            fprintf(out, "%sentry[%d].", m, iv);
    478            sv_PrintInteger(out, &(entry->serialNumber), "serialNumber=");
    479            fprintf(out, "%sentry[%d].", m, iv);
    480            sv_PrintTime(out, &(entry->revocationDate), "revocationDate=");
    481            snprintf(om, sizeof(om), "%sentry[%d].signedCRLEntriesExtensions.", m, iv++);
    482            sv_PrintExtensions(out, entry->extensions, om);
    483        }
    484    }
    485    snprintf(om, sizeof(om), "%ssignedCRLEntriesExtensions.", m);
    486    sv_PrintExtensions(out, crl->extensions, om);
    487 }
    488 
    489 int
    490 sv_PrintCertificate(FILE *out, const SECItem *der, const char *m, int level)
    491 {
    492    PLArenaPool *arena = NULL;
    493    CERTCertificate *c;
    494    int rv;
    495    int iv;
    496    char mm[200];
    497 
    498    /* Decode certificate */
    499    c = (CERTCertificate *)PORT_ZAlloc(sizeof(CERTCertificate));
    500    if (!c)
    501        return PORT_GetError();
    502 
    503    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    504    if (!arena)
    505        return SEC_ERROR_NO_MEMORY;
    506 
    507    rv = SEC_ASN1DecodeItem(arena, c, SEC_ASN1_GET(CERT_CertificateTemplate),
    508                            der);
    509    if (rv) {
    510        PORT_FreeArena(arena, PR_FALSE);
    511        return rv;
    512    }
    513 
    514    /* Pretty print it out */
    515    iv = DER_GetInteger(&c->version);
    516    fprintf(out, "%sversion=%d (0x%x)\n", m, iv + 1, iv);
    517    snprintf(mm, sizeof(mm), "%sserialNumber=", m);
    518    sv_PrintInteger(out, &c->serialNumber, mm);
    519    snprintf(mm, sizeof(mm), "%ssignatureAlgorithm=", m);
    520    sv_PrintAlgorithmID(out, &c->signature, mm);
    521    snprintf(mm, sizeof(mm), "%sissuerName=", m);
    522    sv_PrintName(out, &c->issuer, mm);
    523    snprintf(mm, sizeof(mm), "%svalidity.", m);
    524    sv_PrintValidity(out, &c->validity, mm);
    525    snprintf(mm, sizeof(mm), "%ssubject=", m);
    526    sv_PrintName(out, &c->subject, mm);
    527    snprintf(mm, sizeof(mm), "%ssubjectPublicKeyInfo", m);
    528    rv = sv_PrintSubjectPublicKeyInfo(out, arena, &c->subjectPublicKeyInfo, mm);
    529    if (rv) {
    530        PORT_FreeArena(arena, PR_FALSE);
    531        return rv;
    532    }
    533    snprintf(mm, sizeof(mm), "%ssignedExtensions.", m);
    534    sv_PrintExtensions(out, c->extensions, mm);
    535 
    536    PORT_FreeArena(arena, PR_FALSE);
    537    return 0;
    538 }
    539 
    540 int
    541 sv_PrintSignedData(FILE *out, SECItem *der, char *m, SECU_PPFunc inner)
    542 {
    543    PLArenaPool *arena = NULL;
    544    CERTSignedData *sd;
    545    int rv;
    546 
    547    /* Strip off the signature */
    548    sd = (CERTSignedData *)PORT_ZAlloc(sizeof(CERTSignedData));
    549    if (!sd)
    550        return PORT_GetError();
    551 
    552    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    553    if (!arena)
    554        return SEC_ERROR_NO_MEMORY;
    555 
    556    rv = SEC_ASN1DecodeItem(arena, sd, SEC_ASN1_GET(CERT_SignedDataTemplate),
    557                            der);
    558    if (rv) {
    559        PORT_FreeArena(arena, PR_FALSE);
    560        return rv;
    561    }
    562 
    563    /*    fprintf(out, "%s:\n", m); */
    564    PORT_Strcat(m, "data.");
    565 
    566    rv = (*inner)(out, &sd->data, m, 0);
    567    if (rv) {
    568        PORT_FreeArena(arena, PR_FALSE);
    569        return rv;
    570    }
    571 
    572    m[PORT_Strlen(m) - 5] = 0;
    573    fprintf(out, "%s", m);
    574    sv_PrintAlgorithmID(out, &sd->signatureAlgorithm, "signatureAlgorithm=");
    575    DER_ConvertBitString(&sd->signature);
    576    fprintf(out, "%s", m);
    577    sv_PrintAsHex(out, &sd->signature, "signature=");
    578 
    579    PORT_FreeArena(arena, PR_FALSE);
    580    return 0;
    581 }
    582 
    583 /*
    584 ** secu_PrintPKCS7Signed
    585 **   Pretty print a PKCS7 signed data type (up to version 1).
    586 */
    587 int
    588 sv_PrintPKCS7Signed(FILE *out, SEC_PKCS7SignedData *src)
    589 {
    590    SECAlgorithmID *digAlg;       /* digest algorithms */
    591    SECItem *aCert;               /* certificate */
    592    CERTSignedCrl *aCrl;          /* certificate revocation list */
    593    SEC_PKCS7SignerInfo *sigInfo; /* signer information */
    594    int rv, iv;
    595    char om[120];
    596 
    597    sv_PrintInteger(out, &(src->version), "pkcs7.version=");
    598 
    599    /* Parse and list digest algorithms (if any) */
    600    if (src->digestAlgorithms != NULL) {
    601        iv = 0;
    602        while (src->digestAlgorithms[iv] != NULL)
    603            iv++;
    604        fprintf(out, "pkcs7.digestAlgorithmListLength=%d\n", iv);
    605        iv = 0;
    606        while ((digAlg = src->digestAlgorithms[iv]) != NULL) {
    607            snprintf(om, sizeof(om), "pkcs7.digestAlgorithm[%d]=", iv++);
    608            sv_PrintAlgorithmID(out, digAlg, om);
    609        }
    610    }
    611 
    612    /* Now for the content */
    613    rv = sv_PrintPKCS7ContentInfo(out, &(src->contentInfo),
    614                                  "pkcs7.contentInformation=");
    615    if (rv != 0)
    616        return rv;
    617 
    618    /* Parse and list certificates (if any) */
    619    if (src->rawCerts != NULL) {
    620        iv = 0;
    621        while (src->rawCerts[iv] != NULL)
    622            iv++;
    623        fprintf(out, "pkcs7.certificateListLength=%d\n", iv);
    624 
    625        iv = 0;
    626        while ((aCert = src->rawCerts[iv]) != NULL) {
    627            snprintf(om, sizeof(om), "certificate[%d].", iv++);
    628            rv = sv_PrintSignedData(out, aCert, om, sv_PrintCertificate);
    629            if (rv)
    630                return rv;
    631        }
    632    }
    633 
    634    /* Parse and list CRL's (if any) */
    635    if (src->crls != NULL) {
    636        iv = 0;
    637        while (src->crls[iv] != NULL)
    638            iv++;
    639        fprintf(out, "pkcs7.signedRevocationLists=%d\n", iv);
    640        iv = 0;
    641        while ((aCrl = src->crls[iv]) != NULL) {
    642            snprintf(om, sizeof(om), "signedRevocationList[%d].", iv);
    643            fprintf(out, "%s", om);
    644            sv_PrintAlgorithmID(out, &aCrl->signatureWrap.signatureAlgorithm,
    645                                "signatureAlgorithm=");
    646            DER_ConvertBitString(&aCrl->signatureWrap.signature);
    647            fprintf(out, "%s", om);
    648            sv_PrintAsHex(out, &aCrl->signatureWrap.signature, "signature=");
    649            snprintf(om, sizeof(om), "certificateRevocationList[%d].", iv);
    650            sv_PrintCRLInfo(out, &aCrl->crl, om);
    651            iv++;
    652        }
    653    }
    654 
    655    /* Parse and list signatures (if any) */
    656    if (src->signerInfos != NULL) {
    657        iv = 0;
    658        while (src->signerInfos[iv] != NULL)
    659            iv++;
    660        fprintf(out, "pkcs7.signerInformationListLength=%d\n", iv);
    661        iv = 0;
    662        while ((sigInfo = src->signerInfos[iv]) != NULL) {
    663            snprintf(om, sizeof(om), "signerInformation[%d].", iv++);
    664            sv_PrintSignerInfo(out, sigInfo, om);
    665        }
    666    }
    667 
    668    return 0;
    669 }
    670 
    671 #if 0
    672 /*
    673 ** secu_PrintPKCS7Enveloped
    674 **  Pretty print a PKCS7 enveloped data type (up to version 1).
    675 */
    676 void
    677 secu_PrintPKCS7Enveloped(FILE *out, SEC_PKCS7EnvelopedData *src,
    678             char *m, int level)
    679 {
    680    SEC_PKCS7RecipientInfo *recInfo;   /* pointer for signer information */
    681    int iv;
    682    char om[100];
    683 
    684    secu_Indent(out, level); fprintf(out, "%s:\n", m);
    685    sv_PrintInteger(out, &(src->version), "Version", level + 1);
    686 
    687    /* Parse and list recipients (this is not optional) */
    688    if (src->recipientInfos != NULL) {
    689    secu_Indent(out, level + 1);
    690    fprintf(out, "Recipient Information List:\n");
    691    iv = 0;
    692    while ((recInfo = src->recipientInfos[iv++]) != NULL) {
    693        snprintf(om, sizeof(om), "Recipient Information (%x)", iv);
    694        secu_PrintRecipientInfo(out, recInfo, om, level + 2);
    695    }
    696    }
    697 
    698    secu_PrintPKCS7EncContent(out, &src->encContentInfo,
    699                  "Encrypted Content Information", level + 1);
    700 }
    701 
    702 /*
    703 ** secu_PrintPKCS7SignedEnveloped
    704 **   Pretty print a PKCS7 singed and enveloped data type (up to version 1).
    705 */
    706 int
    707 secu_PrintPKCS7SignedAndEnveloped(FILE *out,
    708                  SEC_PKCS7SignedAndEnvelopedData *src,
    709                  char *m, int level)
    710 {
    711    SECAlgorithmID *digAlg;  /* pointer for digest algorithms */
    712    SECItem *aCert;           /* pointer for certificate */
    713    CERTSignedCrl *aCrl;        /* pointer for certificate revocation list */
    714    SEC_PKCS7SignerInfo *sigInfo;   /* pointer for signer information */
    715    SEC_PKCS7RecipientInfo *recInfo; /* pointer for recipient information */
    716    int rv, iv;
    717    char om[100];
    718 
    719    secu_Indent(out, level); fprintf(out, "%s:\n", m);
    720    sv_PrintInteger(out, &(src->version), "Version", level + 1);
    721 
    722    /* Parse and list recipients (this is not optional) */
    723    if (src->recipientInfos != NULL) {
    724    secu_Indent(out, level + 1);
    725    fprintf(out, "Recipient Information List:\n");
    726    iv = 0;
    727    while ((recInfo = src->recipientInfos[iv++]) != NULL) {
    728        snprintf(om, sizeof(om), "Recipient Information (%x)", iv);
    729        secu_PrintRecipientInfo(out, recInfo, om, level + 2);
    730    }
    731    }
    732 
    733    /* Parse and list digest algorithms (if any) */
    734    if (src->digestAlgorithms != NULL) {
    735    secu_Indent(out, level + 1);  fprintf(out, "Digest Algorithm List:\n");
    736    iv = 0;
    737    while ((digAlg = src->digestAlgorithms[iv++]) != NULL) {
    738        snprintf(om, sizeof(om), "Digest Algorithm (%x)", iv);
    739        sv_PrintAlgorithmID(out, digAlg, om);
    740    }
    741    }
    742 
    743    secu_PrintPKCS7EncContent(out, &src->encContentInfo,
    744                  "Encrypted Content Information", level + 1);
    745 
    746    /* Parse and list certificates (if any) */
    747    if (src->rawCerts != NULL) {
    748    secu_Indent(out, level + 1);  fprintf(out, "Certificate List:\n");
    749    iv = 0;
    750    while ((aCert = src->rawCerts[iv++]) != NULL) {
    751        snprintf(om, sizeof(om), "Certificate (%x)", iv);
    752        rv = SECU_PrintSignedData(out, aCert, om, level + 2,
    753                      SECU_PrintCertificate);
    754        if (rv)
    755        return rv;
    756    }
    757    }
    758 
    759    /* Parse and list CRL's (if any) */
    760    if (src->crls != NULL) {
    761    secu_Indent(out, level + 1);
    762    fprintf(out, "Signed Revocation Lists:\n");
    763    iv = 0;
    764    while ((aCrl = src->crls[iv++]) != NULL) {
    765        snprintf(om, sizeof(om), "Signed Revocation List (%x)", iv);
    766        secu_Indent(out, level + 2);  fprintf(out, "%s:\n", om);
    767        sv_PrintAlgorithmID(out, &aCrl->signatureWrap.signatureAlgorithm,
    768                  "Signature Algorithm");
    769        DER_ConvertBitString(&aCrl->signatureWrap.signature);
    770        sv_PrintAsHex(out, &aCrl->signatureWrap.signature, "Signature",
    771                level+3);
    772        SECU_PrintCRLInfo(out, &aCrl->crl, "Certificate Revocation List",
    773              level + 3);
    774    }
    775    }
    776 
    777    /* Parse and list signatures (if any) */
    778    if (src->signerInfos != NULL) {
    779    secu_Indent(out, level + 1);
    780    fprintf(out, "Signer Information List:\n");
    781    iv = 0;
    782    while ((sigInfo = src->signerInfos[iv++]) != NULL) {
    783        snprintf(om, sizeof(om), "Signer Information (%x)", iv);
    784        secu_PrintSignerInfo(out, sigInfo, om, level + 2);
    785    }
    786    }
    787 
    788    return 0;
    789 }
    790 
    791 /*
    792 ** secu_PrintPKCS7Encrypted
    793 **   Pretty print a PKCS7 encrypted data type (up to version 1).
    794 */
    795 void
    796 secu_PrintPKCS7Encrypted(FILE *out, SEC_PKCS7EncryptedData *src,
    797             char *m, int level)
    798 {
    799    secu_Indent(out, level); fprintf(out, "%s:\n", m);
    800    sv_PrintInteger(out, &(src->version), "Version", level + 1);
    801 
    802    secu_PrintPKCS7EncContent(out, &src->encContentInfo,
    803                  "Encrypted Content Information", level + 1);
    804 }
    805 
    806 /*
    807 ** secu_PrintPKCS7Digested
    808 **   Pretty print a PKCS7 digested data type (up to version 1).
    809 */
    810 void
    811 sv_PrintPKCS7Digested(FILE *out, SEC_PKCS7DigestedData *src)
    812 {
    813    secu_Indent(out, level); fprintf(out, "%s:\n", m);
    814    sv_PrintInteger(out, &(src->version), "Version", level + 1);
    815 
    816    sv_PrintAlgorithmID(out, &src->digestAlg, "Digest Algorithm");
    817    sv_PrintPKCS7ContentInfo(out, &src->contentInfo, "Content Information",
    818                   level + 1);
    819    sv_PrintAsHex(out, &src->digest, "Digest", level + 1);
    820 }
    821 
    822 #endif
    823 
    824 /*
    825 ** secu_PrintPKCS7ContentInfo
    826 **   Takes a SEC_PKCS7ContentInfo type and sends the contents to the
    827 ** appropriate function
    828 */
    829 int
    830 sv_PrintPKCS7ContentInfo(FILE *out, SEC_PKCS7ContentInfo *src, char *m)
    831 {
    832    const char *desc;
    833    SECOidTag kind;
    834    int rv;
    835 
    836    if (src->contentTypeTag == NULL)
    837        src->contentTypeTag = SECOID_FindOID(&(src->contentType));
    838 
    839    if (src->contentTypeTag == NULL) {
    840        desc = "Unknown";
    841        kind = SEC_OID_PKCS7_DATA;
    842    } else {
    843        desc = src->contentTypeTag->desc;
    844        kind = src->contentTypeTag->offset;
    845    }
    846 
    847    fprintf(out, "%s%s\n", m, desc);
    848 
    849    if (src->content.data == NULL) {
    850        fprintf(out, "pkcs7.data=<no content>\n");
    851        return 0;
    852    }
    853 
    854    rv = 0;
    855    switch (kind) {
    856        case SEC_OID_PKCS7_SIGNED_DATA: /* Signed Data */
    857            rv = sv_PrintPKCS7Signed(out, src->content.signedData);
    858            break;
    859 
    860        case SEC_OID_PKCS7_ENVELOPED_DATA: /* Enveloped Data */
    861            fprintf(out, "pkcs7EnvelopedData=<unsupported>\n");
    862            /*sv_PrintPKCS7Enveloped(out, src->content.envelopedData);*/
    863            break;
    864 
    865        case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: /* Signed and Enveloped */
    866            fprintf(out, "pkcs7SignedEnvelopedData=<unsupported>\n");
    867            /*rv = sv_PrintPKCS7SignedAndEnveloped(out,
    868                                src->content.signedAndEnvelopedData);*/
    869            break;
    870 
    871        case SEC_OID_PKCS7_DIGESTED_DATA: /* Digested Data */
    872            fprintf(out, "pkcs7DigestedData=<unsupported>\n");
    873            /*sv_PrintPKCS7Digested(out, src->content.digestedData);*/
    874            break;
    875 
    876        case SEC_OID_PKCS7_ENCRYPTED_DATA: /* Encrypted Data */
    877            fprintf(out, "pkcs7EncryptedData=<unsupported>\n");
    878            /*sv_PrintPKCS7Encrypted(out, src->content.encryptedData);*/
    879            break;
    880 
    881        default:
    882            fprintf(out, "pkcs7UnknownData=<unsupported>\n");
    883            /*sv_PrintAsHex(out, src->content.data);*/
    884            break;
    885    }
    886 
    887    return rv;
    888 }
    889 
    890 int
    891 SV_PrintPKCS7ContentInfo(FILE *out, SECItem *der)
    892 {
    893    SEC_PKCS7ContentInfo *cinfo;
    894    int rv = -1;
    895 
    896    cinfo = SEC_PKCS7DecodeItem(der, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
    897 
    898    if (cinfo != NULL) {
    899        rv = sv_PrintPKCS7ContentInfo(out, cinfo, "pkcs7.contentInfo=");
    900        SEC_PKCS7DestroyContentInfo(cinfo);
    901    }
    902 
    903    return rv;
    904 }
    905 /*
    906 ** End of PKCS7 functions
    907 */