summaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'cmd')
-rw-r--r--cmd/lib/basicutil.h2
-rw-r--r--cmd/lib/secutil.c630
-rw-r--r--cmd/lib/secutil.h6
-rw-r--r--cmd/pk12util/pk12util.c122
-rw-r--r--cmd/pp/pp.c12
5 files changed, 666 insertions, 106 deletions
diff --git a/cmd/lib/basicutil.h b/cmd/lib/basicutil.h
index de8c1b01e..ba76b1798 100644
--- a/cmd/lib/basicutil.h
+++ b/cmd/lib/basicutil.h
@@ -54,10 +54,8 @@ extern void SECU_PrintAsHex(FILE *out, const SECItem *i, const char *m,
/* dump a buffer in hex and ASCII */
extern void SECU_PrintBuf(FILE *out, const char *msg, const void *vp, int len);
-#ifdef HAVE_EPV_TEMPLATE
/* Dump contents of private key */
extern int SECU_PrintPrivateKey(FILE *out, SECItem *der, char *m, int level);
-#endif
/* Init PKCS11 stuff */
extern SECStatus SECU_PKCS11Init(PRBool readOnly);
diff --git a/cmd/lib/secutil.c b/cmd/lib/secutil.c
index 7fb041ec7..d9270ed92 100644
--- a/cmd/lib/secutil.c
+++ b/cmd/lib/secutil.c
@@ -562,20 +562,110 @@ SECU_ReadDERFromFile(SECItem *der, PRFileDesc *inFile, PRBool ascii,
#define INDENT_MULT 4
+/*
+ * remove the tag and length and just leave the bare BER data
+ */
SECStatus
SECU_StripTagAndLength(SECItem *i)
{
unsigned int start;
+ PRBool isIndefinite;
if (!i || !i->data || i->len < 2) { /* must be at least tag and length */
+ PORT_SetError(SEC_ERROR_BAD_DER);
return SECFailure;
}
+ isIndefinite = (i->data[1] == 0x80);
start = ((i->data[1] & 0x80) ? (i->data[1] & 0x7f) + 2 : 2);
if (i->len < start) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
return SECFailure;
}
i->data += start;
i->len -= start;
+ /* we are using indefinite encoding, drop the trailing zero */
+ if (isIndefinite) {
+ if (i->len <= 1) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ /* verify tags are zero */
+ if ((i->data[i->len - 1] != 0) || (i->data[i->len - 2] != 0)) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ i->len -= 2;
+ }
+
+ return SECSuccess;
+}
+
+/*
+ * Create a new SECItem which points to the current BER tag and length with
+ * all it's data. For indefinite encoding, this will also include the trailing
+ * indefinite markers
+ * The 'in' item is advanced to point to the next BER tag.
+ * You don't want to use this in an actual BER/DER parser as NSS already
+ * has 3 to choose from)
+ */
+SECStatus
+SECU_ExtractBERAndStep(SECItem *in, SECItem *out)
+{
+ if (!in || !in->data || in->len < 2) { /* must be at least tag and length */
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+
+ *out = *in;
+
+ /* first handle indefinite encoding */
+ if (out->data[1] == 0x80) {
+ SECItem this = *out;
+ SECItem next;
+ this.data += 2;
+ this.len -= 2;
+ out->len = 2;
+ /* walk through all the entries until we find the '0' */
+ while ((this.len >= 2) && (this.data[0] != 0)) {
+ SECStatus rv = SECU_ExtractBERAndStep(&this, &next);
+ if (rv != SECSuccess) {
+ return rv;
+ }
+ out->len += next.len;
+ }
+ if ((this.len < 2) || ((this.data[0] != 0) && (this.data[1] != 0))) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ out->len += 2; /* include the trailing zeros */
+ in->data += out->len;
+ in->len -= out->len;
+ return SECSuccess;
+ }
+
+ /* now handle normal DER encoding */
+ if (out->data[1] & 0x80) {
+ unsigned int i;
+ unsigned int lenlen = out->data[1] & 0x7f;
+ unsigned int len = 0;
+ if (lenlen > sizeof out->len) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ for (i = 0; i < lenlen; i++) {
+ len = (len << 8) | out->data[2 + i];
+ }
+ out->len = len + lenlen + 2;
+ } else {
+ out->len = out->data[1] + 2;
+ }
+ if (out->len > in->len) {
+ /* we've ran into a truncated file */
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ in->data += out->len;
+ in->len -= out->len;
return SECSuccess;
}
@@ -786,26 +876,10 @@ SECU_PrintSet(FILE *out, const SECItem *t, const char *m, int level)
fprintf(out, "%s{\n", label); /* } */
while (my.len >= 2) {
- SECItem tmp = my;
-
- if (tmp.data[1] & 0x80) {
- unsigned int i;
- unsigned int lenlen = tmp.data[1] & 0x7f;
- if (lenlen > sizeof tmp.len)
- break;
- tmp.len = 0;
- for (i = 0; i < lenlen; i++) {
- tmp.len = (tmp.len << 8) | tmp.data[2 + i];
- }
- tmp.len += lenlen + 2;
- } else {
- tmp.len = tmp.data[1] + 2;
- }
- if (tmp.len > my.len) {
- tmp.len = my.len;
+ SECItem tmp;
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &tmp)) {
+ break;
}
- my.data += tmp.len;
- my.len -= tmp.len;
SECU_PrintAny(out, &tmp, NULL, level + 1);
}
SECU_Indent(out, level);
@@ -906,12 +980,14 @@ SECU_PrintEncodedInteger(FILE *out, const SECItem *i, const char *m, int level)
}
/* Print a DER encoded OID */
-void
+SECOidTag
SECU_PrintEncodedObjectID(FILE *out, const SECItem *i, const char *m, int level)
{
SECItem my = *i;
+ SECOidTag tag = SEC_OID_UNKNOWN;
if (SECSuccess == SECU_StripTagAndLength(&my))
- SECU_PrintObjectID(out, &my, m, level);
+ tag = SECU_PrintObjectID(out, &my, m, level);
+ return tag;
}
static void
@@ -2455,7 +2531,6 @@ SECU_PrintSubjectPublicKeyInfo(FILE *out, SECItem *der, char *m, int level)
return rv;
}
-#ifdef HAVE_EPV_TEMPLATE
int
SECU_PrintPrivateKey(FILE *out, SECItem *der, char *m, int level)
{
@@ -2482,7 +2557,6 @@ loser:
PORT_FreeArena(arena, PR_TRUE);
return rv;
}
-#endif
int
SECU_PrintFingerprints(FILE *out, SECItem *derCert, char *m, int level)
@@ -2545,16 +2619,26 @@ SECU_PrintFingerprints(FILE *out, SECItem *derCert, char *m, int level)
*/
/* forward declaration */
+typedef enum {
+ secuPKCS7Unknown = 0,
+ secuPKCS7PKCS12AuthSafe,
+ secuPKCS7PKCS12Safe
+} secuPKCS7State;
+
static int
-secu_PrintPKCS7ContentInfo(FILE *, SEC_PKCS7ContentInfo *, char *, int);
+secu_PrintPKCS7ContentInfo(FILE *, SEC_PKCS7ContentInfo *, secuPKCS7State,
+ const char *, int);
+static int
+secu_PrintDERPKCS7ContentInfo(FILE *, SECItem *, secuPKCS7State,
+ const char *, int);
/*
** secu_PrintPKCS7EncContent
** Prints a SEC_PKCS7EncryptedContentInfo (without decrypting it)
*/
-static void
+static int
secu_PrintPKCS7EncContent(FILE *out, SEC_PKCS7EncryptedContentInfo *src,
- char *m, int level)
+ secuPKCS7State state, const char *m, int level)
{
if (src->contentTypeTag == NULL)
src->contentTypeTag = SECOID_FindOID(&(src->contentType));
@@ -2569,6 +2653,7 @@ secu_PrintPKCS7EncContent(FILE *out, SEC_PKCS7EncryptedContentInfo *src,
"Content Encryption Algorithm", level + 1);
SECU_PrintAsHex(out, &(src->encContent),
"Encrypted Content", level + 1);
+ return 0;
}
/*
@@ -2576,8 +2661,8 @@ secu_PrintPKCS7EncContent(FILE *out, SEC_PKCS7EncryptedContentInfo *src,
** Prints a PKCS7RecipientInfo type
*/
static void
-secu_PrintRecipientInfo(FILE *out, SEC_PKCS7RecipientInfo *info, char *m,
- int level)
+secu_PrintRecipientInfo(FILE *out, SEC_PKCS7RecipientInfo *info,
+ const char *m, int level)
{
SECU_Indent(out, level);
fprintf(out, "%s:\n", m);
@@ -2599,7 +2684,8 @@ secu_PrintRecipientInfo(FILE *out, SEC_PKCS7RecipientInfo *info, char *m,
** Prints a PKCS7SingerInfo type
*/
static void
-secu_PrintSignerInfo(FILE *out, SEC_PKCS7SignerInfo *info, char *m, int level)
+secu_PrintSignerInfo(FILE *out, SEC_PKCS7SignerInfo *info,
+ const char *m, int level)
{
SEC_PKCS7Attribute *attr;
int iv;
@@ -2691,7 +2777,7 @@ SECU_PrintCRLInfo(FILE *out, CERTCrl *crl, char *m, int level)
*/
static int
secu_PrintPKCS7Signed(FILE *out, SEC_PKCS7SignedData *src,
- const char *m, int level)
+ secuPKCS7State state, const char *m, int level)
{
SECAlgorithmID *digAlg; /* digest algorithms */
SECItem *aCert; /* certificate */
@@ -2717,7 +2803,7 @@ secu_PrintPKCS7Signed(FILE *out, SEC_PKCS7SignedData *src,
/* Now for the content */
rv = secu_PrintPKCS7ContentInfo(out, &(src->contentInfo),
- "Content Information", level + 1);
+ state, "Content Information", level + 1);
if (rv != 0)
return rv;
@@ -2772,9 +2858,9 @@ secu_PrintPKCS7Signed(FILE *out, SEC_PKCS7SignedData *src,
** secu_PrintPKCS7Enveloped
** Pretty print a PKCS7 enveloped data type (up to version 1).
*/
-static void
+static int
secu_PrintPKCS7Enveloped(FILE *out, SEC_PKCS7EnvelopedData *src,
- const char *m, int level)
+ secuPKCS7State state, const char *m, int level)
{
SEC_PKCS7RecipientInfo *recInfo; /* pointer for signer information */
int iv;
@@ -2795,8 +2881,8 @@ secu_PrintPKCS7Enveloped(FILE *out, SEC_PKCS7EnvelopedData *src,
}
}
- secu_PrintPKCS7EncContent(out, &src->encContentInfo,
- "Encrypted Content Information", level + 1);
+ return secu_PrintPKCS7EncContent(out, &src->encContentInfo, state,
+ "Encrypted Content Information", level + 1);
}
/*
@@ -2806,7 +2892,8 @@ secu_PrintPKCS7Enveloped(FILE *out, SEC_PKCS7EnvelopedData *src,
static int
secu_PrintPKCS7SignedAndEnveloped(FILE *out,
SEC_PKCS7SignedAndEnvelopedData *src,
- const char *m, int level)
+ secuPKCS7State state, const char *m,
+ int level)
{
SECAlgorithmID *digAlg; /* pointer for digest algorithms */
SECItem *aCert; /* pointer for certificate */
@@ -2842,8 +2929,10 @@ secu_PrintPKCS7SignedAndEnveloped(FILE *out,
}
}
- secu_PrintPKCS7EncContent(out, &src->encContentInfo,
- "Encrypted Content Information", level + 1);
+ rv = secu_PrintPKCS7EncContent(out, &src->encContentInfo, state,
+ "Encrypted Content Information", level + 1);
+ if (rv)
+ return rv;
/* Parse and list certificates (if any) */
if (src->rawCerts != NULL) {
@@ -2920,25 +3009,25 @@ SECU_PrintCrl(FILE *out, SECItem *der, char *m, int level)
** secu_PrintPKCS7Encrypted
** Pretty print a PKCS7 encrypted data type (up to version 1).
*/
-static void
+static int
secu_PrintPKCS7Encrypted(FILE *out, SEC_PKCS7EncryptedData *src,
- const char *m, int level)
+ secuPKCS7State state, const char *m, int level)
{
SECU_Indent(out, level);
fprintf(out, "%s:\n", m);
SECU_PrintInteger(out, &(src->version), "Version", level + 1);
- secu_PrintPKCS7EncContent(out, &src->encContentInfo,
- "Encrypted Content Information", level + 1);
+ return secu_PrintPKCS7EncContent(out, &src->encContentInfo, state,
+ "Encrypted Content Information", level + 1);
}
/*
** secu_PrintPKCS7Digested
** Pretty print a PKCS7 digested data type (up to version 1).
*/
-static void
+static int
secu_PrintPKCS7Digested(FILE *out, SEC_PKCS7DigestedData *src,
- const char *m, int level)
+ secuPKCS7State state, const char *m, int level)
{
SECU_Indent(out, level);
fprintf(out, "%s:\n", m);
@@ -2946,9 +3035,257 @@ secu_PrintPKCS7Digested(FILE *out, SEC_PKCS7DigestedData *src,
SECU_PrintAlgorithmID(out, &src->digestAlg, "Digest Algorithm",
level + 1);
- secu_PrintPKCS7ContentInfo(out, &src->contentInfo, "Content Information",
- level + 1);
+ secu_PrintPKCS7ContentInfo(out, &src->contentInfo, state,
+ "Content Information", level + 1);
SECU_PrintAsHex(out, &src->digest, "Digest", level + 1);
+ return 0;
+}
+
+static int
+secu_PrintPKCS12Attributes(FILE *out, SECItem *item, const char *m, int level)
+{
+ SECItem my = *item;
+ SECItem attribute;
+ SECItem attributeID;
+ SECItem attributeValues;
+
+ if ((my.data[0] != (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SET)) ||
+ SECSuccess != SECU_StripTagAndLength(&my)) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ level++;
+
+ while (my.len) {
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &attribute)) {
+ return SECFailure;
+ }
+ if ((attribute.data[0] != (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE)) ||
+ SECSuccess != SECU_StripTagAndLength(&attribute)) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+
+ /* attribute ID */
+ if (SECSuccess != SECU_ExtractBERAndStep(&attribute, &attributeID)) {
+ return SECFailure;
+ }
+ if ((attributeID.data[0] & SEC_ASN1_TAGNUM_MASK) != SEC_ASN1_OBJECT_ID) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ SECU_PrintEncodedObjectID(out, &attributeID, "Attribute ID", level);
+
+ /* attribute values */
+ if (!attribute.len) { /* skip if there aren't any */
+ continue;
+ }
+ if (SECSuccess != SECU_ExtractBERAndStep(&attribute, &attributeValues)) {
+ return SECFailure;
+ }
+ if (SECSuccess != SECU_StripTagAndLength(&attributeValues)) {
+ return SECFailure;
+ }
+ while (attributeValues.len) {
+ SECItem tmp;
+ if (SECSuccess != SECU_ExtractBERAndStep(&attributeValues, &tmp)) {
+ return SECFailure;
+ }
+ SECU_PrintAny(out, &tmp, NULL, level + 1);
+ }
+ }
+ return SECSuccess;
+}
+
+static int
+secu_PrintPKCS12Bag(FILE *out, SECItem *item, const char *desc, int level)
+{
+ SECItem my = *item;
+ SECItem bagID;
+ SECItem bagValue;
+ SECItem bagAttributes;
+ SECOidTag bagTag;
+ SECStatus rv;
+ int i;
+ char *m;
+
+ if ((my.data[0] != (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE)) ||
+ SECSuccess != SECU_StripTagAndLength(&my)) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+
+ /* bagId BAG-TYPE.&id ({PKCS12BagSet}) */
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &bagID)) {
+ return SECFailure;
+ }
+ if ((bagID.data[0] & SEC_ASN1_TAGNUM_MASK) != SEC_ASN1_OBJECT_ID) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ m = PR_smprintf("%s ID", desc);
+ bagTag = SECU_PrintEncodedObjectID(out, &bagID, m ? m : "Bag ID", level);
+ if (m)
+ PR_smprintf_free(m);
+
+ /* bagValue [0] EXPLICIT BAG-TYPE.&type({PKCS12BagSet}{@bagID}) */
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &bagValue)) {
+ return SECFailure;
+ }
+ if ((bagValue.data[0] & (SEC_ASN1_CLASS_MASK | SEC_ASN1_TAGNUM_MASK)) !=
+ (SEC_ASN1_CONTEXT_SPECIFIC | 0)) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ if (SECSuccess != SECU_StripTagAndLength(&bagValue)) {
+ return SECFailure;
+ }
+
+ rv = SECSuccess;
+ switch (bagTag) {
+ case SEC_OID_PKCS12_V1_KEY_BAG_ID:
+ /* Future we need to print out raw private keys. Not a priority since
+ * p12util can't create files with unencrypted private keys, but
+ * some tools can and do */
+ SECU_PrintAny(out, &bagValue, "Private Key", level);
+ break;
+ case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID:
+ rv = SECU_PrintPrivateKey(out, &bagValue,
+ "Encrypted Private Key", level);
+ break;
+ case SEC_OID_PKCS12_V1_CERT_BAG_ID:
+ rv = secu_PrintPKCS12Bag(out, &bagValue, "Certificate Bag", level + 1);
+ break;
+ case SEC_OID_PKCS12_V1_CRL_BAG_ID:
+ rv = secu_PrintPKCS12Bag(out, &bagValue, "Crl Bag", level + 1);
+ break;
+ case SEC_OID_PKCS12_V1_SECRET_BAG_ID:
+ rv = secu_PrintPKCS12Bag(out, &bagValue, "Secret Bag", level + 1);
+ break;
+ /* from recursive call from CRL and certificate Bag */
+ case SEC_OID_PKCS9_X509_CRL:
+ case SEC_OID_PKCS9_X509_CERT:
+ case SEC_OID_PKCS9_SDSI_CERT:
+ /* unwrap the octect string */
+ rv = SECU_StripTagAndLength(&bagValue);
+ if (rv != SECSuccess) {
+ break;
+ }
+ /* fall through */
+ case SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID:
+ case SEC_OID_PKCS12_X509_CERT_CRL_BAG:
+ case SEC_OID_PKCS12_SDSI_CERT_BAG:
+ if (strcmp(desc, "Crl Bag") == 0) {
+ rv = SECU_PrintSignedData(out, &bagValue, NULL, level + 1,
+ (SECU_PPFunc)SECU_PrintCrl);
+ } else {
+ rv = SECU_PrintSignedData(out, &bagValue, NULL, level + 1,
+ (SECU_PPFunc)SECU_PrintCertificate);
+ }
+ break;
+ case SEC_OID_PKCS12_V1_SAFE_CONTENTS_BAG_ID:
+ for (i = 1; my.len; i++) {
+ SECItem nextBag;
+ rv = SECU_ExtractBERAndStep(&bagValue, &nextBag);
+ if (rv != SECSuccess) {
+ break;
+ }
+ m = PR_smprintf("Nested Bag %d", i);
+ rv = secu_PrintPKCS12Bag(out, &nextBag,
+ m ? m : "Nested Bag", level + 1);
+ if (m)
+ PR_smprintf_free(m);
+ if (rv != SECSuccess) {
+ break;
+ }
+ }
+ break;
+ default:
+ m = PR_smprintf("%s Value", desc);
+ SECU_PrintAny(out, &bagValue, m ? m : "Bag Value", level);
+ if (m)
+ PR_smprintf_free(m);
+ }
+ if (rv != SECSuccess) {
+ return rv;
+ }
+
+ /* bagAttributes SET OF PKCS12Attributes OPTIONAL */
+ if (my.len &&
+ (my.data[0] == (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SET))) {
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &bagAttributes)) {
+ return SECFailure;
+ }
+ m = PR_smprintf("%s Attributes", desc);
+ rv = secu_PrintPKCS12Attributes(out, &bagAttributes,
+ m ? m : "Bag Attributes", level);
+ if (m)
+ PR_smprintf_free(m);
+ }
+ return rv;
+}
+
+static int
+secu_PrintPKCS7Data(FILE *out, SECItem *item, secuPKCS7State state,
+ const char *desc, int level)
+{
+ SECItem my = *item;
+ SECItem nextbag;
+ int i;
+ SECStatus rv;
+
+ /* walk down each safe */
+ switch (state) {
+ case secuPKCS7PKCS12AuthSafe:
+ if ((my.data[0] != (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE)) ||
+ SECSuccess != SECU_StripTagAndLength(&my)) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ for (i = 1; my.len; i++) {
+ char *m;
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &nextbag)) {
+ return SECFailure;
+ }
+ m = PR_smprintf("Safe %d", i);
+ rv = secu_PrintDERPKCS7ContentInfo(out, &nextbag,
+ secuPKCS7PKCS12Safe,
+ m ? m : "Safe", level);
+ if (m)
+ PR_smprintf_free(m);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+ }
+ return SECSuccess;
+ case secuPKCS7PKCS12Safe:
+ if ((my.data[0] != (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE)) ||
+ SECSuccess != SECU_StripTagAndLength(&my)) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ for (i = 1; my.len; i++) {
+ char *m;
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &nextbag)) {
+ return SECFailure;
+ }
+ m = PR_smprintf("Bag %d", i);
+ rv = secu_PrintPKCS12Bag(out, &nextbag,
+ m ? m : "Bag", level);
+ if (m)
+ PR_smprintf_free(m);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+ }
+ return SECSuccess;
+ case secuPKCS7Unknown:
+ SECU_PrintAsHex(out, item, desc, level);
+ break;
+ }
+ return SECSuccess;
}
/*
@@ -2958,7 +3295,7 @@ secu_PrintPKCS7Digested(FILE *out, SEC_PKCS7DigestedData *src,
*/
static int
secu_PrintPKCS7ContentInfo(FILE *out, SEC_PKCS7ContentInfo *src,
- char *m, int level)
+ secuPKCS7State state, const char *m, int level)
{
const char *desc;
SECOidTag kind;
@@ -2973,7 +3310,7 @@ secu_PrintPKCS7ContentInfo(FILE *out, SEC_PKCS7ContentInfo *src,
if (src->contentTypeTag == NULL) {
desc = "Unknown";
- kind = SEC_OID_PKCS7_DATA;
+ kind = SEC_OID_UNKNOWN;
} else {
desc = src->contentTypeTag->desc;
kind = src->contentTypeTag->offset;
@@ -2991,25 +3328,33 @@ secu_PrintPKCS7ContentInfo(FILE *out, SEC_PKCS7ContentInfo *src,
rv = 0;
switch (kind) {
case SEC_OID_PKCS7_SIGNED_DATA: /* Signed Data */
- rv = secu_PrintPKCS7Signed(out, src->content.signedData, desc, level);
+ rv = secu_PrintPKCS7Signed(out, src->content.signedData,
+ state, desc, level);
break;
case SEC_OID_PKCS7_ENVELOPED_DATA: /* Enveloped Data */
- secu_PrintPKCS7Enveloped(out, src->content.envelopedData, desc, level);
+ rv = secu_PrintPKCS7Enveloped(out, src->content.envelopedData,
+ state, desc, level);
break;
case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: /* Signed and Enveloped */
rv = secu_PrintPKCS7SignedAndEnveloped(out,
src->content.signedAndEnvelopedData,
- desc, level);
+ state, desc, level);
break;
case SEC_OID_PKCS7_DIGESTED_DATA: /* Digested Data */
- secu_PrintPKCS7Digested(out, src->content.digestedData, desc, level);
+ rv = secu_PrintPKCS7Digested(out, src->content.digestedData,
+ state, desc, level);
break;
case SEC_OID_PKCS7_ENCRYPTED_DATA: /* Encrypted Data */
- secu_PrintPKCS7Encrypted(out, src->content.encryptedData, desc, level);
+ rv = secu_PrintPKCS7Encrypted(out, src->content.encryptedData,
+ state, desc, level);
+ break;
+
+ case SEC_OID_PKCS7_DATA:
+ rv = secu_PrintPKCS7Data(out, src->content.data, state, desc, level);
break;
default:
@@ -3024,8 +3369,9 @@ secu_PrintPKCS7ContentInfo(FILE *out, SEC_PKCS7ContentInfo *src,
** SECU_PrintPKCS7ContentInfo
** Decode and print any major PKCS7 data type (up to version 1).
*/
-int
-SECU_PrintPKCS7ContentInfo(FILE *out, SECItem *der, char *m, int level)
+static int
+secu_PrintDERPKCS7ContentInfo(FILE *out, SECItem *der, secuPKCS7State state,
+ const char *m, int level)
{
SEC_PKCS7ContentInfo *cinfo;
int rv;
@@ -3033,7 +3379,7 @@ SECU_PrintPKCS7ContentInfo(FILE *out, SECItem *der, char *m, int level)
cinfo = SEC_PKCS7DecodeItem(der, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
if (cinfo != NULL) {
/* Send it to recursive parsing and printing module */
- rv = secu_PrintPKCS7ContentInfo(out, cinfo, m, level);
+ rv = secu_PrintPKCS7ContentInfo(out, cinfo, state, m, level);
SEC_PKCS7DestroyContentInfo(cinfo);
} else {
rv = -1;
@@ -3042,6 +3388,12 @@ SECU_PrintPKCS7ContentInfo(FILE *out, SECItem *der, char *m, int level)
return rv;
}
+int
+SECU_PrintPKCS7ContentInfo(FILE *out, SECItem *der, char *m, int level)
+{
+ return secu_PrintDERPKCS7ContentInfo(out, der, secuPKCS7Unknown, m, level);
+}
+
/*
** End of PKCS7 functions
*/
@@ -4214,3 +4566,169 @@ cleanup:
PORT_Free(str);
return rv;
}
+
+static SECStatus
+secu_PrintPKCS12DigestInfo(FILE *out, const SECItem *t, char *m, int level)
+{
+ SECItem my = *t;
+ SECItem rawDigestAlgID;
+ SECItem digestData;
+ SECStatus rv;
+ PLArenaPool *arena;
+ SECAlgorithmID digestAlgID;
+ char *mAlgID = NULL;
+ char *mDigest = NULL;
+
+ /* strip the outer sequence */
+ if ((my.data[0] != (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE)) ||
+ SECSuccess != SECU_StripTagAndLength(&my)) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+
+ /* get the algorithm ID */
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &rawDigestAlgID)) {
+ return SECFailure;
+ }
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ return SECFailure;
+ }
+#define DIGEST_ALGID_STRING "Digest Algorithm ID"
+ if (m)
+ mAlgID = PR_smprintf("%s " DIGEST_ALGID_STRING, m);
+ rv = SEC_QuickDERDecodeItem(arena, &digestAlgID,
+ SEC_ASN1_GET(SECOID_AlgorithmIDTemplate),
+ &rawDigestAlgID);
+ if (rv == SECSuccess) {
+ SECU_PrintAlgorithmID(out, &digestAlgID,
+ mAlgID ? mAlgID : DIGEST_ALGID_STRING, level);
+ }
+ if (mAlgID)
+ PR_smprintf_free(mAlgID);
+ PORT_FreeArena(arena, PR_FALSE);
+ if (rv != SECSuccess) {
+ return rv;
+ }
+
+ /* get the mac data */
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &digestData)) {
+ return SECFailure;
+ }
+ if ((digestData.data[0] & SEC_ASN1_TAGNUM_MASK) != SEC_ASN1_OCTET_STRING) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+#define DIGEST_STRING "Digest"
+ if (m)
+ mDigest = PR_smprintf("%s " DIGEST_STRING, m);
+ secu_PrintOctetString(out, &digestData,
+ mDigest ? mDigest : DIGEST_STRING, level);
+ if (mDigest)
+ PR_smprintf_free(mDigest);
+ return SECSuccess;
+}
+
+static SECStatus
+secu_PrintPKCS12MacData(FILE *out, const SECItem *t, char *m, int level)
+{
+ SECItem my = *t;
+ SECItem hash;
+ SECItem salt;
+
+ if (m) {
+ SECU_Indent(out, level);
+ fprintf(out, "%s: \n", m);
+ level++;
+ }
+
+ /* strip the outer sequence */
+ if ((my.data[0] != (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE)) ||
+ SECSuccess != SECU_StripTagAndLength(&my)) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &hash)) {
+ return SECFailure;
+ }
+ if (SECSuccess != secu_PrintPKCS12DigestInfo(out, &hash, "Mac", level)) {
+ return SECFailure;
+ }
+
+ /* handle the salt */
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &salt)) {
+ return SECFailure;
+ ;
+ }
+ if ((salt.data[0] & SEC_ASN1_TAGNUM_MASK) != SEC_ASN1_OCTET_STRING) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ secu_PrintOctetString(out, &salt, "Mac Salt", level);
+
+ if (my.len &&
+ ((my.data[0] & SEC_ASN1_TAGNUM_MASK) == SEC_ASN1_INTEGER)) {
+ SECItem iterator;
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &iterator)) {
+ return SECFailure;
+ }
+ SECU_PrintEncodedInteger(out, &iterator, "Iterations", level);
+ }
+ return SECSuccess;
+}
+
+SECStatus
+SECU_PrintPKCS12(FILE *out, const SECItem *t, char *m, int level)
+{
+ SECItem my = *t;
+ SECItem authSafe;
+ SECItem macData;
+
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ level++;
+
+ /* strip the outer sequence */
+ if ((my.data[0] != (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE)) ||
+ SECSuccess != SECU_StripTagAndLength(&my)) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ /* print and remove the optional version number */
+ if (my.len && ((my.data[0] & SEC_ASN1_TAGNUM_MASK) == SEC_ASN1_INTEGER)) {
+ SECItem version;
+
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &version)) {
+ return SECFailure;
+ }
+ SECU_PrintEncodedInteger(out, &version, "Version", level);
+ }
+
+ /* print the authSafe */
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &authSafe)) {
+ return SECFailure;
+ }
+ if (SECSuccess != secu_PrintDERPKCS7ContentInfo(out, &authSafe,
+ secuPKCS7PKCS12AuthSafe,
+ "AuthSafe", level)) {
+ return SECFailure;
+ }
+
+ /* print the mac data (optional) */
+ if (!my.len) {
+ return SECSuccess;
+ }
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &macData)) {
+ return SECFailure;
+ }
+ if (SECSuccess != secu_PrintPKCS12MacData(out, &macData,
+ "Mac Data", level)) {
+ return SECFailure;
+ }
+
+ if (my.len) {
+ fprintf(out, "Unknown extra data found \n");
+ }
+ return SECSuccess;
+}
diff --git a/cmd/lib/secutil.h b/cmd/lib/secutil.h
index 0bdfa9508..b5f86ad06 100644
--- a/cmd/lib/secutil.h
+++ b/cmd/lib/secutil.h
@@ -26,6 +26,7 @@
#define SEC_CT_CERTIFICATE_REQUEST "certificate-request"
#define SEC_CT_CERTIFICATE_ID "certificate-identity"
#define SEC_CT_PKCS7 "pkcs7"
+#define SEC_CT_PKCS12 "pkcs12"
#define SEC_CT_CRL "crl"
#define SEC_CT_NAME "name"
@@ -235,10 +236,8 @@ extern void SECU_PrintTrustFlags(FILE *out, CERTCertTrust *trust, char *m,
extern int SECU_PrintSubjectPublicKeyInfo(FILE *out, SECItem *der, char *m,
int level);
-#ifdef HAVE_EPV_TEMPLATE
/* Dump contents of private key */
extern int SECU_PrintPrivateKey(FILE *out, SECItem *der, char *m, int level);
-#endif
/* Dump contents of an RSA public key */
extern void SECU_PrintRSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level);
@@ -253,7 +252,8 @@ extern int SECU_PrintFingerprints(FILE *out, SECItem *derCert, char *m,
/* Pretty-print any PKCS7 thing */
extern int SECU_PrintPKCS7ContentInfo(FILE *out, SECItem *der, char *m,
int level);
-
+/* Pretty-print a pkcs12 file */
+extern SECStatus SECU_PrintPKCS12(FILE *out, const SECItem *der, char *m, int level);
/* Init PKCS11 stuff */
extern SECStatus SECU_PKCS11Init(PRBool readOnly);
diff --git a/cmd/pk12util/pk12util.c b/cmd/pk12util/pk12util.c
index 794f17b39..b0c4ffd7b 100644
--- a/cmd/pk12util/pk12util.c
+++ b/cmd/pk12util/pk12util.c
@@ -16,6 +16,7 @@
#include "nss.h"
#include "secport.h"
#include "secpkcs5.h"
+#include "sechash.h"
#include "certdb.h"
#define PKCS12_IN_BUFFER_SIZE 200
@@ -43,7 +44,7 @@ Usage()
FPS "Usage: %s -o exportfile -n certname [-d certdir] [-P dbprefix]\n",
progName);
- FPS "\t\t [-c key_cipher] [-C cert_cipher]\n"
+ FPS "\t\t [-c key_cipher] [-C cert_cipher] [-M mac_alg]\n"
"\t\t [-m | --key_len keyLen] [--cert_key_len certKeyLen] [-v]\n");
FPS "\t\t [-k slotpwfile | -K slotpw]\n"
"\t\t [-w p12filepwfile | -W p12filepw]\n");
@@ -625,7 +626,7 @@ p12u_WriteToExportFile(void *arg, const char *buf, unsigned long len)
void
P12U_ExportPKCS12Object(char *nn, char *outfile, PK11SlotInfo *inSlot,
- SECOidTag cipher, SECOidTag certCipher,
+ SECOidTag cipher, SECOidTag certCipher, SECOidTag hash,
secuPWData *slotPw, secuPWData *p12FilePw)
{
SEC_PKCS12ExportContext *p12ecx = NULL;
@@ -690,7 +691,7 @@ P12U_ExportPKCS12Object(char *nn, char *outfile, PK11SlotInfo *inSlot,
goto loser;
}
- if (SEC_PKCS12AddPasswordIntegrity(p12ecx, pwitem, SEC_OID_SHA1) !=
+ if (SEC_PKCS12AddPasswordIntegrity(p12ecx, pwitem, hash) !=
SECSuccess) {
SECU_PrintError(progName, "PKCS12 add password integrity failed");
pk12uErrno = PK12UERR_PK12ADDPWDINTEG;
@@ -722,8 +723,8 @@ P12U_ExportPKCS12Object(char *nn, char *outfile, PK11SlotInfo *inSlot,
}
if (SEC_PKCS12AddCertAndKey(p12ecx, certSafe, NULL, cert,
- CERT_GetDefaultCertDB(), keySafe, NULL, PR_TRUE, pwitem, cipher) !=
- SECSuccess) {
+ CERT_GetDefaultCertDB(), keySafe, NULL,
+ PR_TRUE, pwitem, cipher) != SECSuccess) {
SECU_PrintError(progName, "add cert and key failed");
pk12uErrno = PK12UERR_ADDCERTKEY;
goto loser;
@@ -857,6 +858,27 @@ loser:
return rv;
}
+SECOidTag
+PKCS12U_FindTagFromString(char *cipherString)
+{
+ SECOidTag tag;
+ SECOidData *oid;
+
+ /* future enhancement: accept dotted oid spec? */
+
+ for (tag = 1; (oid = SECOID_FindOIDByTag(tag)) != NULL; tag++) {
+ /* only interested in oids that we actually understand */
+ if (oid->mechanism == CKM_INVALID_MECHANISM) {
+ continue;
+ }
+ if (PORT_Strcasecmp(oid->desc, cipherString) != 0) {
+ continue;
+ }
+ return tag;
+ }
+ return SEC_OID_UNKNOWN;
+}
+
/*
* use the oid table description to map a user input string to a particular
* oid.
@@ -865,46 +887,55 @@ SECOidTag
PKCS12U_MapCipherFromString(char *cipherString, int keyLen)
{
SECOidTag tag;
- SECOidData *oid;
SECOidTag cipher;
- /* future enhancement: accept dotted oid spec? */
-
/* future enhancement: provide 'friendlier' typed in names for
* pbe mechanisms.
*/
/* look for the oid tag by Description */
+ tag = PKCS12U_FindTagFromString(cipherString);
+ if (tag == SEC_OID_UNKNOWN) {
+ return tag;
+ }
+
cipher = SEC_OID_UNKNOWN;
- for (tag = 1; (oid = SECOID_FindOIDByTag(tag)) != NULL; tag++) {
- /* only interested in oids that we actually understand */
- if (oid->mechanism == CKM_INVALID_MECHANISM) {
- continue;
- }
- if (PORT_Strcasecmp(oid->desc, cipherString) != 0) {
- continue;
- }
- /* we found a match... get the PBE version of this
- * cipher... */
- if (!SEC_PKCS5IsAlgorithmPBEAlgTag(tag)) {
- cipher = SEC_PKCS5GetPBEAlgorithm(tag, keyLen);
- /* no eqivalent PKCS5/PKCS12 cipher, use the raw
- * encryption tag we got and pass it directly in,
- * pkcs12 will use the pkcsv5 mechanism */
- if (cipher == SEC_OID_PKCS5_PBES2) {
- cipher = tag;
- } else if (cipher == SEC_OID_PKCS5_PBMAC1) {
- /* make sure we have not macing ciphers here */
- cipher = SEC_OID_UNKNOWN;
- }
- } else {
+ /* we found a match... get the PBE version of this
+ * cipher... */
+ if (!SEC_PKCS5IsAlgorithmPBEAlgTag(tag)) {
+ cipher = SEC_PKCS5GetPBEAlgorithm(tag, keyLen);
+ /* no eqivalent PKCS5/PKCS12 cipher, use the raw
+ * encryption tag we got and pass it directly in,
+ * pkcs12 will use the pkcsv5 mechanism */
+ if (cipher == SEC_OID_PKCS5_PBES2) {
cipher = tag;
+ } else if (cipher == SEC_OID_PKCS5_PBMAC1) {
+ /* make sure we have not macing ciphers here */
+ cipher = SEC_OID_UNKNOWN;
}
- break;
+ } else {
+ cipher = tag;
}
return cipher;
}
+SECOidTag
+PKCS12U_MapHashFromString(char *hashString)
+{
+ SECOidTag hashAlg;
+
+ /* look for the oid tag by Description */
+ hashAlg = PKCS12U_FindTagFromString(hashString);
+ if (hashAlg == SEC_OID_UNKNOWN) {
+ return hashAlg;
+ }
+ /* make sure it's a hashing oid */
+ if (HASH_GetHashTypeByOidTag(hashAlg) == HASH_AlgNULL) {
+ return SEC_OID_UNKNOWN;
+ }
+ return hashAlg;
+}
+
static void
p12u_EnableAllCiphers()
{
@@ -917,7 +948,7 @@ p12u_EnableAllCiphers()
SEC_PKCS12EnableCipher(PKCS12_AES_CBC_128, 1);
SEC_PKCS12EnableCipher(PKCS12_AES_CBC_192, 1);
SEC_PKCS12EnableCipher(PKCS12_AES_CBC_256, 1);
- SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1);
+ SEC_PKCS12SetPreferredCipher(PKCS12_AES_CBC_256, 1);
}
static PRUintn
@@ -963,7 +994,8 @@ enum {
opt_Cipher,
opt_CertCipher,
opt_KeyLength,
- opt_CertKeyLength
+ opt_CertKeyLength,
+ opt_Mac
};
static secuCommandFlag pk12util_options[] =
@@ -984,7 +1016,8 @@ static secuCommandFlag pk12util_options[] =
{ /* opt_Cipher */ 'c', PR_TRUE, 0, PR_FALSE },
{ /* opt_CertCipher */ 'C', PR_TRUE, 0, PR_FALSE },
{ /* opt_KeyLength */ 'm', PR_TRUE, 0, PR_FALSE, "key_len" },
- { /* opt_CertKeyLength */ 0, PR_TRUE, 0, PR_FALSE, "cert_key_len" }
+ { /* opt_CertKeyLength */ 0, PR_TRUE, 0, PR_FALSE, "cert_key_len" },
+ { /* opt_Mac */ 'M', PR_TRUE, 0, PR_FALSE, PR_FALSE }
};
int
@@ -998,9 +1031,9 @@ main(int argc, char **argv)
char *export_file = NULL;
char *dbprefix = "";
SECStatus rv;
- SECOidTag cipher =
- SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC;
- SECOidTag certCipher;
+ SECOidTag cipher = SEC_OID_AES_256_CBC;
+ SECOidTag hash = SEC_OID_SHA256;
+ SECOidTag certCipher = SEC_OID_AES_128_CBC;
int keyLen = 0;
int certKeyLen = 0;
secuCommand pk12util;
@@ -1114,7 +1147,6 @@ main(int argc, char **argv)
}
}
- certCipher = PK11_IsFIPS() ? SEC_OID_UNKNOWN : SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC;
if (pk12util.options[opt_CertCipher].activated) {
char *cipherString = pk12util.options[opt_CertCipher].arg;
@@ -1132,6 +1164,18 @@ main(int argc, char **argv)
}
}
}
+ if (pk12util.options[opt_Mac].activated) {
+ char *hashString = pk12util.options[opt_Mac].arg;
+
+ hash = PKCS12U_MapHashFromString(hashString);
+ /* We don't support creating Mac-less pkcs 12 files */
+ if (hash == SEC_OID_UNKNOWN) {
+ PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
+ SECU_PrintError(progName, "Algorithm: \"%s\"", hashString);
+ pk12uErrno = PK12UERR_INVALIDALGORITHM;
+ goto done;
+ }
+ }
if (pk12util.options[opt_Import].activated) {
P12U_ImportPKCS12Object(import_file, slot, &slotPw, &p12FilePw);
@@ -1139,7 +1183,7 @@ main(int argc, char **argv)
} else if (pk12util.options[opt_Export].activated) {
P12U_ExportPKCS12Object(pk12util.options[opt_Nickname].arg,
export_file, slot, cipher, certCipher,
- &slotPw, &p12FilePw);
+ hash, &slotPw, &p12FilePw);
} else if (pk12util.options[opt_List].activated) {
P12U_ListPKCS12File(import_file, slot, &slotPw, &p12FilePw);
diff --git a/cmd/pp/pp.c b/cmd/pp/pp.c
index d6e276834..b89b9ad0d 100644
--- a/cmd/pp/pp.c
+++ b/cmd/pp/pp.c
@@ -27,14 +27,13 @@ Usage(char *progName)
progName);
fprintf(stderr, "Pretty prints a file containing ASN.1 data in DER or ascii format.\n");
fprintf(stderr, "%-14s Specify input and display type:", "-t type");
-#ifdef HAVE_EPV_TEMPLATE
fprintf(stderr, " %s (sk),", SEC_CT_PRIVATE_KEY);
-#endif
fprintf(stderr, "\n");
fprintf(stderr, "%-14s %s (pk), %s (c), %s (cr),\n", "", SEC_CT_PUBLIC_KEY,
SEC_CT_CERTIFICATE, SEC_CT_CERTIFICATE_REQUEST);
- fprintf(stderr, "%-14s %s (ci), %s (p7), %s or %s (n).\n", "", SEC_CT_CERTIFICATE_ID,
- SEC_CT_PKCS7, SEC_CT_CRL, SEC_CT_NAME);
+ fprintf(stderr, "%-14s %s (ci), %s (p7), %s (p12), %s or %s (n).\n", "",
+ SEC_CT_CERTIFICATE_ID, SEC_CT_PKCS7, SEC_CT_PKCS12,
+ SEC_CT_CRL, SEC_CT_NAME);
fprintf(stderr, "%-14s (Use either the long type name or the shortcut.)\n", "");
fprintf(stderr, "%-14s Input is in ascii encoded form (RFC1113)\n",
"-a");
@@ -159,11 +158,9 @@ main(int argc, char **argv)
SECU_PrintCertificateRequest);
} else if (PORT_Strcmp(typeTag, SEC_CT_CRL) == 0) {
rv = SECU_PrintSignedData(outFile, &data, "CRL", 0, SECU_PrintCrl);
-#ifdef HAVE_EPV_TEMPLATE
} else if (PORT_Strcmp(typeTag, SEC_CT_PRIVATE_KEY) == 0 ||
PORT_Strcmp(typeTag, "sk") == 0) {
rv = SECU_PrintPrivateKey(outFile, &data, "Private Key", 0);
-#endif
} else if (PORT_Strcmp(typeTag, SEC_CT_PUBLIC_KEY) == 0 ||
PORT_Strcmp(typeTag, "pk") == 0) {
rv = SECU_PrintSubjectPublicKeyInfo(outFile, &data, "Public Key", 0);
@@ -174,6 +171,9 @@ main(int argc, char **argv)
} else if (PORT_Strcmp(typeTag, SEC_CT_NAME) == 0 ||
PORT_Strcmp(typeTag, "n") == 0) {
rv = SECU_PrintDERName(outFile, &data, "Name", 0);
+ } else if (PORT_Strcmp(typeTag, SEC_CT_PKCS12) == 0 ||
+ PORT_Strcmp(typeTag, "p12") == 0) {
+ rv = SECU_PrintPKCS12(outFile, &data, "PKCS #12 File", 0);
} else {
fprintf(stderr, "%s: don't know how to print out '%s' files\n",
progName, typeTag);