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; }
SEC_PKCS7ContentInfo * SECMIME_CreateSigned(CERTCertificate *scert, CERTCertificate *ecert, CERTCertDBHandle *certdb, SECOidTag digestalg, SECItem *digest, SECKEYGetPasswordKey pwfn, void *pwfn_arg) { SEC_PKCS7ContentInfo *cinfo; SECStatus rv; /* See note in header comment above about digestalg. */ /* Doesn't explain this. PORT_Assert (digestalg == SEC_OID_SHA1); */ cinfo = SEC_PKCS7CreateSignedData(scert, certUsageEmailSigner, certdb, digestalg, digest, pwfn, pwfn_arg); if (cinfo == NULL) return NULL; if (SEC_PKCS7IncludeCertChain(cinfo, NULL) != SECSuccess) { SEC_PKCS7DestroyContentInfo(cinfo); return NULL; } /* if the encryption cert and the signing cert differ, then include * the encryption cert too. */ /* it is ok to compare the pointers since we ref count, and the same * cert will always have the same pointer */ if ((ecert != NULL) && (ecert != scert)) { rv = SEC_PKCS7AddCertificate(cinfo, ecert); if (rv != SECSuccess) { SEC_PKCS7DestroyContentInfo(cinfo); return NULL; } } /* * Add the signing time. But if it fails for some reason, * may as well not give up altogether -- just assert. */ rv = SEC_PKCS7AddSigningTime(cinfo); PORT_Assert(rv == SECSuccess); /* * Add the email profile. Again, if it fails for some reason, * may as well not give up altogether -- just assert. */ rv = smime_add_profile(ecert, cinfo); PORT_Assert(rv == SECSuccess); return cinfo; }
/* * Start an S/MIME encrypting context. * * "scert" is the cert for the sender. It will be checked for validity. * "rcerts" are the certs for the recipients. They will also be checked. * * "certdb" is the cert database to use for verifying the certs. * It can be NULL if a default database is available (like in the client). * * This function already does all of the stuff specific to S/MIME protocol * and local policy; the return value just needs to be passed to * SEC_PKCS7Encode() or to SEC_PKCS7EncoderStart() to create the encoded data, * and finally to SEC_PKCS7DestroyContentInfo(). * * An error results in a return value of NULL and an error set. * (Retrieve specific errors via PORT_GetError()/XP_GetError().) */ SEC_PKCS7ContentInfo * SECMIME_CreateEncrypted(CERTCertificate *scert, CERTCertificate **rcerts, CERTCertDBHandle *certdb, SECKEYGetPasswordKey pwfn, void *pwfn_arg) { SEC_PKCS7ContentInfo *cinfo; long cipher; SECOidTag encalg; int keysize; int mapi, rci; cipher = smime_choose_cipher(scert, rcerts); if (cipher < 0) return NULL; mapi = smime_mapi_by_cipher(cipher); if (mapi < 0) return NULL; /* * XXX This is stretching it -- CreateEnvelopedData should probably * take a cipher itself of some sort, because we cannot know what the * future will bring in terms of parameters for each type of algorithm. * For example, just an algorithm and keysize is *not* sufficient to * fully specify the usage of RC5 (which also needs to know rounds and * block size). Work this out into a better API! */ encalg = smime_cipher_maps[mapi].algtag; keysize = smime_keysize_by_cipher(cipher); if (keysize < 0) return NULL; cinfo = SEC_PKCS7CreateEnvelopedData(scert, certUsageEmailRecipient, certdb, encalg, keysize, pwfn, pwfn_arg); if (cinfo == NULL) return NULL; for (rci = 0; rcerts[rci] != NULL; rci++) { if (rcerts[rci] == scert) continue; if (SEC_PKCS7AddRecipient(cinfo, rcerts[rci], certUsageEmailRecipient, NULL) != SECSuccess) { SEC_PKCS7DestroyContentInfo(cinfo); return NULL; } } return cinfo; }
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; }
int SV_PrintPKCS7ContentInfo(FILE *out, SECItem *der) { SEC_PKCS7ContentInfo *cinfo; int rv = -1; cinfo = SEC_PKCS7DecodeItem(der, NULL, NULL, NULL, NULL, NULL, NULL, NULL); if (cinfo != NULL) { rv = sv_PrintPKCS7ContentInfo(out, cinfo, "pkcs7.contentInfo="); SEC_PKCS7DestroyContentInfo(cinfo); } return rv; }
SECStatus SEC_ReadPKCS7Certs(SECItem *pkcs7Item, CERTImportCertificateFunc f, void *arg) { SEC_PKCS7ContentInfo *contentInfo = NULL; SECStatus rv; SECItem **certs; int count; contentInfo = SEC_PKCS7DecodeItem(pkcs7Item, NULL, NULL, NULL, NULL, NULL, NULL, NULL); if ( contentInfo == NULL ) { goto loser; } if ( SEC_PKCS7ContentType (contentInfo) != SEC_OID_PKCS7_SIGNED_DATA ) { goto loser; } certs = contentInfo->content.signedData->rawCerts; if ( certs ) { count = 0; while ( *certs ) { count++; certs++; } rv = (* f)(arg, contentInfo->content.signedData->rawCerts, count); } rv = SECSuccess; goto done; loser: rv = SECFailure; done: if ( contentInfo ) { SEC_PKCS7DestroyContentInfo(contentInfo); } return(rv); }
static SECStatus crmf_destroy_encrypted_key(CRMFEncryptedKey *inEncrKey, PRBool freeit) { PORT_Assert(inEncrKey != NULL); if (inEncrKey != NULL) { switch (inEncrKey->encKeyChoice) { case crmfEncryptedValueChoice: crmf_destroy_encrypted_value(&inEncrKey->value.encryptedValue, PR_FALSE); break; case crmfEnvelopedDataChoice: SEC_PKCS7DestroyContentInfo(inEncrKey->value.envelopedData); break; default: break; } if (freeit) { PORT_Free(inEncrKey); } } return SECSuccess; }
static int EncryptFile(FILE *outFile, FILE *inFile, struct recipient *recipients, char *progName) { SEC_PKCS7ContentInfo *cinfo; SEC_PKCS7EncoderContext *ecx; struct recipient *rcpt; SECStatus rv; if (outFile == NULL || inFile == NULL || recipients == NULL) return -1; /* XXX Need a better way to handle that certUsage stuff! */ /* XXX keysize? */ cinfo = SEC_PKCS7CreateEnvelopedData (recipients->cert, certUsageEmailRecipient, NULL, SEC_OID_DES_EDE3_CBC, 0, NULL, NULL); if (cinfo == NULL) return -1; for (rcpt = recipients->next; rcpt != NULL; rcpt = rcpt->next) { rv = SEC_PKCS7AddRecipient (cinfo, rcpt->cert, certUsageEmailRecipient, NULL); if (rv != SECSuccess) { SECU_PrintError(progName, "error adding recipient \"%s\"", rcpt->nickname); return -1; } } ecx = SEC_PKCS7EncoderStart (cinfo, EncryptOut, outFile, NULL); if (ecx == NULL) return -1; for (;;) { char ibuf[1024]; int nb; if (feof(inFile)) break; nb = fread(ibuf, 1, sizeof(ibuf), inFile); if (nb == 0) { if (ferror(inFile)) { PORT_SetError(SEC_ERROR_IO); rv = SECFailure; } break; } rv = SEC_PKCS7EncoderUpdate(ecx, ibuf, nb); if (rv != SECSuccess) break; } if (SEC_PKCS7EncoderFinish(ecx, NULL, NULL) != SECSuccess) rv = SECFailure; SEC_PKCS7DestroyContentInfo (cinfo); if (rv != SECSuccess) return -1; return 0; }
/************************************************************************* * * o u t p u t _ c a _ c e r t */ static void output_ca_cert (CERTCertificate *cert, CERTCertDBHandle *db) { FILE * out; SECItem * encodedCertChain; SEC_PKCS7ContentInfo * certChain; char *filename; /* the raw */ filename = PORT_ZAlloc(strlen(DEFAULT_X509_BASENAME) + 8); if (!filename) out_of_memory(); sprintf(filename, "%s.raw", DEFAULT_X509_BASENAME); if ((out = fopen (filename, "wb")) == NULL) { PR_fprintf(errorFD, "%s: Can't open %s output file\n", PROGRAM_NAME, filename); errorCount++; exit(ERRX); } certChain = SEC_PKCS7CreateCertsOnly (cert, PR_TRUE, db); encodedCertChain = SEC_PKCS7EncodeItem (NULL, NULL, certChain, NULL, NULL, NULL); SEC_PKCS7DestroyContentInfo (certChain); if (encodedCertChain) { fprintf(out, "Content-type: application/x-x509-ca-cert\n\n"); fwrite (encodedCertChain->data, 1, encodedCertChain->len, out); SECITEM_FreeItem(encodedCertChain, PR_TRUE); } else { PR_fprintf(errorFD, "%s: Can't DER encode this certificate\n", PROGRAM_NAME); errorCount++; exit(ERRX); } fclose (out); /* and the cooked */ sprintf(filename, "%s.cacert", DEFAULT_X509_BASENAME); if ((out = fopen (filename, "wb")) == NULL) { PR_fprintf(errorFD, "%s: Can't open %s output file\n", PROGRAM_NAME, filename); errorCount++; return; } fprintf (out, "%s\n%s\n%s\n", NS_CERT_HEADER, BTOA_DataToAscii (cert->derCert.data, cert->derCert.len), NS_CERT_TRAILER); fclose (out); if (verbosity >= 0) { PR_fprintf(outputFD, "Exported certificate to %s.raw and %s.cacert.\n", DEFAULT_X509_BASENAME, DEFAULT_X509_BASENAME); } }
int jar_create_pk7(CERTCertDBHandle *certdb, void *keydb, CERTCertificate *cert, char *password, JAR_FILE infp, JAR_FILE outfp) { SEC_PKCS7ContentInfo *cinfo; const SECHashObject *hashObj; char *errstring; void *mw = NULL; void *hashcx; unsigned int len; int status = 0; SECStatus rv; SECItem digest; unsigned char digestdata[32]; unsigned char buffer[4096]; if (outfp == NULL || infp == NULL || cert == NULL) return JAR_ERR_GENERAL; /* we sign with SHA */ hashObj = HASH_GetHashObject(HASH_AlgSHA1); hashcx = (* hashObj->create)(); if (hashcx == NULL) return JAR_ERR_GENERAL; (* hashObj->begin)(hashcx); while (1) { int nb = JAR_FREAD(infp, buffer, sizeof buffer); if (nb == 0) { /* eof */ break; } (* hashObj->update) (hashcx, buffer, nb); } (* hashObj->end)(hashcx, digestdata, &len, 32); (* hashObj->destroy)(hashcx, PR_TRUE); digest.data = digestdata; digest.len = len; /* signtool must use any old context it can find since it's calling from inside javaland. */ PORT_SetError (0); cinfo = SEC_PKCS7CreateSignedData(cert, certUsageObjectSigner, NULL, SEC_OID_SHA1, &digest, NULL, mw); if (cinfo == NULL) return JAR_ERR_PK7; rv = SEC_PKCS7IncludeCertChain(cinfo, NULL); if (rv != SECSuccess) { status = PORT_GetError(); SEC_PKCS7DestroyContentInfo(cinfo); return status; } /* Having this here forces signtool to always include signing time. */ rv = SEC_PKCS7AddSigningTime(cinfo); /* don't check error */ PORT_SetError(0); /* if calling from mozilla thread*/ rv = SEC_PKCS7Encode(cinfo, jar_pk7_out, outfp, NULL, NULL, mw); if (rv != SECSuccess) status = PORT_GetError(); SEC_PKCS7DestroyContentInfo (cinfo); if (rv != SECSuccess) { errstring = JAR_get_error (status); return ((status < 0) ? status : JAR_ERR_GENERAL); } 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; }
void pesign_context_fini(pesign_context *ctx) { if (!ctx) return; if (ctx->cms_ctx) { cms_context_fini(ctx->cms_ctx); ctx->cms_ctx = NULL; } if (ctx->outpe) { pe_end(ctx->outpe); ctx->outpe = NULL; } if (ctx->inpe) { pe_end(ctx->inpe); ctx->inpe = NULL; } xfree(ctx->outfile); xfree(ctx->infile); xfree(ctx->rawsig); xfree(ctx->insattrs); xfree(ctx->outsattrs); xfree(ctx->insig); xfree(ctx->outsig); xfree(ctx->outkey); xfree(ctx->outcert); if (ctx->rawsigfd >= 0) { close(ctx->rawsigfd); ctx->rawsigfd = -1; } if (ctx->insattrsfd >= 0) { close(ctx->insattrsfd); ctx->insattrsfd = -1; } if (ctx->outsattrsfd >= 0) { close(ctx->outsattrsfd); ctx->outsattrsfd = -1; } if (ctx->insigfd >= 0) { close(ctx->insigfd); ctx->insigfd = -1; } if (ctx->outsigfd >= 0) { close(ctx->outsigfd); ctx->outsigfd = -1; } if (ctx->outkeyfd >= 0) { close(ctx->outkeyfd); ctx->outkeyfd = -1; } if (ctx->outcertfd >= 0) { close(ctx->outcertfd); ctx->outcertfd = -1; } if (ctx->cinfo) { SEC_PKCS7DestroyContentInfo(ctx->cinfo); ctx->cinfo = NULL; } if (ctx->outfd >= 0) { close(ctx->outfd); ctx->outfd = -1; } if (ctx->infd >= 0) { close(ctx->infd); ctx->infd = -1; } ctx->signum = -1; if (!(ctx->flags & PESIGN_C_ALLOCATED)) pesign_context_init(ctx); }
/********************************************************************** * * S i g n F i l e */ static int SignFile (FILE *outFile, FILE *inFile, CERTCertificate *cert) { int nb; char ibuf[4096], digestdata[32]; const SECHashObject *hashObj; void *hashcx; unsigned int len; SECItem digest; SEC_PKCS7ContentInfo * cinfo; SECStatus rv; if (outFile == NULL || inFile == NULL || cert == NULL) return - 1; /* XXX probably want to extend interface to allow other hash algorithms */ hashObj = HASH_GetHashObject(HASH_AlgSHA1); hashcx = (*hashObj->create)(); if (hashcx == NULL) return - 1; (*hashObj->begin)(hashcx); for (; ; ) { if (feof(inFile)) break; nb = fread(ibuf, 1, sizeof(ibuf), inFile); if (nb == 0) { if (ferror(inFile)) { PORT_SetError(SEC_ERROR_IO); (*hashObj->destroy)(hashcx, PR_TRUE); return - 1; } /* eof */ break; } (*hashObj->update)(hashcx, (unsigned char *) ibuf, nb); } (*hashObj->end)(hashcx, (unsigned char *) digestdata, &len, 32); (*hashObj->destroy)(hashcx, PR_TRUE); digest.data = (unsigned char *) digestdata; digest.len = len; cinfo = SEC_PKCS7CreateSignedData (cert, certUsageObjectSigner, NULL, SEC_OID_SHA1, &digest, NULL, NULL); if (cinfo == NULL) return - 1; rv = SEC_PKCS7IncludeCertChain (cinfo, NULL); if (rv != SECSuccess) { SEC_PKCS7DestroyContentInfo (cinfo); return - 1; } if (no_time == 0) { rv = SEC_PKCS7AddSigningTime (cinfo); if (rv != SECSuccess) { /* don't check error */ } } rv = SEC_PKCS7Encode(cinfo, SignOut, outFile, NULL, NULL, &pwdata); SEC_PKCS7DestroyContentInfo (cinfo); if (rv != SECSuccess) return - 1; return 0; }
smime_CMDExports() { SEC_PKCS7DecodeItem(); SEC_PKCS7DestroyContentInfo(); }
int list_signatures(pesign_context *ctx) { cert_iter iter; int rc = cert_iter_init(&iter, ctx->inpe); if (rc < 0) { printf("No certificate list found.\n"); return rc; } void *data; ssize_t datalen; int nsigs = 0; rc = 0; while (1) { rc = next_cert(&iter, &data, &datalen); if (rc <= 0) break; SEC_PKCS7DecoderContext *dc = NULL; saw_content = 0; dc = SEC_PKCS7DecoderStart(handle_bytes, NULL, NULL, NULL, NULL, NULL, decryption_allowed); if (dc == NULL) { fprintf(stderr, "SEC_PKCS7DecoderStart failed\n"); exit(1); } SECStatus status = SEC_PKCS7DecoderUpdate(dc, data, datalen); if (status != SECSuccess) { fprintf(stderr, "Found invalid certificate\n"); continue; } SEC_PKCS7ContentInfo *cinfo = SEC_PKCS7DecoderFinish(dc); if (cinfo == NULL) { fprintf(stderr, "Found invalid certificate\n"); continue; } nsigs++; printf("---------------------------------------------\n"); printf("Content was%s encrypted.\n", SEC_PKCS7ContentIsEncrypted(cinfo) ? "" : " not"); if (SEC_PKCS7ContentIsSigned(cinfo)) { char *signer_cname, *signer_ename; SECItem *signing_time; if (saw_content) { printf("Signature is "); PORT_SetError(0); if (SEC_PKCS7VerifySignature(cinfo, certUsageEmailSigner, PR_FALSE)) { printf("valid.\n"); } else { printf("invalid (Reason: 0x%08x).\n", (uint32_t)PORT_GetError()); } } else { printf("Content is detached; signature cannot " "be verified.\n"); } signer_cname = SEC_PKCS7GetSignerCommonName(cinfo); if (signer_cname != NULL) { printf("The signer's common name is %s\n", signer_cname); PORT_Free(signer_cname); } else { printf("No signer common name.\n"); } signer_ename = SEC_PKCS7GetSignerEmailAddress(cinfo); if (signer_ename != NULL) { printf("The signer's email address is %s\n", signer_ename); PORT_Free(signer_ename); } else { printf("No signer email address.\n"); } signing_time = SEC_PKCS7GetSigningTime(cinfo); if (signing_time != NULL) { printf("Signing time: %s\n", DER_TimeChoiceDayToAscii(signing_time)); } else { printf("No signing time included.\n"); } printf("There were%s certs or crls included.\n", SEC_PKCS7ContainsCertsOrCrls(cinfo) ? "" : " no"); SEC_PKCS7DestroyContentInfo(cinfo); } } if (nsigs) { printf("---------------------------------------------\n"); } else { printf("No signatures found.\n"); } return rc; }
SECStatus SEC_ReadCertSequence(SECItem *certsItem, CERTImportCertificateFunc f, void *arg) { SECStatus rv; SECItem **certs; int count; SECItem **rawCerts = NULL; PRArenaPool *arena; SEC_PKCS7ContentInfo *contentInfo = NULL; arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (arena == NULL) { return SECFailure; } contentInfo = SEC_PKCS7DecodeItem(certsItem, NULL, NULL, NULL, NULL, NULL, NULL, NULL); if ( contentInfo == NULL ) { goto loser; } if ( SEC_PKCS7ContentType (contentInfo) != SEC_OID_NS_TYPE_CERT_SEQUENCE ) { goto loser; } rv = SEC_QuickDERDecodeItem(arena, &rawCerts, SEC_CertSequenceTemplate, contentInfo->content.data); if (rv != SECSuccess) { goto loser; } certs = rawCerts; if ( certs ) { count = 0; while ( *certs ) { count++; certs++; } rv = (* f)(arg, rawCerts, count); } rv = SECSuccess; goto done; loser: rv = SECFailure; done: if ( contentInfo ) { SEC_PKCS7DestroyContentInfo(contentInfo); } if ( arena ) { PORT_FreeArena(arena, PR_FALSE); } return(rv); }