CERTCertificate* find_certificate(CERTCertDBHandle *handle, const char *name, PRBool ascii) { CERTCertificate *cert = NULL; SECItem der; PRFileDesc *certFile; if (handle == NULL || name == NULL) return NULL; if (ascii == PR_FALSE) { /* by default need to check if there is cert nick is given */ cert = CERT_FindCertByNicknameOrEmailAddr (handle, (char *) name); if (cert != NULL) return cert; } certFile = PR_Open(name, PR_RDONLY, 0); if (certFile == NULL) { return NULL; } if (SECU_ReadDERFromFile(&der, certFile, ascii, PR_FALSE) == SECSuccess) { cert = CERT_DecodeCertFromPackage((char*)der.data, der.len); SECITEM_FreeItem(&der, PR_FALSE); } PR_Close(certFile); return cert; }
SECStatus DumpCRL(PRFileDesc *inFile) { int rv; PLArenaPool *arena = NULL; CERTSignedCrl *newCrl = NULL; SECItem crlDER; crlDER.data = NULL; /* Read in the entire file specified with the -f argument */ rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE, PR_FALSE); if (rv != SECSuccess) { SECU_PrintError(progName, "unable to read input file"); return (SECFailure); } rv = SEC_ERROR_NO_MEMORY; arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (!arena) return rv; newCrl = CERT_DecodeDERCrlWithFlags(arena, &crlDER, SEC_CRL_TYPE, CRL_DECODE_DEFAULT_OPTIONS); if (!newCrl) return SECFailure; SECU_PrintCRLInfo (stdout, &newCrl->crl, "CRL file contents", 0); PORT_FreeArena (arena, PR_FALSE); return rv; }
static PKIX_PL_Cert * createCert(char *inFileName) { PKIX_PL_ByteArray *byteArray = NULL; void *buf = NULL; PRFileDesc *inFile = NULL; PKIX_UInt32 len; SECItem certDER; SECStatus rv; /* default: NULL cert (failure case) */ PKIX_PL_Cert *cert = NULL; PKIX_TEST_STD_VARS(); certDER.data = NULL; inFile = PR_Open(inFileName, PR_RDONLY, 0); if (!inFile){ pkixTestErrorMsg = "Unable to open cert file"; goto cleanup; } else { rv = SECU_ReadDERFromFile(&certDER, inFile, PR_FALSE); if (!rv){ buf = (void *)certDER.data; len = certDER.len; PKIX_TEST_EXPECT_NO_ERROR (PKIX_PL_ByteArray_Create (buf, len, &byteArray, plContext)); PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_Create (byteArray, &cert, plContext)); SECITEM_FreeItem(&certDER, PR_FALSE); } else { pkixTestErrorMsg = "Unable to read DER from cert file"; goto cleanup; } } cleanup: if (inFile){ PR_Close(inFile); } if (PKIX_TEST_ERROR_RECEIVED){ SECITEM_FreeItem(&certDER, PR_FALSE); } PKIX_TEST_DECREF_AC(byteArray); PKIX_TEST_RETURN(); return (cert); }
SECStatus ImportCRL (CERTCertDBHandle *certHandle, char *url, int type, PRFileDesc *inFile, PRInt32 importOptions, PRInt32 decodeOptions) { CERTSignedCrl *crl = NULL; SECItem crlDER; PK11SlotInfo* slot = NULL; int rv; #if defined(DEBUG_jp96085) PRIntervalTime starttime, endtime, elapsed; PRUint32 mins, secs, msecs; #endif crlDER.data = NULL; /* Read in the entire file specified with the -f argument */ rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE); if (rv != SECSuccess) { SECU_PrintError(progName, "unable to read input file"); return (SECFailure); } decodeOptions |= CRL_DECODE_DONT_COPY_DER; slot = PK11_GetInternalKeySlot(); #if defined(DEBUG_jp96085) starttime = PR_IntervalNow(); #endif crl = PK11_ImportCRL(slot, &crlDER, url, type, NULL, importOptions, NULL, decodeOptions); #if defined(DEBUG_jp96085) endtime = PR_IntervalNow(); elapsed = endtime - starttime; mins = PR_IntervalToSeconds(elapsed) / 60; secs = PR_IntervalToSeconds(elapsed) % 60; msecs = PR_IntervalToMilliseconds(elapsed) % 1000; printf("Elapsed : %2d:%2d.%3d\n", mins, secs, msecs); #endif if (!crl) { const char *errString; rv = SECFailure; errString = SECU_Strerror(PORT_GetError()); if ( errString && PORT_Strlen (errString) == 0) SECU_PrintError (progName, "CRL is not imported (error: input CRL is not up to date.)"); else SECU_PrintError (progName, "unable to import CRL"); } else { SEC_DestroyCrl (crl); } if (slot) { PK11_FreeSlot(slot); } return (rv); }
static int SignFile(FILE *outFile, PRFileDesc *inFile, CERTCertificate *cert, PRBool encapsulated) { char digestdata[32]; unsigned int len; SECItem digest, data2sign; SEC_PKCS7ContentInfo *cinfo; SECStatus rv; if (outFile == NULL || inFile == NULL || cert == NULL) return -1; /* suck the file in */ if (SECU_ReadDERFromFile(&data2sign, inFile, PR_FALSE) != SECSuccess) return -1; if (!encapsulated) { /* unfortunately, we must create the digest ourselves */ /* SEC_PKCS7CreateSignedData should have a flag to not include */ /* the content for non-encapsulated content at encode time, but */ /* should always compute the hash itself */ if (CreateDigest(&data2sign, digestdata, &len, 32) < 0) return -1; digest.data = (unsigned char *)digestdata; digest.len = len; } /* XXX Need a better way to handle that usage stuff! */ cinfo = SEC_PKCS7CreateSignedData (cert, certUsageEmailSigner, NULL, SEC_OID_SHA1, encapsulated ? NULL : &digest, NULL, NULL); if (cinfo == NULL) return -1; if (encapsulated) { SEC_PKCS7SetContent(cinfo, (char *)data2sign.data, data2sign.len); } rv = SEC_PKCS7IncludeCertChain (cinfo, NULL); if (rv != SECSuccess) { SEC_PKCS7DestroyContentInfo (cinfo); return -1; } rv = SEC_PKCS7Encode (cinfo, SignOut, outFile, NULL, NULL, &pwdata); SEC_PKCS7DestroyContentInfo (cinfo); if (rv != SECSuccess) return -1; return 0; }
int main(int argc, char **argv) { if (NSS_NoDB_Init(NULL) != SECSuccess) { printf(" >>> NSS_NoDB_Init() failed.\n"); return 1; } if (argc < 3) { printf(" >>> I need a DER encoded file to read and have to know what to do with it [decode, private]!\n"); return 1; } PRFileDesc* file = PR_Open(argv[1], PR_RDONLY, 0); SECItem data = {0, NULL, 0}; if (SECU_ReadDERFromFile(&data, file, PR_FALSE, PR_FALSE) != SECSuccess) { printf(" >>> SECU_ReadDERFromFile() failed.\n"); return 1; } PR_Close(file); if (strcmp(argv[2], "decode") == 0) { CERTCertificate *cert = CERT_DecodeCertFromPackage((char*)data.data, data.len); if (cert){ printf(" >>> read cert!\n"); printf(" >>> SN: %s\n", cert->subjectName); printf(" >>> IN: %s\n", cert->issuerName); CERT_DestroyCertificate(cert); } else { printf(" >>> CERT_DecodeCertFromPackage failed.\n"); SECITEM_FreeItem(&data, PR_FALSE); return 1; } } if (argv[2] == "private") { PK11SlotInfo* slot = PK11_GetInternalSlot(); if (!slot) { printf(" >>> PK11_GetInternalSlot() failed.\n"); SECITEM_FreeItem(&data, PR_FALSE); return 1; } SECKEYPrivateKey* privKey; if (PK11_ImportDERPrivateKeyInfoAndReturnKey(slot, &data, NULL, NULL, PR_FALSE, PR_FALSE, KU_ALL, &privKey, NULL) != SECSuccess) { printf(" >>> PK11_ImportDERPrivateKeyInfoAndReturnKey() failed.\n"); SECITEM_FreeItem(&data, PR_FALSE); return 1; } } printf(" !!! Done.\n"); return 0; }
static int HashDecodeAndVerify(FILE *out, FILE *content, PRFileDesc *signature, SECCertUsage usage, char *progName) { SECItem derdata; SEC_PKCS7ContentInfo *cinfo; SEC_PKCS7SignedData *signedData; HASH_HashType digestType; SECItem digest; unsigned char buffer[32]; if (SECU_ReadDERFromFile(&derdata, signature, PR_FALSE) != SECSuccess) { SECU_PrintError(progName, "error reading signature file"); return -1; } cinfo = SEC_PKCS7DecodeItem(&derdata, NULL, NULL, NULL, NULL, NULL, NULL, NULL); if (cinfo == NULL) return -1; if (! SEC_PKCS7ContentIsSigned(cinfo)) { fprintf (out, "Signature file is pkcs7 data, but not signed.\n"); return -1; } signedData = cinfo->content.signedData; /* assume that there is only one digest algorithm for now */ digestType = AlgorithmToHashType(signedData->digestAlgorithms[0]); if (digestType == HASH_AlgNULL) { fprintf (out, "Invalid hash algorithmID\n"); return -1; } digest.data = buffer; if (DigestFile (digest.data, &digest.len, 32, content, digestType)) { SECU_PrintError (progName, "problem computing message digest"); return -1; } fprintf(out, "Signature is "); if (SEC_PKCS7VerifyDetachedSignature (cinfo, usage, &digest, digestType, PR_FALSE)) fprintf(out, "valid.\n"); else fprintf(out, "invalid (Reason: %s).\n", SECU_Strerror(PORT_GetError())); SEC_PKCS7DestroyContentInfo(cinfo); return 0; }
CERTCertificate * getCert(const char *name, PRBool isAscii, const char * progName) { CERTCertificate * cert; CERTCertDBHandle *defaultDB; PRFileDesc* fd; SECStatus rv; SECItem item = {0, NULL, 0}; defaultDB = CERT_GetDefaultCertDB(); /* First, let's try to find the cert in existing DB. */ cert = CERT_FindCertByNicknameOrEmailAddr(defaultDB, name); if (cert) { return cert; } /* Don't have a cert with name "name" in the DB. Try to * open a file with such name and get the cert from there.*/ fd = PR_Open(name, PR_RDONLY, 0777); if (!fd) { PRIntn err = PR_GetError(); fprintf(stderr, "open of %s failed, %d = %s\n", name, err, SECU_Strerror(err)); return cert; } rv = SECU_ReadDERFromFile(&item, fd, isAscii); PR_Close(fd); if (rv != SECSuccess) { fprintf(stderr, "%s: SECU_ReadDERFromFile failed\n", progName); return cert; } if (!item.len) { /* file was empty */ fprintf(stderr, "cert file %s was empty.\n", name); return cert; } cert = CERT_NewTempCertificate(defaultDB, &item, NULL /* nickname */, PR_FALSE /* isPerm */, PR_TRUE /* copyDER */); if (!cert) { PRIntn err = PR_GetError(); fprintf(stderr, "couldn't import %s, %d = %s\n", name, err, SECU_Strerror(err)); } PORT_Free(item.data); return cert; }
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; }
static CERTSignedCrl* CreateModifiedCRLCopy(PLArenaPool *arena, CERTCertDBHandle *certHandle, CERTCertificate **cert, char *certNickName, PRFileDesc *inFile, PRInt32 decodeOptions, PRInt32 importOptions) { SECItem crlDER = {0, NULL, 0}; CERTSignedCrl *signCrl = NULL; CERTSignedCrl *modCrl = NULL; PLArenaPool *modArena = NULL; SECStatus rv = SECSuccess; if (!arena || !certHandle || !certNickName) { PORT_SetError(SEC_ERROR_INVALID_ARGS); SECU_PrintError(progName, "CreateModifiedCRLCopy: invalid args\n"); return NULL; } modArena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); if (!modArena) { SECU_PrintError(progName, "fail to allocate memory\n"); return NULL; } if (inFile != NULL) { rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE, PR_FALSE); if (rv != SECSuccess) { SECU_PrintError(progName, "unable to read input file"); PORT_FreeArena(modArena, PR_FALSE); goto loser; } decodeOptions |= CRL_DECODE_DONT_COPY_DER; modCrl = CERT_DecodeDERCrlWithFlags(modArena, &crlDER, SEC_CRL_TYPE, decodeOptions); if (!modCrl) { SECU_PrintError(progName, "fail to decode CRL"); goto loser; } if (0 == (importOptions & CRL_IMPORT_BYPASS_CHECKS)){ /* If caCert is a v2 certificate, make sure that it * can be used for crl signing purpose */ *cert = FindSigningCert(certHandle, modCrl, NULL); if (!*cert) { goto loser; } rv = CERT_VerifySignedData(&modCrl->signatureWrap, *cert, PR_Now(), NULL); if (rv != SECSuccess) { SECU_PrintError(progName, "fail to verify signed data\n"); goto loser; } } } else { modCrl = FindCRL(certHandle, certNickName, SEC_CRL_TYPE); if (!modCrl) { SECU_PrintError(progName, "fail to find crl %s in database\n", certNickName); goto loser; } } signCrl = PORT_ArenaZNew(arena, CERTSignedCrl); if (signCrl == NULL) { SECU_PrintError(progName, "fail to allocate memory\n"); goto loser; } rv = SECU_CopyCRL(arena, &signCrl->crl, &modCrl->crl); if (rv != SECSuccess) { SECU_PrintError(progName, "unable to dublicate crl for " "modification."); goto loser; } /* Make sure the update time is current. It can be modified later * by "update <time>" command from crl generation script */ rv = DER_EncodeTimeChoice(arena, &signCrl->crl.lastUpdate, PR_Now()); if (rv != SECSuccess) { SECU_PrintError(progName, "fail to encode current time\n"); goto loser; } signCrl->arena = arena; loser: if (crlDER.data) { SECITEM_FreeItem(&crlDER, PR_FALSE); } if (modCrl) SEC_DestroyCrl(modCrl); if (rv != SECSuccess && signCrl) { SEC_DestroyCrl(signCrl); signCrl = NULL; } return signCrl; }
/* * FUNCTION: pkix_pl_CollectionCertStoreContext_CreateCRL * DESCRIPTION: * * Creates CRL using data file path name pointed to by "crlFileName" and * stores it at "pCrl". If the CRL can not be decoded, NULL is stored * at "pCrl". * * PARAMETERS * "crlFileName" - Address of CRL data file path name. Must be non-NULL. * "pCrl" - Address where object pointer will be stored. Must be non-NULL. * "plContext" - Platform-specific context pointer. * THREAD SAFETY: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) * RETURNS: * Returns NULL if the function succeeds. * Returns a CollectionCertStoreContext Error if the function fails in * a non-fatal way. * Returns a Fatal Error if the function fails in an unrecoverable way. */ static PKIX_Error * pkix_pl_CollectionCertStoreContext_CreateCRL( const char *crlFileName, PKIX_PL_CRL **pCrl, void *plContext) { PKIX_PL_ByteArray *byteArray = NULL; PKIX_PL_CRL *crl = NULL; PRFileDesc *inFile = NULL; SECItem crlDER; void *buf = NULL; PKIX_UInt32 len; SECStatus rv; PKIX_ENTER(COLLECTIONCERTSTORECONTEXT, "pkix_pl_CollectionCertStoreContext_CreateCRL"); PKIX_NULLCHECK_TWO(crlFileName, pCrl); *pCrl = NULL; crlDER.data = NULL; PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG("\t\t Calling PR_Open.\n"); inFile = PR_Open(crlFileName, PR_RDONLY, 0); if (!inFile){ PKIX_ERROR(PKIX_UNABLETOOPENCRLFILE); } else { PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG ("\t\t Calling SECU_ReadDerFromFile.\n"); rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE); if (!rv){ buf = (void *)crlDER.data; len = crlDER.len; PKIX_CHECK(PKIX_PL_ByteArray_Create (buf, len, &byteArray, plContext), PKIX_BYTEARRAYCREATEFAILED); PKIX_CHECK(PKIX_PL_CRL_Create (byteArray, &crl, plContext), PKIX_CRLCREATEFAILED); PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG ("\t\t Calling SECITEM_FreeItem.\n"); SECITEM_FreeItem(&crlDER, PR_FALSE); } else { PKIX_ERROR(PKIX_UNABLETOREADDERFROMCRLFILE); } } *pCrl = crl; cleanup: if (inFile){ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG ("\t\t Calling PR_CloseDir.\n"); PR_Close(inFile); } if (PKIX_ERROR_RECEIVED){ PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG ("\t\t Calling SECITEM_FreeItem).\n"); SECITEM_FreeItem(&crlDER, PR_FALSE); PKIX_DECREF(crl); if (crlDER.data != NULL) { SECITEM_FreeItem(&crlDER, PR_FALSE); } } PKIX_DECREF(byteArray); PKIX_RETURN(COLLECTIONCERTSTORECONTEXT); }
static int SignFile(FILE *outFile, PRFileDesc *inFile, CERTCertificate *cert) { SECItem data2sign; SECStatus rv; char *data; SECKEYPrivateKey *privKey; SECOidTag algID; PLArenaPool *arena; CERTSignedData sd; SECItem *result; if (outFile == NULL || inFile == NULL || cert == NULL) return -1; /* suck the file in */ if (SECU_ReadDERFromFile(&data2sign, inFile, PR_FALSE, PR_FALSE) != SECSuccess) return -1; privKey = NULL; privKey = PK11_FindKeyByAnyCert(cert, NULL); algID = SEC_GetSignatureAlgorithmOidTag(privKey->keyType, SEC_OID_SHA1); if (algID == SEC_OID_UNKNOWN) return -1; arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); PORT_Memset(&sd, 0, sizeof(CERTSignedData)); rv = SEC_SignData(&(sd.signature), data2sign.data, data2sign.len, privKey, algID); if (rv != SECSuccess) { fprintf (stderr, "Could not sign.\n"); return -1; } sd.signature.len = sd.signature.len << 3; rv = SECOID_SetAlgorithmID(arena, &sd.signatureAlgorithm, algID, 0); if (rv != SECSuccess) { fprintf (stderr, "Could not set alg id.\n"); return -1; } result = SEC_ASN1EncodeItem(arena, NULL, &sd, CERTSignatureDataTemplate); SECITEM_FreeItem(&(sd.signature), PR_FALSE); if (!result) { fprintf (stderr, "Could not encode.\n"); return -1; } data = PL_Base64Encode((const char*)result->data, result->len, NULL); if (!data) return -1; fputs("signature:\n", outFile); fputs(data, outFile); fputs("\n", outFile); ExportPublicKey(outFile, cert); SECKEY_DestroyPrivateKey(privKey); PORT_FreeArena(arena, PR_FALSE); return 0; }
int main(int argc, char **argv) { PRFileDesc *contentFile = NULL; PRFileDesc *signFile = PR_STDIN; FILE * outFile = stdout; char * progName; SECStatus rv; int result = 1; SECItem pkcs7der, content; secuCommand signver; pkcs7der.data = NULL; content.data = NULL; signver.numCommands = sizeof(signver_commands) /sizeof(secuCommandFlag); signver.numOptions = sizeof(signver_options) / sizeof(secuCommandFlag); signver.commands = signver_commands; signver.options = signver_options; #ifdef XP_PC progName = strrchr(argv[0], '\\'); #else progName = strrchr(argv[0], '/'); #endif progName = progName ? progName+1 : argv[0]; rv = SECU_ParseCommandLine(argc, argv, progName, &signver); if (SECSuccess != rv) { Usage(progName, outFile); } debugInfo = signver.options[opt_DebugInfo ].activated; verbose = signver.options[opt_PrintWhyFailure ].activated; doVerify = signver.commands[cmd_VerifySignedObj].activated; displayAll= signver.commands[cmd_DisplayAllPCKS7Info].activated; if (!doVerify && !displayAll) doVerify = PR_TRUE; /* Set the certdb directory (default is ~/.netscape) */ rv = NSS_Init(SECU_ConfigDirectory(signver.options[opt_CertDir].arg)); if (rv != SECSuccess) { SECU_PrintPRandOSError(progName); return result; } /* below here, goto cleanup */ SECU_RegisterDynamicOids(); /* Open the input content file. */ if (signver.options[opt_InputDataFile].activated && signver.options[opt_InputDataFile].arg) { if (PL_strcmp("-", signver.options[opt_InputDataFile].arg)) { contentFile = PR_Open(signver.options[opt_InputDataFile].arg, PR_RDONLY, 0); if (!contentFile) { PR_fprintf(PR_STDERR, "%s: unable to open \"%s\" for reading.\n", progName, signver.options[opt_InputDataFile].arg); goto cleanup; } } else contentFile = PR_STDIN; } /* Open the input signature file. */ if (signver.options[opt_InputSigFile].activated && signver.options[opt_InputSigFile].arg) { if (PL_strcmp("-", signver.options[opt_InputSigFile].arg)) { signFile = PR_Open(signver.options[opt_InputSigFile].arg, PR_RDONLY, 0); if (!signFile) { PR_fprintf(PR_STDERR, "%s: unable to open \"%s\" for reading.\n", progName, signver.options[opt_InputSigFile].arg); goto cleanup; } } } if (contentFile == PR_STDIN && signFile == PR_STDIN && doVerify) { PR_fprintf(PR_STDERR, "%s: cannot read both content and signature from standard input\n", progName); goto cleanup; } /* Open|Create the output file. */ if (signver.options[opt_OutputFile].activated) { outFile = fopen(signver.options[opt_OutputFile].arg, "w"); if (!outFile) { PR_fprintf(PR_STDERR, "%s: unable to open \"%s\" for writing.\n", progName, signver.options[opt_OutputFile].arg); goto cleanup; } } /* read in the input files' contents */ rv = SECU_ReadDERFromFile(&pkcs7der, signFile, signver.options[opt_ASCII].activated); if (signFile != PR_STDIN) PR_Close(signFile); if (rv != SECSuccess) { SECU_PrintError(progName, "problem reading PKCS7 input"); goto cleanup; } if (contentFile) { rv = SECU_FileToItem(&content, contentFile); if (contentFile != PR_STDIN) PR_Close(contentFile); if (rv != SECSuccess) content.data = NULL; } /* Signature Verification */ if (doVerify) { SEC_PKCS7ContentInfo *cinfo; SEC_PKCS7SignedData *signedData; HASH_HashType digestType; PRBool contentIsSigned; cinfo = SEC_PKCS7DecodeItem(&pkcs7der, NULL, NULL, NULL, NULL, NULL, NULL, NULL); if (cinfo == NULL) { PR_fprintf(PR_STDERR, "Unable to decode PKCS7 data\n"); goto cleanup; } /* below here, goto done */ contentIsSigned = SEC_PKCS7ContentIsSigned(cinfo); if (debugInfo) { PR_fprintf(PR_STDERR, "Content is%s encrypted.\n", SEC_PKCS7ContentIsEncrypted(cinfo) ? "" : " not"); } if (debugInfo || !contentIsSigned) { PR_fprintf(PR_STDERR, "Content is%s signed.\n", contentIsSigned ? "" : " not"); } if (!contentIsSigned) goto done; signedData = cinfo->content.signedData; /* assume that there is only one digest algorithm for now */ digestType = AlgorithmToHashType(signedData->digestAlgorithms[0]); if (digestType == HASH_AlgNULL) { PR_fprintf(PR_STDERR, "Invalid hash algorithmID\n"); goto done; } if (content.data) { SECCertUsage usage = certUsageEmailSigner; SECItem digest; unsigned char digestBuffer[HASH_LENGTH_MAX]; if (debugInfo) PR_fprintf(PR_STDERR, "contentToVerify=%s\n", content.data); digest.data = digestBuffer; digest.len = sizeof digestBuffer; if (DigestContent(&digest, &content, digestType)) { SECU_PrintError(progName, "Message digest computation failure"); goto done; } if (debugInfo) { unsigned int i; PR_fprintf(PR_STDERR, "Data Digest=:"); for (i = 0; i < digest.len; i++) PR_fprintf(PR_STDERR, "%02x:", digest.data[i]); PR_fprintf(PR_STDERR, "\n"); } fprintf(outFile, "signatureValid="); PORT_SetError(0); if (SEC_PKCS7VerifyDetachedSignature (cinfo, usage, &digest, digestType, PR_FALSE)) { fprintf(outFile, "yes"); } else { fprintf(outFile, "no"); if (verbose) { fprintf(outFile, ":%s", SECU_Strerror(PORT_GetError())); } } fprintf(outFile, "\n"); result = 0; } done: SEC_PKCS7DestroyContentInfo(cinfo); } if (displayAll) { if (SV_PrintPKCS7ContentInfo(outFile, &pkcs7der)) result = 1; } cleanup: SECITEM_FreeItem(&pkcs7der, PR_FALSE); SECITEM_FreeItem(&content, PR_FALSE); if (NSS_Shutdown() != SECSuccess) { result = 1; } return result; }
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; }
PKIX_PL_CRL * createCRL( char *dirName, char *crlFileName, void *plContext) { PKIX_PL_ByteArray *byteArray = NULL; PKIX_PL_CRL *crl = NULL; PKIX_Error *error = NULL; PRFileDesc *inFile = NULL; SECItem crlDER; void *buf = NULL; PKIX_UInt32 len; SECStatus rv; char *pathName = NULL; PKIX_TEST_STD_VARS(); crlDER.data = NULL; pathName = catDirName(dirName, crlFileName, plContext); inFile = PR_Open(pathName, PR_RDONLY, 0); if (!inFile){ pkixTestErrorMsg = "Unable to open crl file"; goto cleanup; } else { rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE); if (!rv){ buf = (void *)crlDER.data; len = crlDER.len; error = PKIX_PL_ByteArray_Create (buf, len, &byteArray, plContext); if (error){ pkixTestErrorMsg = "PKIX_PL_ByteArray_Create failed"; goto cleanup; } error = PKIX_PL_CRL_Create(byteArray, &crl, plContext); if (error){ pkixTestErrorMsg = "PKIX_PL_Crl_Create failed"; goto cleanup; } SECITEM_FreeItem(&crlDER, PR_FALSE); } else { pkixTestErrorMsg = "Unable to read DER from crl file"; goto cleanup; } } cleanup: PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(pathName, plContext)); if (inFile){ PR_Close(inFile); } if (error){ SECITEM_FreeItem(&crlDER, PR_FALSE); } PKIX_TEST_DECREF_AC(byteArray); PKIX_TEST_RETURN(); return (crl); }
static PKIX_PL_Cert * createCert(char *inFileName) { PKIX_PL_ByteArray *byteArray = NULL; PKIX_PL_Cert *cert = NULL; PKIX_Error *error = NULL; PRFileDesc *inFile = NULL; SECItem certDER; void *buf = NULL; PKIX_UInt32 len; SECStatus rv = SECFailure; certDER.data = NULL; inFile = PR_Open(inFileName, PR_RDONLY, 0); if (!inFile){ printFailure("Unable to open cert file"); goto cleanup; } else { rv = SECU_ReadDERFromFile(&certDER, inFile, PR_FALSE); if (!rv){ buf = (void *)certDER.data; len = certDER.len; error = PKIX_PL_ByteArray_Create (buf, len, &byteArray, plContext); if (error){ printFailure("PKIX_PL_ByteArray_Create failed"); goto cleanup; } error = PKIX_PL_Cert_Create (byteArray, &cert, plContext); if (error){ printFailure("PKIX_PL_Cert_Create failed"); goto cleanup; } } else { printFailure("Unable to read DER from cert file"); goto cleanup; } } cleanup: if (inFile){ PR_Close(inFile); } if (rv == SECSuccess){ SECITEM_FreeItem(&certDER, PR_FALSE); } if (byteArray){ PKIX_PL_Object_DecRef((PKIX_PL_Object *)(byteArray), plContext); } return (cert); }