static void print_raw_certificates (FILE *out_file, SECItem **raw_certs, int level) { SECItem *raw_cert; int i = 0; char cert_label[50]; SECU_Indent (out_file, level); if (raw_certs == NULL) { fprintf (out_file, "No Certificates.\n"); return; } fprintf (out_file, "Certificate List:\n"); while ((raw_cert = raw_certs[i++]) != NULL) { sprintf (cert_label, "Certificate (%d)", i); (void) SECU_PrintSignedData (out_file, raw_cert, cert_label, level + 1, SECU_PrintCertificate); } }
int main(int argc, char **argv) { int rv, ascii; char *progName; FILE *outFile; PRFileDesc *inFile; SECItem der, data; char *typeTag; PLOptState *optstate; progName = strrchr(argv[0], '/'); progName = progName ? progName+1 : argv[0]; ascii = 0; inFile = 0; outFile = 0; typeTag = 0; optstate = PL_CreateOptState(argc, argv, "at:i:o:"); while ( PL_GetNextOpt(optstate) == PL_OPT_OK ) { switch (optstate->option) { case '?': Usage(progName); break; case 'a': ascii = 1; break; case 'i': inFile = PR_Open(optstate->value, PR_RDONLY, 0); if (!inFile) { fprintf(stderr, "%s: unable to open \"%s\" for reading\n", progName, optstate->value); return -1; } break; case 'o': outFile = fopen(optstate->value, "w"); if (!outFile) { fprintf(stderr, "%s: unable to open \"%s\" for writing\n", progName, optstate->value); return -1; } break; case 't': typeTag = strdup(optstate->value); break; } } PL_DestroyOptState(optstate); if (!typeTag) Usage(progName); if (!inFile) inFile = PR_STDIN; if (!outFile) outFile = stdout; PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); rv = NSS_NoDB_Init(NULL); if (rv != SECSuccess) { fprintf(stderr, "%s: NSS_NoDB_Init failed (%s)\n", progName, SECU_Strerror(PORT_GetError())); exit(1); } SECU_RegisterDynamicOids(); rv = SECU_ReadDERFromFile(&der, inFile, ascii, PR_FALSE); if (rv != SECSuccess) { fprintf(stderr, "%s: SECU_ReadDERFromFile failed\n", progName); exit(1); } /* Data is untyped, using the specified type */ data.data = der.data; data.len = der.len; /* Pretty print it */ if (PORT_Strcmp(typeTag, SEC_CT_CERTIFICATE) == 0) { rv = SECU_PrintSignedData(outFile, &data, "Certificate", 0, SECU_PrintCertificate); } else if (PORT_Strcmp(typeTag, SEC_CT_CERTIFICATE_ID) == 0) { PRBool saveWrapeState = SECU_GetWrapEnabled(); SECU_EnableWrap(PR_FALSE); rv = SECU_PrintSignedContent(outFile, &data, 0, 0, SECU_PrintDumpDerIssuerAndSerial); SECU_EnableWrap(saveWrapeState); } else if (PORT_Strcmp(typeTag, SEC_CT_CERTIFICATE_REQUEST) == 0) { rv = SECU_PrintSignedData(outFile, &data, "Certificate Request", 0, 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) { rv = SECU_PrintPrivateKey(outFile, &data, "Private Key", 0); #endif } else if (PORT_Strcmp(typeTag, SEC_CT_PUBLIC_KEY) == 0) { rv = SECU_PrintSubjectPublicKeyInfo(outFile, &data, "Public Key", 0); } else if (PORT_Strcmp(typeTag, SEC_CT_PKCS7) == 0) { rv = SECU_PrintPKCS7ContentInfo(outFile, &data, "PKCS #7 Content Info", 0); } else if (PORT_Strcmp(typeTag, SEC_CT_NAME) == 0) { rv = SECU_PrintDERName(outFile, &data, "Name", 0); } else { fprintf(stderr, "%s: don't know how to print out '%s' files\n", progName, typeTag); SECU_PrintAny(outFile, &data, "File contains", 0); return -1; } if (inFile != PR_STDIN) PR_Close(inFile); PORT_Free(der.data); if (rv) { fprintf(stderr, "%s: problem converting data (%s)\n", progName, SECU_Strerror(PORT_GetError())); } if (NSS_Shutdown() != SECSuccess) { fprintf(stderr, "%s: NSS_Shutdown failed (%s)\n", progName, SECU_Strerror(PORT_GetError())); rv = SECFailure; } PR_Cleanup(); return rv; }
/* ** secu_PrintPKCS7SignedEnveloped ** Pretty print a PKCS7 singed and enveloped data type (up to version 1). */ int secu_PrintPKCS7SignedAndEnveloped(FILE *out, SEC_PKCS7SignedAndEnvelopedData *src, char *m, int level) { SECAlgorithmID *digAlg; /* pointer for digest algorithms */ SECItem *aCert; /* pointer for certificate */ CERTSignedCrl *aCrl; /* pointer for certificate revocation list */ SEC_PKCS7SignerInfo *sigInfo; /* pointer for signer information */ SEC_PKCS7RecipientInfo *recInfo; /* pointer for recipient information */ int rv, iv; char om[100]; secu_Indent(out, level); fprintf(out, "%s:\n", m); sv_PrintInteger(out, &(src->version), "Version", level + 1); /* Parse and list recipients (this is not optional) */ if (src->recipientInfos != NULL) { secu_Indent(out, level + 1); fprintf(out, "Recipient Information List:\n"); iv = 0; while ((recInfo = src->recipientInfos[iv++]) != NULL) { sprintf(om, "Recipient Information (%x)", iv); secu_PrintRecipientInfo(out, recInfo, om, level + 2); } } /* Parse and list digest algorithms (if any) */ if (src->digestAlgorithms != NULL) { secu_Indent(out, level + 1); fprintf(out, "Digest Algorithm List:\n"); iv = 0; while ((digAlg = src->digestAlgorithms[iv++]) != NULL) { sprintf(om, "Digest Algorithm (%x)", iv); sv_PrintAlgorithmID(out, digAlg, om); } } secu_PrintPKCS7EncContent(out, &src->encContentInfo, "Encrypted Content Information", level + 1); /* Parse and list certificates (if any) */ if (src->rawCerts != NULL) { secu_Indent(out, level + 1); fprintf(out, "Certificate List:\n"); iv = 0; while ((aCert = src->rawCerts[iv++]) != NULL) { sprintf(om, "Certificate (%x)", iv); rv = SECU_PrintSignedData(out, aCert, om, level + 2, SECU_PrintCertificate); if (rv) return rv; } } /* Parse and list CRL's (if any) */ if (src->crls != NULL) { secu_Indent(out, level + 1); fprintf(out, "Signed Revocation Lists:\n"); iv = 0; while ((aCrl = src->crls[iv++]) != NULL) { sprintf(om, "Signed Revocation List (%x)", iv); secu_Indent(out, level + 2); fprintf(out, "%s:\n", om); sv_PrintAlgorithmID(out, &aCrl->signatureWrap.signatureAlgorithm, "Signature Algorithm"); DER_ConvertBitString(&aCrl->signatureWrap.signature); sv_PrintAsHex(out, &aCrl->signatureWrap.signature, "Signature", level+3); SECU_PrintCRLInfo(out, &aCrl->crl, "Certificate Revocation List", level + 3); } } /* Parse and list signatures (if any) */ if (src->signerInfos != NULL) { secu_Indent(out, level + 1); fprintf(out, "Signer Information List:\n"); iv = 0; while ((sigInfo = src->signerInfos[iv++]) != NULL) { sprintf(om, "Signer Information (%x)", iv); secu_PrintSignerInfo(out, sigInfo, om, level + 2); } } return 0; }
int main(int argc, char **argv) { int verbose=0, force=0; int ascii=0, issuerAscii=0; char *progName=0; PRFileDesc *inFile=0, *issuerCertFile=0; SECItem derCert, derIssuerCert; PLArenaPool *arena=0; CERTSignedData *signedData=0; CERTCertificate *cert=0, *issuerCert=0; SECKEYPublicKey *rsapubkey=0; SECAlgorithmID md5WithRSAEncryption, md2WithRSAEncryption; SECAlgorithmID sha1WithRSAEncryption, rsaEncryption; SECItem spk; int selfSigned=0; int invalid=0; char *inFileName = NULL, *issuerCertFileName = NULL; PLOptState *optstate; PLOptStatus status; SECStatus rv; PORT_Memset(&md5WithRSAEncryption, 0, sizeof(md5WithRSAEncryption)); PORT_Memset(&md2WithRSAEncryption, 0, sizeof(md2WithRSAEncryption)); PORT_Memset(&sha1WithRSAEncryption, 0, sizeof(sha1WithRSAEncryption)); PORT_Memset(&rsaEncryption, 0, sizeof(rsaEncryption)); progName = strrchr(argv[0], '/'); progName = progName ? progName+1 : argv[0]; optstate = PL_CreateOptState(argc, argv, "aAvf"); while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { switch (optstate->option) { case 'v': verbose = 1; break; case 'f': force = 1; break; case 'a': ascii = 1; break; case 'A': issuerAscii = 1; break; case '\0': if (!inFileName) inFileName = PL_strdup(optstate->value); else if (!issuerCertFileName) issuerCertFileName = PL_strdup(optstate->value); else Usage(progName); break; } } if (!inFileName || !issuerCertFileName || status == PL_OPT_BAD) { /* insufficient or excess args */ Usage(progName); } inFile = PR_Open(inFileName, PR_RDONLY, 0); if (!inFile) { fprintf(stderr, "%s: unable to open \"%s\" for reading\n", progName, inFileName); exit(1); } issuerCertFile = PR_Open(issuerCertFileName, PR_RDONLY, 0); if (!issuerCertFile) { fprintf(stderr, "%s: unable to open \"%s\" for reading\n", progName, issuerCertFileName); exit(1); } if (SECU_ReadDERFromFile(&derCert, inFile, ascii, PR_FALSE) != SECSuccess) { printf("Couldn't read input certificate as DER binary or base64\n"); exit(1); } arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (arena == 0) { fprintf(stderr,"%s: can't allocate scratch arena!", progName); exit(1); } if (issuerCertFile) { CERTSignedData *issuerCertSD=0; if (SECU_ReadDERFromFile(&derIssuerCert, issuerCertFile, issuerAscii, PR_FALSE) != SECSuccess) { printf("Couldn't read issuer certificate as DER binary or base64.\n"); exit(1); } issuerCertSD = PORT_ArenaZNew(arena, CERTSignedData); if (!issuerCertSD) { fprintf(stderr,"%s: can't allocate issuer signed data!", progName); exit(1); } rv = SEC_ASN1DecodeItem(arena, issuerCertSD, SEC_ASN1_GET(CERT_SignedDataTemplate), &derIssuerCert); if (rv) { fprintf(stderr, "%s: Issuer cert isn't X509 SIGNED Data?\n", progName); exit(1); } issuerCert = createEmptyCertificate(); if (!issuerCert) { printf("%s: can't allocate space for issuer cert.", progName); exit(1); } rv = SEC_ASN1DecodeItem(arena, issuerCert, SEC_ASN1_GET(CERT_CertificateTemplate), &issuerCertSD->data); if (rv) { printf("%s: Does not appear to be an X509 Certificate.\n", progName); exit(1); } } signedData = PORT_ArenaZNew(arena,CERTSignedData); if (!signedData) { fprintf(stderr,"%s: can't allocate signedData!", progName); exit(1); } rv = SEC_ASN1DecodeItem(arena, signedData, SEC_ASN1_GET(CERT_SignedDataTemplate), &derCert); if (rv) { fprintf(stderr, "%s: Does not appear to be X509 SIGNED Data.\n", progName); exit(1); } if (verbose) { printf("Decoded ok as X509 SIGNED data.\n"); } cert = createEmptyCertificate(); if (!cert) { fprintf(stderr, "%s: can't allocate cert", progName); exit(1); } rv = SEC_ASN1DecodeItem(arena, cert, SEC_ASN1_GET(CERT_CertificateTemplate), &signedData->data); if (rv) { fprintf(stderr, "%s: Does not appear to be an X509 Certificate.\n", progName); exit(1); } if (verbose) { printf("Decoded ok as an X509 certificate.\n"); } SECU_RegisterDynamicOids(); rv = SECU_PrintSignedData(stdout, &derCert, "Certificate", 0, (SECU_PPFunc)SECU_PrintCertificate); if (rv) { fprintf(stderr, "%s: Unable to pretty print cert. Error: %d\n", progName, PORT_GetError()); if (!force) { exit(1); } } /* Do various checks on the cert */ printf("\n"); /* Check algorithms */ rv = SECOID_SetAlgorithmID(arena, &md5WithRSAEncryption, SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION, NULL); if (rv) { fprintf(stderr, "%s: failed to set algorithm ID for SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION.\n", progName); exit(1); } rv = SECOID_SetAlgorithmID(arena, &md2WithRSAEncryption, SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION, NULL); if (rv) { fprintf(stderr, "%s: failed to set algorithm ID for SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION.\n", progName); exit(1); } rv = SECOID_SetAlgorithmID(arena, &sha1WithRSAEncryption, SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION, NULL); if (rv) { fprintf(stderr, "%s: failed to set algorithm ID for SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION.\n", progName); exit(1); } rv = SECOID_SetAlgorithmID(arena, &rsaEncryption, SEC_OID_PKCS1_RSA_ENCRYPTION, NULL); if (rv) { fprintf(stderr, "%s: failed to set algorithm ID for SEC_OID_PKCS1_RSA_ENCRYPTION.\n", progName); exit(1); } { int isMD5RSA = (SECOID_CompareAlgorithmID(&cert->signature, &md5WithRSAEncryption) == 0); int isMD2RSA = (SECOID_CompareAlgorithmID(&cert->signature, &md2WithRSAEncryption) == 0); int isSHA1RSA = (SECOID_CompareAlgorithmID(&cert->signature, &sha1WithRSAEncryption) == 0); if (verbose) { printf("\nDoing algorithm checks.\n"); } if (!(isMD5RSA || isMD2RSA || isSHA1RSA)) { printf("PROBLEM: Signature not PKCS1 MD5, MD2, or SHA1 + RSA.\n"); } else if (!isMD5RSA) { printf("WARNING: Signature not PKCS1 MD5 with RSA Encryption\n"); } if (SECOID_CompareAlgorithmID(&cert->signature, &signedData->signatureAlgorithm)) { printf("PROBLEM: Algorithm in sig and certInfo don't match.\n"); } } if (SECOID_CompareAlgorithmID(&cert->subjectPublicKeyInfo.algorithm, &rsaEncryption)) { printf("PROBLEM: Public key algorithm is not PKCS1 RSA Encryption.\n"); } /* Check further public key properties */ spk = cert->subjectPublicKeyInfo.subjectPublicKey; DER_ConvertBitString(&spk); if (verbose) { printf("\nsubjectPublicKey DER\n"); rv = DER_PrettyPrint(stdout, &spk, PR_FALSE); printf("\n"); } rsapubkey = (SECKEYPublicKey *) PORT_ArenaZAlloc(arena,sizeof(SECKEYPublicKey)); if (!rsapubkey) { fprintf(stderr, "%s: rsapubkey allocation failed.\n", progName); exit(1); } rv = SEC_ASN1DecodeItem(arena, rsapubkey, SEC_ASN1_GET(SECKEY_RSAPublicKeyTemplate), &spk); if (rv) { printf("PROBLEM: subjectPublicKey is not a DER PKCS1 RSAPublicKey.\n"); } else { int mlen; int pubexp; if (verbose) { printf("Decoded RSA Public Key ok. Doing key checks.\n"); } PORT_Assert(rsapubkey->keyType == rsaKey); /* XXX RSA */ mlen = checkInteger(&rsapubkey->u.rsa.modulus, "Modulus", verbose); printf("INFO: Public Key modulus length in bits: %d\n", mlen); if (mlen > MAX_MODULUS) { printf("PROBLEM: Modulus length exceeds %d bits.\n", MAX_MODULUS); } if (mlen < 512) { printf("WARNING: Short modulus.\n"); } if (mlen != (1 << (ffs(mlen)-1))) { printf("WARNING: Unusual modulus length (not a power of two).\n"); } checkInteger(&rsapubkey->u.rsa.publicExponent, "Public Exponent", verbose); pubexp = DER_GetInteger(&rsapubkey->u.rsa.publicExponent); if (pubexp != 17 && pubexp != 3 && pubexp != 65537) { printf("WARNING: Public exponent not any of: 3, 17, 65537\n"); } } /* Name checks */ checkName(&cert->issuer, "Issuer Name", verbose); checkName(&cert->subject, "Subject Name", verbose); if (issuerCert) { SECComparison c = CERT_CompareName(&cert->issuer, &issuerCert->subject); if (c) { printf("PROBLEM: Issuer Name and Subject in Issuing Cert differ\n"); } } /* Check if self-signed */ selfSigned = (CERT_CompareName(&cert->issuer, &cert->subject) == 0); if (selfSigned) { printf("INFO: Certificate is self signed.\n"); } else { printf("INFO: Certificate is NOT self-signed.\n"); } /* Validity time check */ if (CERT_CertTimesValid(cert) == SECSuccess) { printf("INFO: Inside validity period of certificate.\n"); } else { printf("PROBLEM: Not in validity period of certificate.\n"); invalid = 1; } /* Signature check if self-signed */ if (selfSigned && !invalid) { if (rsapubkey->u.rsa.modulus.len) { SECStatus ver; if (verbose) { printf("Checking self signature.\n"); } ver = OurVerifySignedData(signedData, cert); if (ver != SECSuccess) { printf("PROBLEM: Verification of self-signature failed!\n"); } else { printf("INFO: Self-signature verifies ok.\n"); } } else { printf("INFO: Not checking signature due to key problems.\n"); } } else if (!selfSigned && !invalid && issuerCert) { SECStatus ver; ver = OurVerifySignedData(signedData, issuerCert); if (ver != SECSuccess) { printf("PROBLEM: Verification of issuer's signature failed!\n"); } else { printf("INFO: Issuer's signature verifies ok.\n"); } } else { printf("INFO: Not checking signature.\n"); } return 0; }