static gpg_error_t search_certs_by_field (void *hook, struct cert *cert) { struct search_ctx_by_field *ctx = hook; gpg_error_t err = 0; if ((ctx->field == SEARCH_BY_GRIP && !strcmp (ctx->pattern, cert->grip)) || (ctx->field == SEARCH_BY_FPR && !strcmp (ctx->pattern, cert->fpr))) { if (strlen (cert->fpr) != 40) return gpg_error (GPG_ERR_GENERAL); err = export_cert (cert->fpr, cert); if (err) return err; err = (*ctx->search_cb) (ctx->search_cb_hook, cert); } return err; }
static int exec_gencrl(int argc, char **argv) { CRYPT_KEYSET cakeys, store; CRYPT_CERTIFICATE crl; CRYPT_CONTEXT ca_privkey; const char *dbfilename; char cakeysfilename[4096]; int status; if (argc < 2) { fprintf(stderr, "missing dbfilename/outfilename\n"); return 1; } dbfilename = argv[0]; /* open store */ status = cryptKeysetOpen(&store, CRYPT_UNUSED, CRYPT_KEYSET_DATABASE_STORE, dbfilename, CRYPT_KEYOPT_NONE); WARN_AND_RETURN_IF(status); /* get ca privkey */ snprintf(cakeysfilename, 4095, "%s.keys", dbfilename); cakeysfilename[4095] = '\0'; status = cryptKeysetOpen(&cakeys, CRYPT_UNUSED, CRYPT_KEYSET_FILE, cakeysfilename, CRYPT_KEYOPT_NONE); WARN_AND_RETURN_IF(status); status = cryptGetPrivateKey(cakeys, &ca_privkey, CRYPT_KEYID_NAME, DEFAULT_CA_PRIVKEY_LABEL, DEFAULT_PASSWORD); WARN_AND_RETURN_IF(status); status = cryptKeysetClose(cakeys); WARN_AND_RETURN_IF(status); status = cryptCACertManagement(&crl, CRYPT_CERTACTION_ISSUE_CRL, store, ca_privkey, CRYPT_UNUSED); WARN_AND_RETURN_IF(status); status = export_cert(crl, argv[1]); WARN_AND_RETURN_IF(status); status = cryptDestroyCert(crl); WARN_AND_RETURN_IF(status); status = cryptKeysetClose(store); WARN_AND_RETURN_IF(status); status = cryptDestroyContext(ca_privkey); WARN_AND_RETURN_IF(status); return 0; }
static int exec_cmpcli_init(int argc, char **argv) { CRYPT_SESSION session; CRYPT_CERTIFICATE cert, cacert, req; CRYPT_CONTEXT keypair; CRYPT_KEYSET privkeys; const char *cmd, *uid, *ipwd, *crtfilename, *cacrtfilename, *kpfilename; void *crtdata; int status, data_len; if (argc != 6) { fprintf(stderr, "cmpcli argv!=6\n"); return 1; } cmd = argv[0]; uid = argv[1]; ipwd = argv[2]; crtfilename=argv[3]; cacrtfilename=argv[4]; kpfilename = argv[5]; fprintf(stderr, "uid=\"%s\" ipwd=\"%s\"\n", uid, ipwd); #if 0 crtdata = read_full_file(crtfilename, &data_len); if (!crtdata) return 1; status = cryptImportCert(crtdata, data_len, CRYPT_UNUSED, &cert); WARN_AND_RETURN_IF(status); free(crtdata); #endif crtdata = read_full_file(cacrtfilename, &data_len); if (!crtdata) return 1; status = cryptImportCert(crtdata, data_len, CRYPT_UNUSED, &cacert); WARN_AND_RETURN_IF(status); free(crtdata); status = create_keypair(&keypair, DEFAULT_PRIVKEY_LABEL); WARN_AND_RETURN_IF(status); status = cryptKeysetOpen(&privkeys, CRYPT_UNUSED, CRYPT_KEYSET_FILE, kpfilename, CRYPT_KEYOPT_CREATE); WARN_AND_RETURN_IF(status); status = cryptAddPrivateKey(privkeys, keypair, DEFAULT_PASSWORD); WARN_AND_RETURN_IF(status); status = cryptCreateCert(&req, CRYPT_UNUSED, CRYPT_CERTTYPE_REQUEST_CERT); WARN_AND_RETURN_IF(status); status = cryptSetAttribute(req, CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, keypair); WARN_AND_RETURN_IF(status); status = cryptSignCert(req, keypair); WARN_AND_RETURN_IF(status); status = cryptCreateSession(&session, CRYPT_UNUSED, CRYPT_SESSION_CMP); WARN_AND_RETURN_IF(status); status = cryptSetAttribute(session, CRYPT_SESSINFO_CMP_REQUESTTYPE, CRYPT_REQUESTTYPE_INITIALIZATION); WARN_AND_RETURN_IF(status); status = cryptSetAttribute(session, CRYPT_SESSINFO_CACERTIFICATE, cacert); WARN_AND_RETURN_IF(status); status = cryptSetAttribute(session, CRYPT_SESSINFO_REQUEST, req); WARN_AND_RETURN_IF(status); status = cryptSetAttributeString(session, CRYPT_SESSINFO_USERNAME, uid, strlen(uid)); WARN_AND_RETURN_IF(status); status = cryptSetAttributeString(session, CRYPT_SESSINFO_PASSWORD, ipwd, strlen(ipwd)); WARN_AND_RETURN_IF(status); status = cryptSetAttributeString(session, CRYPT_SESSINFO_SERVER_NAME, "127.0.0.1", 9); WARN_AND_RETURN_IF(status); status = cryptSetAttribute(session, CRYPT_SESSINFO_SERVER_PORT, 65000); WARN_AND_RETURN_IF(status); status = cryptSetAttribute(session, CRYPT_SESSINFO_ACTIVE, 1); WARN_AND_RETURN_IF(status); status = cryptGetAttribute(session, CRYPT_SESSINFO_RESPONSE, &cert); WARN_AND_RETURN_IF(status); status = export_cert(cert, crtfilename); WARN_AND_RETURN_IF(status); status = cryptAddPublicKey(privkeys, cert); WARN_AND_RETURN_IF(status); status = cryptKeysetClose(privkeys); WARN_AND_RETURN_IF(status); status = cryptDestroySession(session); WARN_AND_RETURN_IF(status); status = cryptDestroyCert(cacert); WARN_AND_RETURN_IF(status); status = cryptDestroyCert(cert); WARN_AND_RETURN_IF(status); status = cryptDestroyCert(req); WARN_AND_RETURN_IF(status); status = cryptDestroyContext(keypair); return 0; }
static int exec_sign(int argc, char **argv) { const char *id, *dbfilename, *certfilename; char cakeysfilename[4096]; CRYPT_KEYID_TYPE id_type; CRYPT_KEYSET store, cakeys; CRYPT_CERTIFICATE cert, csr; CRYPT_CONTEXT ca_privkey; int status; if (argc != 4) { fprintf(stderr, "usage: sign dbfile (-e email | -n name) certfile\n"); return 1; } dbfilename = argv[0]; certfilename = argv[3]; id = argv[2]; if (strcmp(argv[1], "-e") == 0) { id_type = CRYPT_KEYID_EMAIL; } else if (strcmp(argv[1], "-n") == 0) { id_type = CRYPT_KEYID_NAME; } else { fprintf(stderr, "usage: sign dbfile (-e email | -n name) certfile\n"); return 1; } status = cryptKeysetOpen(&store, CRYPT_UNUSED, CRYPT_KEYSET_DATABASE_STORE, dbfilename, CRYPT_KEYOPT_NONE); WARN_AND_RETURN_IF(status); status = cryptCAGetItem(store, &csr, CRYPT_CERTTYPE_CERTREQUEST, id_type, id); WARN_AND_RETURN_IF(status); snprintf(cakeysfilename, 4095, "%s.keys", dbfilename); status = cryptKeysetOpen(&cakeys, CRYPT_UNUSED, CRYPT_KEYSET_FILE, cakeysfilename, CRYPT_KEYOPT_NONE); WARN_AND_RETURN_IF(status); status = cryptGetPrivateKey(cakeys, &ca_privkey, CRYPT_KEYID_NAME, DEFAULT_CA_PRIVKEY_LABEL, DEFAULT_PASSWORD); WARN_AND_RETURN_IF(status); status = cryptKeysetClose(cakeys); WARN_AND_RETURN_IF(status); status = cryptCACertManagement(&cert, CRYPT_CERTACTION_ISSUE_CERT, store, ca_privkey, csr); if (!cryptStatusOK(status)) { int errorLocus; int errorType; cryptGetAttribute(store, CRYPT_ATTRIBUTE_ERRORLOCUS, &errorLocus); cryptGetAttribute(store, CRYPT_ATTRIBUTE_ERRORTYPE, &errorType); fprintf(stderr, "store: locus %d type %d\n", errorLocus, errorType); cryptGetAttribute(csr, CRYPT_ATTRIBUTE_ERRORLOCUS, &errorLocus); cryptGetAttribute(csr, CRYPT_ATTRIBUTE_ERRORTYPE, &errorType); fprintf(stderr, "csr: locus %d type %d\n", errorLocus, errorType); cryptGetAttribute(ca_privkey, CRYPT_ATTRIBUTE_ERRORLOCUS, &errorLocus); cryptGetAttribute(ca_privkey, CRYPT_ATTRIBUTE_ERRORTYPE, &errorType); fprintf(stderr, "ca_privkey: locus %d type %d\n", errorLocus, errorType); } WARN_AND_RETURN_IF(status); status = export_cert(cert, certfilename); WARN_AND_RETURN_IF(status); status = cryptDestroyCert(cert); WARN_AND_RETURN_IF(status); status = cryptDestroyCert(csr); WARN_AND_RETURN_IF(status); status = cryptDestroyContext(ca_privkey); WARN_AND_RETURN_IF(status); status = cryptKeysetClose(store); WARN_AND_RETURN_IF(status); return 0; }
static int exec_create(int argc, char **argv) { CRYPT_KEYSET keyset; CRYPT_CERTIFICATE cert; CRYPT_CONTEXT context; int status; const char *filename = argv[0]; char keyfilename[4096]; /* PATH_MAX */ char certfilename[4096]; /* PATH_MAX */ /* create the tables using cryptlib */ status = cryptKeysetOpen(&keyset, CRYPT_UNUSED, CRYPT_KEYSET_DATABASE_STORE, filename, CRYPT_KEYOPT_CREATE); if (!cryptStatusOK(status)) { fprintf(stderr, "cryptlib error %d while opening keyset\n", status); return 1; } status = cryptKeysetClose(keyset); if (!cryptStatusOK(status)) { fprintf(stderr, "cryptlib error %d while closing keyset\n", status); return 1; } if (opt_verbose) fprintf(stdout, "file %s created OK as cert keyset store\n", filename); /* the database has been created, but there is still no CA key * and CA cert -- now we generate it and put the CA key in a file * and import the public key & cert into the db. */ status = create_keypair(&context, DEFAULT_CA_PRIVKEY_LABEL); if (!cryptStatusOK(status)) { fprintf(stderr, "cryptlib error %d while generating CA keypair\n", status); return 1; } /* generate cert */ status = create_selfsigned_cert(context, DEFAULT_DN, &cert); if (!cryptStatusOK(status)) { fprintf(stderr, "cryptlib error %d while generating CA cert\n", status); goto err_ctx_exit; } snprintf(keyfilename, 4095, "%s.keys", filename); status = save_ca_keypair_and_cert_to_file(context, cert, keyfilename, DEFAULT_PASSWORD); /* TODO password */ if (!cryptStatusOK(status)) { fprintf(stderr, "cryptlib error %d while saving CA keypair to %s\n", status, keyfilename); goto err_ctx_exit; } if (opt_verbose) fprintf(stdout, "CA keys saved to file keyset %s\n", filename); /* save it */ snprintf(certfilename, 4095, "%s.ca.crt", filename); status = export_cert(cert, certfilename); if (!cryptStatusOK(status)) { fprintf(stderr, "cryptlib error %d while saving CA cert\n", status); goto err_cert_exit; } #if 0 /* add to store */ status = cryptKeysetOpen(&keyset, CRYPT_UNUSED, CRYPT_KEYSET_DATABASE_STORE, filename, CRYPT_KEYOPT_NONE); if (!cryptStatusOK(status)) { fprintf(stderr, "cryptlib error %d while opening CA cert store to save CA cert\n", status); goto err_cert_exit; } status = add_ca_cert_to_store(keyset, DEFAULT_DN, cert); /* status = cryptCAAddItem(keyset, cert); */ if (!cryptStatusOK(status)) { fprintf(stderr, "cryptlib error %d while saving CA cert to CA cert store\n", status); cryptKeysetClose(keyset); goto err_cert_exit; } status = cryptKeysetClose(keyset); if (!cryptStatusOK(status)) { fprintf(stderr, "cryptlib error %d while closing CA cert store\n", status); goto err_cert_exit; } if (opt_verbose) fprintf(stdout, "CA certs for %s saved to %s\n", DEFAULT_DN, filename); #endif /* cleanup */ status = cryptDestroyCert(cert); if (!cryptStatusOK(status)) { fprintf(stderr, "cryptlib error %d while destroying CA cert\n", status); goto err_ctx_exit; } status = cryptDestroyContext(context); if (!cryptStatusOK(status)) { fprintf(stderr, "cryptlib error %d while destroying CA keypair context\n", status); /* NO ERROR CASE */ return 1; } return 0; err_cert_exit: cryptDestroyCert(cert); err_ctx_exit: cryptDestroyContext(context); return 1; }
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 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); }