int main(int argc, char *argv[]) { int rc; pesign_context ctx, *ctxp = &ctx; int list = 0; int remove = 0; char *digest_name = "sha256"; poptContext optCon; struct poptOption options[] = { {NULL, '\0', POPT_ARG_INTL_DOMAIN, "pesign" }, {"in", 'i', POPT_ARG_STRING, &ctx.infile, 0, "specify input file", "<infile>"}, {"out", 'o', POPT_ARG_STRING, &ctx.outfile, 0, "specify output file", "<outfile>" }, {"certficate", 'c', POPT_ARG_STRING, &ctx.cms_ctx.certname, 0, "specify certificate nickname", "<certificate nickname>" }, {"privkey", 'p', POPT_ARG_STRING, &ctx.privkeyfile, 0, "specify private key file", "<privkey>" }, {"force", 'f', POPT_ARG_VAL, &ctx.force, 1, "force overwriting of output file", NULL }, {"nogaps", 'n', POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &ctx.hashgaps, 0, "skip gaps between sections when signing", NULL }, {"sign", 's', POPT_ARG_VAL, &ctx.sign, 1, "create a new signature", NULL }, {"hash", 'h', POPT_ARG_VAL, &ctx.hash, 1, "hash binary", NULL }, {"digest_type", 'd', POPT_ARG_STRING|POPT_ARGFLAG_SHOW_DEFAULT, &digest_name, 0, "digest type to use for pe hash" }, {"import-signature", 'm', POPT_ARG_STRING|POPT_ARGFLAG_DOC_HIDDEN, &ctx.insig, 0,"import signature from file", "<insig>" }, {"signature-number", 'u', POPT_ARG_INT, &ctx.signum, -1, "specify which signature to operate on","<sig-number>"}, {"list-signatures", 'l', POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &list, 1, "list signatures", NULL }, {"show-signature", 'S', POPT_ARG_VAL, &list, 1, "show signature", NULL }, {"remove-signature", 'r', POPT_ARG_VAL, &remove, 1, "remove signature" }, {"export-signature", 'e', POPT_ARG_STRING|POPT_ARGFLAG_DOC_HIDDEN, &ctx.outsig, 0,"export signature to file", "<outsig>" }, {"export-pubkey", 'K', POPT_ARG_STRING, &ctx.outkey, 0, "export pubkey to file", "<outkey>" }, {"export-cert", 'C', POPT_ARG_STRING, &ctx.outcert, 0, "export signing cert to file", "<outcert>" }, {"ascii-armor", 'a', POPT_ARG_VAL, &ctx.ascii, 1, "use ascii armoring", NULL }, POPT_AUTOALIAS POPT_AUTOHELP POPT_TABLEEND }; rc = pesign_context_init(ctxp); if (rc < 0) { fprintf(stderr, "Could not initialize context: %m\n"); exit(1); } optCon = poptGetContext("pesign", argc, (const char **)argv, options,0); while ((rc = poptGetNextOpt(optCon)) > 0) ; if (rc < -1) { fprintf(stderr, "pesign: Invalid argument: %s: %s\n", poptBadOption(optCon, 0), poptStrerror(rc)); exit(1); } if (poptPeekArg(optCon)) { fprintf(stderr, "pesign: Invalid Argument: \"%s\"\n", poptPeekArg(optCon)); exit(1); } poptFreeContext(optCon); rc = set_digest_parameters(&ctx.cms_ctx, digest_name); int is_help = strcmp(digest_name, "help") ? 0 : 1; if (rc < 0) { if (!is_help) { fprintf(stderr, "Digest \"%s\" not found.\n", digest_name); } exit(!is_help); } int action = 0; if (ctx.insig) action |= IMPORT_SIGNATURE; if (ctx.outkey) action |= EXPORT_PUBKEY; if (ctx.outcert) action |= EXPORT_CERT; if (ctx.outsig) action |= EXPORT_SIGNATURE; if (remove != 0) action |= REMOVE_SIGNATURE; if (list != 0) action |= LIST_SIGNATURES; if (ctx.sign) { action |= GENERATE_SIGNATURE; if (!(action & EXPORT_SIGNATURE)) action |= IMPORT_SIGNATURE; } if (ctx.hash) action |= GENERATE_DIGEST|PRINT_DIGEST; SECItem newsig; switch (action) { case NO_FLAGS: fprintf(stderr, "pesign: Nothing to do.\n"); exit(0); break; /* add a signature from a file */ case IMPORT_SIGNATURE: check_inputs(ctxp); open_input(ctxp); open_output(ctxp); close_input(ctxp); open_sig_input(ctxp); import_signature(ctxp); close_sig_input(ctxp); close_output(ctxp); break; case EXPORT_PUBKEY: rc = find_certificate(&ctx.cms_ctx); if (rc < 0) { fprintf(stderr, "pesign: Could not find " "certificate %s\n", ctx.cms_ctx.certname); exit(1); } open_pubkey_output(ctxp); export_pubkey(ctxp); break; case EXPORT_CERT: rc = find_certificate(&ctx.cms_ctx); if (rc < 0) { fprintf(stderr, "pesign: Could not find " "certificate %s\n", ctx.cms_ctx.certname); exit(1); } open_cert_output(ctxp); export_cert(ctxp); break; /* find a signature in the binary and save it to a file */ case EXPORT_SIGNATURE: open_input(ctxp); open_sig_output(ctxp); if (ctx.signum > ctx.cms_ctx.num_signatures) { fprintf(stderr, "Invalid signature number.\n"); exit(1); } SECItem *sig = ctx.cms_ctx.signatures[ctx.signum]; export_signature(ctxp, sig); close_input(ctxp); close_sig_output(ctxp); break; /* remove a signature from the binary */ case REMOVE_SIGNATURE: check_inputs(ctxp); open_input(ctxp); open_output(ctxp); close_input(ctxp); if (ctx.signum > ctx.cms_ctx.num_signatures) { fprintf(stderr, "Invalid signature number.\n"); exit(1); } remove_signature(&ctx); close_output(ctxp); break; /* list signatures in the binary */ case LIST_SIGNATURES: open_input(ctxp); list_signatures(ctxp); break; case GENERATE_DIGEST|PRINT_DIGEST: open_input(ctxp); generate_digest(ctxp, ctx.inpe); print_digest(ctxp); break; /* generate a signature and save it in a separate file */ case EXPORT_SIGNATURE|GENERATE_SIGNATURE: rc = find_certificate(&ctx.cms_ctx); if (rc < 0) { fprintf(stderr, "pesign: Could not find " "certificate %s\n", ctx.cms_ctx.certname); exit(1); } open_input(ctxp); open_sig_output(ctxp); generate_digest(ctxp, ctx.inpe); generate_signature(ctxp, &newsig); export_signature(ctxp, &newsig); break; /* generate a signature and embed it in the binary */ case IMPORT_SIGNATURE|GENERATE_SIGNATURE: check_inputs(ctxp); rc = find_certificate(&ctx.cms_ctx); if (rc < 0) { fprintf(stderr, "pesign: Could not find " "certificate %s\n", ctx.cms_ctx.certname); exit(1); } open_input(ctxp); open_output(ctxp); close_input(ctxp); generate_digest(ctxp, ctx.outpe); generate_signature(ctxp, &newsig); insert_signature(ctxp, &newsig); close_output(ctxp); break; default: fprintf(stderr, "Incompatible flags (0x%08x): ", action); for (int i = 1; i < FLAG_LIST_END; i <<= 1) { if (action & i) print_flag_name(stderr, i); } fprintf(stderr, "\n"); exit(1); } pesign_context_fini(&ctx); return (rc < 0); }
int main (int argc, char **argv) { int retval; PRFileDesc *in_file; FILE *out_file; /* not PRFileDesc until SECU accepts it */ int crequest, dresponse; int prequest, presponse; int ccert, vcert; const char *db_dir, *date_str, *cert_usage_str, *name; const char *responder_name, *responder_url, *signer_name; PRBool add_acceptable_responses, add_service_locator; SECItem *data = NULL; PLOptState *optstate; SECStatus rv; CERTCertDBHandle *handle = NULL; SECCertUsage cert_usage; PRTime verify_time; CERTCertificate *cert = NULL; PRBool ascii = PR_FALSE; retval = -1; /* what we return/exit with on error */ program_name = PL_strrchr(argv[0], '/'); program_name = program_name ? (program_name + 1) : argv[0]; in_file = PR_STDIN; out_file = stdout; crequest = 0; dresponse = 0; prequest = 0; presponse = 0; ccert = 0; vcert = 0; db_dir = NULL; date_str = NULL; cert_usage_str = NULL; name = NULL; responder_name = NULL; responder_url = NULL; signer_name = NULL; add_acceptable_responses = PR_FALSE; add_service_locator = PR_FALSE; optstate = PL_CreateOptState (argc, argv, "AHLPR:S:V:d:l:pr:s:t:u:w:"); if (optstate == NULL) { SECU_PrintError (program_name, "PL_CreateOptState failed"); return retval; } while (PL_GetNextOpt (optstate) == PL_OPT_OK) { switch (optstate->option) { case '?': short_usage (program_name); return retval; case 'A': add_acceptable_responses = PR_TRUE; break; case 'H': long_usage (program_name); return retval; case 'L': add_service_locator = PR_TRUE; break; case 'P': presponse = 1; break; case 'R': dresponse = 1; name = optstate->value; break; case 'S': ccert = 1; name = optstate->value; break; case 'V': vcert = 1; name = optstate->value; break; case 'a': ascii = PR_TRUE; break; case 'd': db_dir = optstate->value; break; case 'l': responder_url = optstate->value; break; case 'p': prequest = 1; break; case 'r': crequest = 1; name = optstate->value; break; case 's': signer_name = optstate->value; break; case 't': responder_name = optstate->value; break; case 'u': cert_usage_str = optstate->value; break; case 'w': date_str = optstate->value; break; } } PL_DestroyOptState(optstate); if ((crequest + dresponse + prequest + presponse + ccert + vcert) != 1) { PR_fprintf (PR_STDERR, "%s: must specify exactly one command\n\n", program_name); short_usage (program_name); return retval; } if (vcert) { if (cert_usage_str == NULL) { PR_fprintf (PR_STDERR, "%s: verification requires cert usage\n\n", program_name); short_usage (program_name); return retval; } rv = cert_usage_from_char (cert_usage_str, &cert_usage); if (rv != SECSuccess) { PR_fprintf (PR_STDERR, "%s: invalid cert usage (\"%s\")\n\n", program_name, cert_usage_str); long_usage (program_name); return retval; } } if (ccert + vcert) { if (responder_url != NULL || responder_name != NULL) { /* * To do a full status check, both the URL and the cert name * of the responder must be specified if either one is. */ if (responder_url == NULL || responder_name == NULL) { if (responder_url == NULL) PR_fprintf (PR_STDERR, "%s: must also specify responder location\n\n", program_name); else PR_fprintf (PR_STDERR, "%s: must also specify responder name\n\n", program_name); short_usage (program_name); return retval; } } if (date_str != NULL) { rv = DER_AsciiToTime (&verify_time, (char *) date_str); if (rv != SECSuccess) { SECU_PrintError (program_name, "error converting time string"); PR_fprintf (PR_STDERR, "\n"); long_usage (program_name); return retval; } } else { verify_time = PR_Now(); } } retval = -2; /* errors change from usage to runtime */ /* * Initialize the NSPR and Security libraries. */ PR_Init (PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); db_dir = SECU_ConfigDirectory (db_dir); rv = NSS_Init (db_dir); if (rv != SECSuccess) { SECU_PrintError (program_name, "NSS_Init failed"); goto prdone; } SECU_RegisterDynamicOids(); if (prequest + presponse) { MAKE_FILE_BINARY(stdin); data = read_file_into_item (in_file, siBuffer); if (data == NULL) { SECU_PrintError (program_name, "problem reading input"); goto nssdone; } } if (crequest + dresponse + presponse + ccert + vcert) { handle = CERT_GetDefaultCertDB(); if (handle == NULL) { SECU_PrintError (program_name, "problem getting certdb handle"); goto nssdone; } /* * It would be fine to do the enable for all of these commands, * but this way we check that everything but an overall verify * can be done without it. That is, that the individual pieces * work on their own. */ if (vcert) { rv = CERT_EnableOCSPChecking (handle); if (rv != SECSuccess) { SECU_PrintError (program_name, "error enabling OCSP checking"); goto nssdone; } } if ((ccert + vcert) && (responder_name != NULL)) { rv = CERT_SetOCSPDefaultResponder (handle, responder_url, responder_name); if (rv != SECSuccess) { SECU_PrintError (program_name, "error setting default responder"); goto nssdone; } rv = CERT_EnableOCSPDefaultResponder (handle); if (rv != SECSuccess) { SECU_PrintError (program_name, "error enabling default responder"); goto nssdone; } } } #define NOTYET(opt) \ { \ PR_fprintf (PR_STDERR, "%s not yet working\n", opt); \ exit (-1); \ } if (name) { cert = find_certificate(handle, name, ascii); } if (crequest) { if (signer_name != NULL) { NOTYET("-s"); } rv = create_request (out_file, handle, cert, add_service_locator, add_acceptable_responses); } else if (dresponse) { if (signer_name != NULL) { NOTYET("-s"); } rv = dump_response (out_file, handle, cert, responder_url); } else if (prequest) { rv = print_request (out_file, data); } else if (presponse) { rv = print_response (out_file, data, handle); } else if (ccert) { if (signer_name != NULL) { NOTYET("-s"); } rv = get_cert_status (out_file, handle, cert, name, verify_time); } else if (vcert) { if (signer_name != NULL) { NOTYET("-s"); } rv = verify_cert (out_file, handle, cert, name, cert_usage, verify_time); } if (rv != SECSuccess) SECU_PrintError (program_name, "error performing requested operation"); else retval = 0; nssdone: if (cert) { CERT_DestroyCertificate(cert); } if (data != NULL) { SECITEM_FreeItem (data, PR_TRUE); } if (handle != NULL) { CERT_DisableOCSPDefaultResponder(handle); CERT_DisableOCSPChecking (handle); } if (NSS_Shutdown () != SECSuccess) { retval = 1; } prdone: PR_Cleanup (); return retval; }
int main(int argc, char *argv[]) { int rc; pesign_context *ctxp; int list = 0; int remove = 0; int daemon = 0; int fork = 1; int padding = 0; int need_db = 0; char *digest_name = "sha256"; char *tokenname = "NSS Certificate DB"; char *origtoken = tokenname; char *certname = NULL; char *certdir = "/etc/pki/pesign"; char *signum = NULL; rc = pesign_context_new(&ctxp); if (rc < 0) { fprintf(stderr, "Could not initialize context: %m\n"); exit(1); } poptContext optCon; struct poptOption options[] = { {NULL, '\0', POPT_ARG_INTL_DOMAIN, "pesign" }, {"in", 'i', POPT_ARG_STRING, &ctxp->infile, 0, "specify input file", "<infile>"}, {"out", 'o', POPT_ARG_STRING, &ctxp->outfile, 0, "specify output file", "<outfile>" }, {"certficate", 'c', POPT_ARG_STRING, &certname, 0, "specify certificate nickname", "<certificate nickname>" }, {"certdir", 'n', POPT_ARG_STRING|POPT_ARGFLAG_SHOW_DEFAULT, &certdir, 0, "specify nss certificate database directory", "<certificate directory path>" }, {"force", 'f', POPT_ARG_VAL, &ctxp->force, 1, "force overwriting of output file", NULL }, {"sign", 's', POPT_ARG_VAL, &ctxp->sign, 1, "create a new signature", NULL }, {"hash", 'h', POPT_ARG_VAL, &ctxp->hash, 1, "hash binary", NULL }, {"digest_type", 'd', POPT_ARG_STRING|POPT_ARGFLAG_SHOW_DEFAULT, &digest_name, 0, "digest type to use for pe hash" }, {"import-signed-certificate", 'm', POPT_ARG_STRING|POPT_ARGFLAG_DOC_HIDDEN, &ctxp->insig, 0,"import signature from file", "<insig>" }, {"export-signed-attributes", 'E', POPT_ARG_STRING|POPT_ARGFLAG_DOC_HIDDEN, &ctxp->outsattrs, 0, "export signed attributes to file", "<signed_attributes_file>" }, {"import-signed-attributes", 'I', POPT_ARG_STRING|POPT_ARGFLAG_DOC_HIDDEN, &ctxp->insattrs, 0, "import signed attributes from file", "<signed_attributes_file>" }, {"import-raw-signature", 'R', POPT_ARG_STRING|POPT_ARGFLAG_DOC_HIDDEN, &ctxp->rawsig, 0, "import raw signature from file", "<inraw>" }, {"signature-number", 'u', POPT_ARG_STRING, &signum, 0, "specify which signature to operate on","<sig-number>"}, {"list-signatures", 'l', POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &list, 1, "list signatures", NULL }, {"nss-token", 't', POPT_ARG_STRING|POPT_ARGFLAG_SHOW_DEFAULT, &tokenname, 0, "NSS token holding signing key" }, {"show-signature", 'S', POPT_ARG_VAL, &list, 1, "show signature", NULL }, {"remove-signature", 'r', POPT_ARG_VAL, &remove, 1, "remove signature" }, {"export-signature", 'e', POPT_ARG_STRING|POPT_ARGFLAG_DOC_HIDDEN, &ctxp->outsig, 0, "export signature to file", "<outsig>" }, {"export-pubkey", 'K', POPT_ARG_STRING, &ctxp->outkey, 0, "export pubkey to file", "<outkey>" }, {"export-cert", 'C', POPT_ARG_STRING, &ctxp->outcert, 0, "export signing cert to file", "<outcert>" }, {"ascii-armor", 'a', POPT_ARG_VAL, &ctxp->ascii, 1, "use ascii armoring", NULL }, {"daemonize", 'D', POPT_ARG_VAL, &daemon, 1, "run as a daemon process", NULL }, {"nofork", 'N', POPT_ARG_VAL, &fork, 0, "don't fork when daemonizing", NULL }, {"verbose", 'v', POPT_ARG_VAL, &ctxp->verbose, 1, "be very verbose", NULL }, {"padding", 'P', POPT_ARG_VAL, &padding, 1, "pad data section", NULL }, POPT_AUTOALIAS POPT_AUTOHELP POPT_TABLEEND }; optCon = poptGetContext("pesign", argc, (const char **)argv, options,0); rc = poptReadDefaultConfig(optCon, 0); if (rc < 0 && !(rc == POPT_ERROR_ERRNO && errno == ENOENT)) { fprintf(stderr, "pesign: poptReadDefaultConfig failed: %s\n", poptStrerror(rc)); exit(1); } while ((rc = poptGetNextOpt(optCon)) > 0) ; if (rc < -1) { fprintf(stderr, "pesign: Invalid argument: %s: %s\n", poptBadOption(optCon, 0), poptStrerror(rc)); exit(1); } if (poptPeekArg(optCon)) { fprintf(stderr, "pesign: Invalid Argument: \"%s\"\n", poptPeekArg(optCon)); exit(1); } poptFreeContext(optCon); if (signum) { errno = 0; ctxp->signum = strtol(signum, NULL, 0); if (errno != 0) { fprintf(stderr, "invalid signature number: %m\n"); exit(1); } } int action = 0; if (daemon) action |= DAEMONIZE; if (ctxp->rawsig) { action |= IMPORT_RAW_SIGNATURE; need_db = 1; } if (ctxp->insattrs) action |= IMPORT_SATTRS; if (ctxp->outsattrs) action |= EXPORT_SATTRS; if (ctxp->insig) action |= IMPORT_SIGNATURE; if (ctxp->outkey) { action |= EXPORT_PUBKEY; need_db = 1; } if (ctxp->outcert) { action |= EXPORT_CERT; need_db = 1; } if (ctxp->outsig) action |= EXPORT_SIGNATURE; if (remove != 0) action |= REMOVE_SIGNATURE; if (list != 0) action |= LIST_SIGNATURES; if (ctxp->sign) { action |= GENERATE_SIGNATURE; if (!(action & EXPORT_SIGNATURE)) action |= IMPORT_SIGNATURE; need_db = 1; } if (ctxp->hash) action |= GENERATE_DIGEST|PRINT_DIGEST; if (!daemon) { SECStatus status; if (need_db) status = NSS_Init(certdir); else status = NSS_NoDB_Init(NULL); if (status != SECSuccess) { fprintf(stderr, "Could not initialize nss: %s\n", PORT_ErrorToString(PORT_GetError())); exit(1); } status = register_oids(ctxp->cms_ctx); if (status != SECSuccess) { fprintf(stderr, "Could not register OIDs\n"); exit(1); } } rc = set_digest_parameters(ctxp->cms_ctx, digest_name); int is_help = strcmp(digest_name, "help") ? 0 : 1; if (rc < 0) { if (!is_help) { fprintf(stderr, "Digest \"%s\" not found.\n", digest_name); } exit(!is_help); } ctxp->cms_ctx->tokenname = tokenname ? PORT_ArenaStrdup(ctxp->cms_ctx->arena, tokenname) : NULL; if (tokenname && !ctxp->cms_ctx->tokenname) { fprintf(stderr, "could not allocate token name: %s\n", PORT_ErrorToString(PORT_GetError())); exit(1); } if (tokenname != origtoken) free(tokenname); ctxp->cms_ctx->certname = certname ? PORT_ArenaStrdup(ctxp->cms_ctx->arena, certname) : NULL; if (certname && !ctxp->cms_ctx->certname) { fprintf(stderr, "could not allocate certificate name: %s\n", PORT_ErrorToString(PORT_GetError())); exit(1); } if (certname) free(certname); if (ctxp->sign) { if (!ctxp->cms_ctx->certname) { fprintf(stderr, "pesign: signing requested but no " "certificate nickname provided\n"); exit(1); } } ssize_t sigspace = 0; switch (action) { case NO_FLAGS: fprintf(stderr, "pesign: Nothing to do.\n"); exit(0); break; /* in this case we have the actual binary signature and the * signing cert, but not the pkcs7ish certificate that goes * with it. */ case IMPORT_RAW_SIGNATURE|IMPORT_SATTRS: check_inputs(ctxp); rc = find_certificate(ctxp->cms_ctx, 0); if (rc < 0) { fprintf(stderr, "pesign: Could not find " "certificate %s\n", ctxp->cms_ctx->certname); exit(1); } open_rawsig_input(ctxp); open_sattr_input(ctxp); import_raw_signature(ctxp); close_sattr_input(ctxp); close_rawsig_input(ctxp); open_input(ctxp); open_output(ctxp); close_input(ctxp); generate_digest(ctxp->cms_ctx, ctxp->outpe, 1); sigspace = calculate_signature_space(ctxp->cms_ctx, ctxp->outpe); allocate_signature_space(ctxp->outpe, sigspace); generate_signature(ctxp->cms_ctx); insert_signature(ctxp->cms_ctx, ctxp->signum); close_output(ctxp); break; case EXPORT_SATTRS: open_input(ctxp); open_sattr_output(ctxp); generate_digest(ctxp->cms_ctx, ctxp->inpe, 1); generate_sattr_blob(ctxp); close_sattr_output(ctxp); close_input(ctxp); break; /* add a signature from a file */ case IMPORT_SIGNATURE: check_inputs(ctxp); if (ctxp->signum > ctxp->cms_ctx->num_signatures + 1) { fprintf(stderr, "Invalid signature number.\n"); exit(1); } open_input(ctxp); open_output(ctxp); close_input(ctxp); open_sig_input(ctxp); parse_signature(ctxp); sigspace = get_sigspace_extend_amount(ctxp->cms_ctx, ctxp->outpe, &ctxp->cms_ctx->newsig); allocate_signature_space(ctxp->outpe, sigspace); check_signature_space(ctxp); insert_signature(ctxp->cms_ctx, ctxp->signum); close_sig_input(ctxp); close_output(ctxp); break; case EXPORT_PUBKEY: rc = find_certificate(ctxp->cms_ctx, 1); if (rc < 0) { fprintf(stderr, "pesign: Could not find " "certificate %s\n", ctxp->cms_ctx->certname); exit(1); } open_pubkey_output(ctxp); export_pubkey(ctxp); break; case EXPORT_CERT: rc = find_certificate(ctxp->cms_ctx, 0); if (rc < 0) { fprintf(stderr, "pesign: Could not find " "certificate %s\n", ctxp->cms_ctx->certname); exit(1); } open_cert_output(ctxp); export_cert(ctxp); break; /* find a signature in the binary and save it to a file */ case EXPORT_SIGNATURE: open_input(ctxp); open_sig_output(ctxp); if (ctxp->signum > ctxp->cms_ctx->num_signatures) { fprintf(stderr, "Invalid signature number.\n"); exit(1); } if (ctxp->signum < 0) ctxp->signum = 0; if (ctxp->signum >= ctxp->cms_ctx->num_signatures) { fprintf(stderr, "No valid signature #%d.\n", ctxp->signum); exit(1); } memcpy(&ctxp->cms_ctx->newsig, ctxp->cms_ctx->signatures[ctxp->signum], sizeof (ctxp->cms_ctx->newsig)); export_signature(ctxp->cms_ctx, ctxp->outsigfd, ctxp->ascii); close_input(ctxp); close_sig_output(ctxp); memset(&ctxp->cms_ctx->newsig, '\0', sizeof (ctxp->cms_ctx->newsig)); break; /* remove a signature from the binary */ case REMOVE_SIGNATURE: check_inputs(ctxp); open_input(ctxp); open_output(ctxp); close_input(ctxp); if (ctxp->signum < 0 || ctxp->signum >= ctxp->cms_ctx->num_signatures) { fprintf(stderr, "Invalid signature number %d. " "Must be between 0 and %d.\n", ctxp->signum, ctxp->cms_ctx->num_signatures - 1); exit(1); } remove_signature(ctxp); close_output(ctxp); break; /* list signatures in the binary */ case LIST_SIGNATURES: open_input(ctxp); list_signatures(ctxp); break; case GENERATE_DIGEST|PRINT_DIGEST: open_input(ctxp); generate_digest(ctxp->cms_ctx, ctxp->inpe, padding); print_digest(ctxp); break; /* generate a signature and save it in a separate file */ case EXPORT_SIGNATURE|GENERATE_SIGNATURE: rc = find_certificate(ctxp->cms_ctx, 1); if (rc < 0) { fprintf(stderr, "pesign: Could not find " "certificate %s\n", ctxp->cms_ctx->certname); exit(1); } open_input(ctxp); open_sig_output(ctxp); generate_digest(ctxp->cms_ctx, ctxp->inpe, 1); generate_signature(ctxp->cms_ctx); export_signature(ctxp->cms_ctx, ctxp->outsigfd, ctxp->ascii); break; /* generate a signature and embed it in the binary */ case IMPORT_SIGNATURE|GENERATE_SIGNATURE: check_inputs(ctxp); rc = find_certificate(ctxp->cms_ctx, 1); if (rc < 0) { fprintf(stderr, "pesign: Could not find " "certificate %s\n", ctxp->cms_ctx->certname); exit(1); } if (ctxp->signum > ctxp->cms_ctx->num_signatures + 1) { fprintf(stderr, "Invalid signature number.\n"); exit(1); } open_input(ctxp); open_output(ctxp); close_input(ctxp); generate_digest(ctxp->cms_ctx, ctxp->outpe, 1); sigspace = calculate_signature_space(ctxp->cms_ctx, ctxp->outpe); allocate_signature_space(ctxp->outpe, sigspace); generate_digest(ctxp->cms_ctx, ctxp->outpe, 1); generate_signature(ctxp->cms_ctx); insert_signature(ctxp->cms_ctx, ctxp->signum); close_output(ctxp); break; case DAEMONIZE: rc = daemonize(ctxp->cms_ctx, certdir, fork); break; default: fprintf(stderr, "Incompatible flags (0x%08x): ", action); for (int i = 1; i < FLAG_LIST_END; i <<= 1) { if (action & i) print_flag_name(stderr, i); } fprintf(stderr, "\n"); exit(1); } pesign_context_free(ctxp); if (!daemon) { SECStatus status = NSS_Shutdown(); if (status != SECSuccess) { fprintf(stderr, "could not shut down NSS: %s", PORT_ErrorToString(PORT_GetError())); exit(1); } } return (rc < 0); }