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 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 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; }