PageRenderTime 81ms CodeModel.GetById 12ms app.highlight 63ms RepoModel.GetById 1ms app.codeStats 0ms

/security/nss/cmd/signver/pk7print.c

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