/* * find a module by name and delete it off the module list */ SECStatus SECMOD_DeleteInternalModule(const char *name) { SECMODModuleList *mlp; SECMODModuleList **mlpp; SECStatus rv = SECFailure; if (pendingModule) { PORT_SetError(SEC_ERROR_MODULE_STUCK); return rv; } if (!moduleLock) { PORT_SetError(SEC_ERROR_NOT_INITIALIZED); return rv; } SECMOD_GetWriteLock(moduleLock); for(mlpp = &modules,mlp = modules; mlp != NULL; mlpp = &mlp->next, mlp = *mlpp) { if (PORT_Strcmp(name,mlp->module->commonName) == 0) { /* don't delete the internal module */ if (mlp->module->internal) { SECMOD_RemoveList(mlpp,mlp); rv = STAN_RemoveModuleFromDefaultTrustDomain(mlp->module); } break; } } SECMOD_ReleaseWriteLock(moduleLock); if (rv == SECSuccess) { SECMODModule *newModule,*oldModule; if (mlp->module->isFIPS) { newModule = SECMOD_CreateModule(NULL, SECMOD_INT_NAME, NULL, SECMOD_INT_FLAGS); } else { newModule = SECMOD_CreateModule(NULL, SECMOD_FIPS_NAME, NULL, SECMOD_FIPS_FLAGS); } if (newModule) { PK11SlotInfo *slot; newModule->libraryParams = PORT_ArenaStrdup(newModule->arena,mlp->module->libraryParams); /* if an explicit internal key slot has been set, reset it */ slot = pk11_SwapInternalKeySlot(NULL); if (slot) { secmod_SetInternalKeySlotFlag(newModule, PR_TRUE); } rv = SECMOD_AddModule(newModule); if (rv != SECSuccess) { /* load failed, restore the internal key slot */ pk11_SetInternalKeySlot(slot); SECMOD_DestroyModule(newModule); newModule = NULL; } /* free the old explicit internal key slot, we now have a new one */ if (slot) { PK11_FreeSlot(slot); } } if (newModule == NULL) { SECMODModuleList *last = NULL,*mlp2; /* we're in pretty deep trouble if this happens...Security * not going to work well... try to put the old module back on * the list */ SECMOD_GetWriteLock(moduleLock); for(mlp2 = modules; mlp2 != NULL; mlp2 = mlp->next) { last = mlp2; } if (last == NULL) { modules = mlp; } else { SECMOD_AddList(last,mlp,NULL); } SECMOD_ReleaseWriteLock(moduleLock); return SECFailure; } pendingModule = oldModule = internalModule; internalModule = NULL; SECMOD_DestroyModule(oldModule); SECMOD_DeletePermDB(mlp->module); SECMOD_DestroyModuleListElement(mlp); internalModule = newModule; /* adopt the module */ } return rv; }
/* * for 3.4 we continue to use the old SECMODModule structure */ SECMODModule * SECMOD_CreateModuleEx(const char *library, const char *moduleName, const char *parameters, const char *nss, const char *config) { SECMODModule *mod; SECStatus rv; char *slotParams,*ciphers; /* pk11pars.h still does not have const char * interfaces */ char *nssc = (char *)nss; char *configc = NULL; if (config) { configc = PORT_Strdup(config); /* no const */ } rv = applyCryptoPolicy(configc); if (configc) PORT_Free(configc); /* do not load the module if policy parsing fails */ if (rv != SECSuccess) { return NULL; } mod = secmod_NewModule(); if (mod == NULL) return NULL; mod->commonName = PORT_ArenaStrdup(mod->arena,moduleName ? moduleName : ""); if (library) { mod->dllName = PORT_ArenaStrdup(mod->arena,library); } /* new field */ if (parameters) { mod->libraryParams = PORT_ArenaStrdup(mod->arena,parameters); } mod->internal = NSSUTIL_ArgHasFlag("flags","internal",nssc); mod->isFIPS = NSSUTIL_ArgHasFlag("flags","FIPS",nssc); mod->isCritical = NSSUTIL_ArgHasFlag("flags","critical",nssc); slotParams = NSSUTIL_ArgGetParamValue("slotParams",nssc); mod->slotInfo = NSSUTIL_ArgParseSlotInfo(mod->arena,slotParams, &mod->slotInfoCount); if (slotParams) PORT_Free(slotParams); /* new field */ mod->trustOrder = NSSUTIL_ArgReadLong("trustOrder",nssc, NSSUTIL_DEFAULT_TRUST_ORDER,NULL); /* new field */ mod->cipherOrder = NSSUTIL_ArgReadLong("cipherOrder",nssc, NSSUTIL_DEFAULT_CIPHER_ORDER,NULL); /* new field */ mod->isModuleDB = NSSUTIL_ArgHasFlag("flags","moduleDB",nssc); mod->moduleDBOnly = NSSUTIL_ArgHasFlag("flags","moduleDBOnly",nssc); if (mod->moduleDBOnly) mod->isModuleDB = PR_TRUE; /* we need more bits, but we also want to preserve binary compatibility * so we overload the isModuleDB PRBool with additional flags. * These flags are only valid if mod->isModuleDB is already set. * NOTE: this depends on the fact that PRBool is at least a char on * all platforms. These flags are only valid if moduleDB is set, so * code checking if (mod->isModuleDB) will continue to work correctly. */ if (mod->isModuleDB) { char flags = SECMOD_FLAG_MODULE_DB_IS_MODULE_DB; if (NSSUTIL_ArgHasFlag("flags","skipFirst",nssc)) { flags |= SECMOD_FLAG_MODULE_DB_SKIP_FIRST; } if (NSSUTIL_ArgHasFlag("flags","defaultModDB",nssc)) { flags |= SECMOD_FLAG_MODULE_DB_DEFAULT_MODDB; } /* additional moduleDB flags could be added here in the future */ mod->isModuleDB = (PRBool) flags; } if (mod->internal) { char flags = SECMOD_FLAG_INTERNAL_IS_INTERNAL; if (NSSUTIL_ArgHasFlag("flags", "internalKeySlot", nssc)) { flags |= SECMOD_FLAG_INTERNAL_KEY_SLOT; } mod->internal = (PRBool) flags; } ciphers = NSSUTIL_ArgGetParamValue("ciphers",nssc); NSSUTIL_ArgParseCipherFlags(&mod->ssl[0],ciphers); if (ciphers) PORT_Free(ciphers); secmod_PrivateModuleCount++; return mod; }
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); }