static CURLcode nss_load_key(struct connectdata *conn, int sockindex, char *key_file) { PK11SlotInfo *slot; SECStatus status; CURLcode rv; struct ssl_connect_data *ssl = conn->ssl; (void)sockindex; /* unused */ rv = nss_create_object(ssl, CKO_PRIVATE_KEY, key_file, FALSE); if(CURLE_OK != rv) { PR_SetError(SEC_ERROR_BAD_KEY, 0); return rv; } slot = PK11_FindSlotByName("PEM Token #1"); if(!slot) return CURLE_SSL_CERTPROBLEM; /* This will force the token to be seen as re-inserted */ SECMOD_WaitForAnyTokenEvent(mod, 0, 0); PK11_IsPresent(slot); status = PK11_Authenticate(slot, PR_TRUE, conn->data->set.str[STRING_KEY_PASSWD]); PK11_FreeSlot(slot); return (SECSuccess == status) ? CURLE_OK : CURLE_SSL_CERTPROBLEM; }
NS_IMETHODIMP nsPK11TokenDB::FindTokenByName(const nsACString& tokenName, /*out*/ nsIPK11Token** _retval) { NS_ENSURE_ARG_POINTER(_retval); nsresult rv = BlockUntilLoadableRootsLoaded(); if (NS_FAILED(rv)) { return rv; } if (tokenName.IsEmpty()) { return NS_ERROR_ILLEGAL_VALUE; } UniquePK11SlotInfo slot( PK11_FindSlotByName(PromiseFlatCString(tokenName).get())); if (!slot) { return NS_ERROR_FAILURE; } nsCOMPtr<nsIPK11Token> token = new nsPK11Token(slot.get()); token.forget(_retval); return NS_OK; }
static int nss_load_key(struct connectdata *conn, int sockindex, char *key_file) { #ifdef HAVE_PK11_CREATEGENERICOBJECT PK11SlotInfo *slot; SECStatus status; struct ssl_connect_data *ssl = conn->ssl; if(CURLE_OK != nss_create_object(ssl, CKO_PRIVATE_KEY, key_file, FALSE)) { PR_SetError(SEC_ERROR_BAD_KEY, 0); return 0; } slot = PK11_FindSlotByName("PEM Token #1"); if(!slot) return 0; /* This will force the token to be seen as re-inserted */ SECMOD_WaitForAnyTokenEvent(mod, 0, 0); PK11_IsPresent(slot); status = PK11_Authenticate(slot, PR_TRUE, conn->data->set.str[STRING_KEY_PASSWD]); PK11_FreeSlot(slot); return (SECSuccess == status) ? 1 : 0; #else /* If we don't have PK11_CreateGenericObject then we can't load a file-based * key. */ (void)conn; /* unused */ (void)key_file; /* unused */ return 0; #endif }
static int nss_load_key(struct connectdata *conn, int sockindex, char *key_file) { #ifdef HAVE_PK11_CREATEGENERICOBJECT PK11SlotInfo * slot = NULL; CK_ATTRIBUTE *attrs; CK_ATTRIBUTE theTemplate[20]; CK_BBOOL cktrue = CK_TRUE; CK_OBJECT_CLASS objClass = CKO_PRIVATE_KEY; CK_SLOT_ID slotID; char slotname[SLOTSIZE]; struct ssl_connect_data *sslconn = &conn->ssl[sockindex]; attrs = theTemplate; /* FIXME: grok the various file types */ slotID = 1; /* hardcoded for now */ snprintf(slotname, sizeof(slotname), "PEM Token #%ld", slotID); slot = PK11_FindSlotByName(slotname); if(!slot) return 0; PK11_SETATTRS(attrs, CKA_CLASS, &objClass, sizeof(objClass) ); attrs++; PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL) ); attrs++; PK11_SETATTRS(attrs, CKA_LABEL, (unsigned char *)key_file, strlen(key_file)+1); attrs++; /* When adding an encrypted key the PKCS#11 will be set as removed */ sslconn->key = PK11_CreateGenericObject(slot, theTemplate, 3, PR_FALSE /* isPerm */); if(sslconn->key == NULL) { PR_SetError(SEC_ERROR_BAD_KEY, 0); return 0; } /* This will force the token to be seen as re-inserted */ SECMOD_WaitForAnyTokenEvent(mod, 0, 0); PK11_IsPresent(slot); /* parg is initialized in nss_Init_Tokens() */ if(PK11_Authenticate(slot, PR_TRUE, conn->data->set.str[STRING_KEY_PASSWD]) != SECSuccess) { PK11_FreeSlot(slot); return 0; } PK11_FreeSlot(slot); return 1; #else /* If we don't have PK11_CreateGenericObject then we can't load a file-based * key. */ (void)conn; /* unused */ (void)key_file; /* unused */ return 0; #endif }
static CERTCertificate *load_cert_file(sxc_client_t *sx, const char *file, struct PK11_ctx *ctx) { const char *slot_name = "PEM Token #0"; CK_OBJECT_CLASS obj_class; CK_ATTRIBUTE attrs[/* max count of attributes */ 4]; unsigned attr_cnt = 0; CK_BBOOL cktrue = CK_TRUE; SECMODModule *mod; CERTCertificate *cert = NULL; if(!file || !ctx) { sxi_seterr(sx, SXE_EARG, "NULL argument"); return NULL; } memset(ctx, 0, sizeof(*ctx)); mod = SECMOD_LoadUserModule("library=libnsspem.so name=PEM", NULL, PR_FALSE); if (!mod || !mod->loaded) { if (mod) SECMOD_DestroyModule(mod); sxi_setsyserr(sx, SXE_ECFG, "Failed to load NSS PEM library"); return NULL; } sxi_crypto_check_ver(NULL); ctx->slot = PK11_FindSlotByName(slot_name); if (ctx->slot) { obj_class = CKO_CERTIFICATE; PK11_SETATTRS(attrs, attr_cnt, CKA_CLASS, &obj_class, sizeof(obj_class)); PK11_SETATTRS(attrs, attr_cnt, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL)); PK11_SETATTRS(attrs, attr_cnt, CKA_LABEL, (unsigned char *)file, strlen(file) + 1); if(CKO_CERTIFICATE == obj_class) { CK_BBOOL *pval = &cktrue; PK11_SETATTRS(attrs, attr_cnt, CKA_TRUST, pval, sizeof(*pval)); } ctx->obj = PK11_CreateGenericObject(ctx->slot, attrs, attr_cnt, PR_FALSE); if (!ctx->obj) { sxi_seterr(sx, SXE_ECFG, "Cannot load certificate from '%s': %s, %s", file, PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT), PR_ErrorToName(PR_GetError())); return NULL; } ctx->list = PK11_ListCertsInSlot(ctx->slot); if (ctx->list) { CERTCertListNode *node = CERT_LIST_HEAD(ctx->list); cert = node ? node->cert : NULL; } } else { sxi_seterr(sx, SXE_ECFG, "Failed to initialize NSS PEM token"); return NULL; } return cert; }
/** * * Callback to pick the SSL client certificate. */ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock, struct CERTDistNamesStr *caNames, struct CERTCertificateStr **pRetCert, struct SECKEYPrivateKeyStr **pRetKey) { SECKEYPrivateKey *privKey; struct ssl_connect_data *connssl = (struct ssl_connect_data *) arg; char *nickname = connssl->client_nickname; void *proto_win = NULL; SECStatus secStatus = SECFailure; PK11SlotInfo *slot; (void)caNames; proto_win = SSL_RevealPinArg(sock); if(!nickname) return secStatus; connssl->client_cert = PK11_FindCertFromNickname(nickname, proto_win); if(connssl->client_cert) { if(!strncmp(nickname, "PEM Token", 9)) { CK_SLOT_ID slotID = 1; /* hardcoded for now */ char slotname[SLOTSIZE]; snprintf(slotname, SLOTSIZE, "PEM Token #%ld", slotID); slot = PK11_FindSlotByName(slotname); privKey = PK11_FindPrivateKeyFromCert(slot, connssl->client_cert, NULL); PK11_FreeSlot(slot); if(privKey) { secStatus = SECSuccess; } } else { privKey = PK11_FindKeyByAnyCert(connssl->client_cert, proto_win); if(privKey) secStatus = SECSuccess; } } if(secStatus == SECSuccess) { *pRetCert = connssl->client_cert; *pRetKey = privKey; } else { if(connssl->client_cert) CERT_DestroyCertificate(connssl->client_cert); connssl->client_cert = NULL; } return secStatus; }
/* Call PK11_CreateGenericObject() with the given obj_class and filename. If * the call succeeds, append the object handle to the list of objects so that * the object can be destroyed in Curl_nss_close(). */ static CURLcode nss_create_object(struct ssl_connect_data *ssl, CK_OBJECT_CLASS obj_class, const char *filename, bool cacert) { PK11SlotInfo *slot; PK11GenericObject *obj; CK_BBOOL cktrue = CK_TRUE; CK_BBOOL ckfalse = CK_FALSE; CK_ATTRIBUTE attrs[/* max count of attributes */ 4]; int attr_cnt = 0; CURLcode err = (cacert) ? CURLE_SSL_CACERT_BADFILE : CURLE_SSL_CERTPROBLEM; const int slot_id = (cacert) ? 0 : 1; char *slot_name = aprintf("PEM Token #%d", slot_id); if(!slot_name) return CURLE_OUT_OF_MEMORY; slot = PK11_FindSlotByName(slot_name); free(slot_name); if(!slot) return err; PK11_SETATTRS(attrs, attr_cnt, CKA_CLASS, &obj_class, sizeof(obj_class)); PK11_SETATTRS(attrs, attr_cnt, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL)); PK11_SETATTRS(attrs, attr_cnt, CKA_LABEL, (unsigned char *)filename, strlen(filename) + 1); if(CKO_CERTIFICATE == obj_class) { CK_BBOOL *pval = (cacert) ? (&cktrue) : (&ckfalse); PK11_SETATTRS(attrs, attr_cnt, CKA_TRUST, pval, sizeof(*pval)); } obj = PK11_CreateGenericObject(slot, attrs, attr_cnt, PR_FALSE); PK11_FreeSlot(slot); if(!obj) return err; if(!Curl_llist_insert_next(ssl->obj_list, ssl->obj_list->tail, obj)) { PK11_DestroyGenericObject(obj); return CURLE_OUT_OF_MEMORY; } if(!cacert && CKO_CERTIFICATE == obj_class) /* store reference to a client certificate */ ssl->obj_clicert = obj; return CURLE_OK; }
/************************************************************************** * * G e n e r a t e S e l f S i g n e d O b j e c t S i g n i n g C e r t * *phew*^ * */ static CERTCertificate* GenerateSelfSignedObjectSigningCert(char *nickname, CERTCertDBHandle *db, char *subject, unsigned long serial, int keysize, char *token) { CERTCertificate * cert, *temp_cert; SECItem * derCert; CERTCertificateRequest * req; PK11SlotInfo * slot = NULL; SECKEYPrivateKey * privk = NULL; SECKEYPublicKey * pubk = NULL; if ( token ) { slot = PK11_FindSlotByName(token); } else { slot = PK11_GetInternalKeySlot(); } if (slot == NULL) { PR_fprintf(errorFD, "Can't find PKCS11 slot %s\n", token ? token : ""); errorCount++; exit (ERRX); } if ( GenerateKeyPair(slot, &pubk, &privk, keysize) != SECSuccess) { FatalError("Error generating keypair."); } req = make_cert_request (subject, pubk); temp_cert = make_cert (req, serial, &req->subject); if (set_cert_type(temp_cert, NS_CERT_TYPE_OBJECT_SIGNING | NS_CERT_TYPE_OBJECT_SIGNING_CA) != SECSuccess) { FatalError("Unable to set cert type"); } derCert = sign_cert (temp_cert, privk); cert = install_cert(db, derCert, nickname); if (ChangeTrustAttributes(db, cert, ",,uC") != SECSuccess) { FatalError("Unable to change trust on generated certificate"); } /* !!! Free memory ? !!! */ PK11_FreeSlot(slot); SECKEY_DestroyPrivateKey(privk); SECKEY_DestroyPublicKey(pubk); return cert; }
/* * find a slot by it's slot number or label. If slot number is '0' any * slot is ok. */ int find_slot_by_number_and_label(pkcs11_handle_t *h, int wanted_slot_id, const char *wanted_token_label, unsigned int *slot_num) { int rv; const char *token_label = NULL; PK11SlotInfo *slot = NULL; /* we want a specific slot id, or we don't kare about the label */ if ((wanted_token_label == NULL) || (wanted_slot_id != 0)) { rv = find_slot_by_number(h, wanted_slot_id, slot_num); /* if we don't care about the label, or we failed, we're done */ if ((wanted_token_label == NULL) || (rv != 0)) { return rv; } /* verify it's the label we want */ token_label = PK11_GetTokenName(h->slot); if ((token_label != NULL) && (strcmp (wanted_token_label, token_label) == 0)) { return 0; } return -1; } /* we want a specific slot by label only */ slot = PK11_FindSlotByName(wanted_token_label); if (!slot) { return -1; } /* make sure it's in the right module */ if (h->module) { if (h->module != PK11_GetModule(slot)) { PK11_FreeSlot(slot); return -1; } } else { /* no module was specified, use the one slot came in */ h->module = SECMOD_ReferenceModule(PK11_GetModule(slot)); } h->slot = slot; /* Adopt the reference */ *slot_num = PK11_GetSlotID(h->slot); return 0; }
/* nsIPKCS11Module findSlotByName(in wstring name); */ NS_IMETHODIMP nsPKCS11ModuleDB::FindSlotByName(const char16_t *aName, nsIPKCS11Slot **_retval) { nsNSSShutDownPreventionLock locker; NS_ConvertUTF16toUTF8 aUtf8Name(aName); PK11SlotInfo *slotinfo = PK11_FindSlotByName(const_cast<char*>(aUtf8Name.get())); if (!slotinfo) return NS_ERROR_FAILURE; nsCOMPtr<nsIPKCS11Slot> slot = new nsPKCS11Slot(slotinfo); PK11_FreeSlot(slotinfo); *_retval = slot; NS_ADDREF(*_retval); return NS_OK; }
/* nsIPK11Token findTokenByName (in wchar tokenName); */ NS_IMETHODIMP nsPK11TokenDB:: FindTokenByName(const PRUnichar* tokenName, nsIPK11Token **_retval) { nsNSSShutDownPreventionLock locker; nsresult rv = NS_OK; PK11SlotInfo *slot = 0; NS_ConvertUTF16toUTF8 aUtf8TokenName(tokenName); slot = PK11_FindSlotByName(const_cast<char*>(aUtf8TokenName.get())); if (!slot) { rv = NS_ERROR_FAILURE; goto done; } *_retval = new nsPK11Token(slot); NS_ADDREF(*_retval); done: if (slot) PK11_FreeSlot(slot); return rv; }
/** * * Callback to pick the SSL client certificate. */ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock, struct CERTDistNamesStr *caNames, struct CERTCertificateStr **pRetCert, struct SECKEYPrivateKeyStr **pRetKey) { static const char pem_nickname[] = "PEM Token #1"; const char *pem_slotname = pem_nickname; struct ssl_connect_data *connssl = (struct ssl_connect_data *)arg; struct SessionHandle *data = connssl->data; const char *nickname = connssl->client_nickname; if (mod && nickname && 0 == strncmp(nickname, pem_nickname, /* length of "PEM Token" */ 9)) { /* use the cert/key provided by PEM reader */ PK11SlotInfo *slot; void *proto_win = SSL_RevealPinArg(sock); *pRetKey = NULL; *pRetCert = PK11_FindCertFromNickname(nickname, proto_win); if (NULL == *pRetCert) { failf(data, "NSS: client certificate not found: %s", nickname); return SECFailure; } slot = PK11_FindSlotByName(pem_slotname); if (NULL == slot) { failf(data, "NSS: PK11 slot not found: %s", pem_slotname); return SECFailure; } *pRetKey = PK11_FindPrivateKeyFromCert(slot, *pRetCert, NULL); PK11_FreeSlot(slot); if (NULL == *pRetKey) { failf(data, "NSS: private key not found for certificate: %s", nickname); return SECFailure; } infof(data, "NSS: client certificate: %s\n", nickname); display_cert_info(data, *pRetCert); return SECSuccess; } /* use the default NSS hook */ if (SECSuccess != NSS_GetClientAuthData((void *)nickname, sock, caNames, pRetCert, pRetKey) || NULL == *pRetCert) { if (NULL == nickname) failf(data, "NSS: client certificate not found (nickname not specified)"); else failf(data, "NSS: client certificate not found: %s", nickname); return SECFailure; } /* get certificate nickname if any */ nickname = (*pRetCert)->nickname; if (NULL == nickname) nickname = "[unknown]"; if (NULL == *pRetKey) { failf(data, "NSS: private key not found for certificate: %s", nickname); return SECFailure; } infof(data, "NSS: using client certificate: %s\n", nickname); display_cert_info(data, *pRetCert); return SECSuccess; }
static SECStatus SignAndStoreCrl(CERTSignedCrl *signCrl, CERTCertificate *cert, char *outFileName, SECOidTag hashAlgTag, int ascii, char *slotName, char *url, secuPWData *pwdata) { PK11SlotInfo *slot = NULL; PRFileDesc *outFile = NULL; SECStatus rv; SignAndEncodeFuncExitStat errCode; PORT_Assert(signCrl && (!ascii || outFileName)); if (!signCrl || (ascii && !outFileName)) { SECU_PrintError(progName, "invalid args for function " "SignAndStoreCrl\n"); return SECFailure; } if (!slotName || !PL_strcmp(slotName, "internal")) slot = PK11_GetInternalKeySlot(); else slot = PK11_FindSlotByName(slotName); if (!slot) { SECU_PrintError(progName, "can not find requested slot"); return SECFailure; } if (PK11_NeedLogin(slot)) { rv = PK11_Authenticate(slot, PR_TRUE, pwdata); if (rv != SECSuccess) goto loser; } rv = SECU_SignAndEncodeCRL(cert, signCrl, hashAlgTag, &errCode); if (rv != SECSuccess) { char* errMsg = NULL; switch (errCode) { case noKeyFound: errMsg = "No private key found of signing cert"; break; case noSignatureMatch: errMsg = "Key and Algorithm OId are do not match"; break; default: case failToEncode: errMsg = "Failed to encode crl structure"; break; case failToSign: errMsg = "Failed to sign crl structure"; break; case noMem: errMsg = "Can not allocate memory"; break; } SECU_PrintError(progName, "%s\n", errMsg); goto loser; } if (outFileName) { outFile = PR_Open(outFileName, PR_WRONLY|PR_CREATE_FILE, PR_IRUSR | PR_IWUSR); if (!outFile) { SECU_PrintError(progName, "unable to open \"%s\" for writing\n", outFileName); goto loser; } } rv = SECU_StoreCRL(slot, signCrl->derCrl, outFile, ascii, url); if (rv != SECSuccess) { SECU_PrintError(progName, "fail to save CRL\n"); } loser: if (outFile) PR_Close(outFile); if (slot) PK11_FreeSlot(slot); return rv; }
/************************************************************************ * * C h a n g e P W */ Error ChangePW(char *tokenName, char *pwFile, char *newpwFile) { char *oldpw = NULL, *newpw = NULL, *newpw2 = NULL; PK11SlotInfo *slot; Error ret = UNSPECIFIED_ERR; PRBool matching; slot = PK11_FindSlotByName(tokenName); if (!slot) { PR_fprintf(PR_STDERR, errStrings[NO_SUCH_TOKEN_ERR], tokenName); return NO_SUCH_TOKEN_ERR; } /* Get old password */ if (!PK11_NeedUserInit(slot)) { if (pwFile) { oldpw = SECU_FilePasswd(NULL, PR_FALSE, pwFile); if (PK11_CheckUserPassword(slot, oldpw) != SECSuccess) { PR_fprintf(PR_STDERR, errStrings[BAD_PW_ERR]); ret = BAD_PW_ERR; goto loser; } } else if (PK11_NeedLogin(slot)) { for (matching = PR_FALSE; !matching;) { oldpw = SECU_GetPasswordString(NULL, "Enter old password: "******"Enter new password: "******"Re-enter new password: "); if (strcmp(newpw, newpw2)) { PR_fprintf(PR_STDOUT, msgStrings[PW_MATCH_MSG]); PORT_ZFree(newpw, strlen(newpw)); PORT_ZFree(newpw2, strlen(newpw2)); } else { matching = PR_TRUE; } } } /* Change the password */ if (PK11_NeedUserInit(slot)) { if (PK11_InitPin(slot, NULL /*ssopw*/, newpw) != SECSuccess) { PR_fprintf(PR_STDERR, errStrings[CHANGEPW_FAILED_ERR], tokenName); ret = CHANGEPW_FAILED_ERR; goto loser; } } else { if (PK11_ChangePW(slot, oldpw, newpw) != SECSuccess) { PR_fprintf(PR_STDERR, errStrings[CHANGEPW_FAILED_ERR], tokenName); ret = CHANGEPW_FAILED_ERR; goto loser; } } PR_fprintf(PR_STDOUT, msgStrings[CHANGEPW_SUCCESS_MSG], tokenName); ret = SUCCESS; loser: if (oldpw) { PORT_ZFree(oldpw, strlen(oldpw)); } if (newpw) { PORT_ZFree(newpw, strlen(newpw)); } if (newpw2) { PORT_ZFree(newpw2, strlen(newpw2)); } PK11_FreeSlot(slot); return ret; }
VCardEmulError vcard_emul_init(const VCardEmulOptions *options) { SECStatus rv; PRBool ret, has_readers = PR_FALSE; VReader *vreader; VReaderEmul *vreader_emul; SECMODListLock *module_lock; SECMODModuleList *module_list; SECMODModuleList *mlp; int i; if (vcard_emul_init_called) { return VCARD_EMUL_INIT_ALREADY_INITED; } vcard_emul_init_called = 1; vreader_init(); vevent_queue_init(); if (options == NULL) { options = &default_options; } /* first initialize NSS */ if (options->nss_db) { rv = NSS_Init(options->nss_db); } else { gchar *path; #ifndef _WIN32 path = g_strdup("/etc/pki/nssdb"); #else if (g_get_system_config_dirs() == NULL || g_get_system_config_dirs()[0] == NULL) { return VCARD_EMUL_FAIL; } path = g_build_filename( g_get_system_config_dirs()[0], "pki", "nssdb", NULL); #endif rv = NSS_Init(path); g_free(path); } if (rv != SECSuccess) { return VCARD_EMUL_FAIL; } /* Set password callback function */ PK11_SetPasswordFunc(vcard_emul_get_password); /* set up soft cards emulated by software certs rather than physical cards * */ for (i = 0; i < options->vreader_count; i++) { int j; int cert_count; unsigned char **certs; int *cert_len; VCardKey **keys; PK11SlotInfo *slot; slot = PK11_FindSlotByName(options->vreader[i].name); if (slot == NULL) { continue; } vreader_emul = vreader_emul_new(slot, options->vreader[i].card_type, options->vreader[i].type_params); vreader = vreader_new(options->vreader[i].vname, vreader_emul, vreader_emul_delete); vreader_add_reader(vreader); cert_count = options->vreader[i].cert_count; ret = vcard_emul_alloc_arrays(&certs, &cert_len, &keys, options->vreader[i].cert_count); if (ret == PR_FALSE) { continue; } cert_count = 0; for (j = 0; j < options->vreader[i].cert_count; j++) { /* we should have a better way of identifying certs than by * nickname here */ CERTCertificate *cert = PK11_FindCertFromNickname( options->vreader[i].cert_name[j], NULL); if (cert == NULL) { continue; } certs[cert_count] = cert->derCert.data; cert_len[cert_count] = cert->derCert.len; keys[cert_count] = vcard_emul_make_key(slot, cert); /* this is safe because the key is still holding a cert reference */ CERT_DestroyCertificate(cert); cert_count++; } if (cert_count) { VCard *vcard = vcard_emul_make_card(vreader, certs, cert_len, keys, cert_count); vreader_insert_card(vreader, vcard); vcard_emul_init_series(vreader, vcard); /* allow insertion and removal of soft cards */ vreader_emul->saved_vcard = vcard_reference(vcard); vcard_free(vcard); vreader_free(vreader); has_readers = PR_TRUE; } g_free(certs); g_free(cert_len); g_free(keys); } /* if we aren't suppose to use hw, skip looking up hardware tokens */ if (!options->use_hw) { nss_emul_init = has_readers; return has_readers ? VCARD_EMUL_OK : VCARD_EMUL_FAIL; } /* make sure we have some PKCS #11 module loaded */ module_lock = SECMOD_GetDefaultModuleListLock(); module_list = SECMOD_GetDefaultModuleList(); SECMOD_GetReadLock(module_lock); for (mlp = module_list; mlp; mlp = mlp->next) { SECMODModule *module = mlp->module; if (module_has_removable_hw_slots(module)) { break; } } SECMOD_ReleaseReadLock(module_lock); /* now examine all the slots, finding which should be readers */ /* We should control this with options. For now we mirror out any * removable hardware slot */ default_card_type = options->hw_card_type; default_type_params = g_strdup(options->hw_type_params); SECMOD_GetReadLock(module_lock); for (mlp = module_list; mlp; mlp = mlp->next) { SECMODModule *module = mlp->module; /* Ignore the internal module */ if (module == NULL || module == SECMOD_GetInternalModule()) { continue; } for (i = 0; i < module->slotCount; i++) { PK11SlotInfo *slot = module->slots[i]; /* only map removable HW slots */ if (slot == NULL || !PK11_IsRemovable(slot) || !PK11_IsHW(slot)) { continue; } if (strcmp("E-Gate 0 0", PK11_GetSlotName(slot)) == 0) { /* * coolkey <= 1.1.0-20 emulates this reader if it can't find * any hardware readers. This causes problems, warn user of * problems. */ fprintf(stderr, "known bad coolkey version - see " "https://bugzilla.redhat.com/show_bug.cgi?id=802435\n"); continue; } vreader_emul = vreader_emul_new(slot, options->hw_card_type, options->hw_type_params); vreader = vreader_new(PK11_GetSlotName(slot), vreader_emul, vreader_emul_delete); vreader_add_reader(vreader); if (PK11_IsPresent(slot)) { VCard *vcard; vcard = vcard_emul_mirror_card(vreader); vreader_insert_card(vreader, vcard); vcard_emul_init_series(vreader, vcard); vcard_free(vcard); } } vcard_emul_new_event_thread(module); } SECMOD_ReleaseReadLock(module_lock); nss_emul_init = PR_TRUE; return VCARD_EMUL_OK; }
nsresult nsPKCS12Blob::ImportFromFileHelper(nsILocalFile *file, nsPKCS12Blob::ImportMode aImportMode, nsPKCS12Blob::RetryReason &aWantRetry) { nsNSSShutDownPreventionLock locker; nsresult rv; SECStatus srv = SECSuccess; SEC_PKCS12DecoderContext *dcx = NULL; SECItem unicodePw; PK11SlotInfo *slot=nsnull; nsXPIDLString tokenName; unicodePw.data = NULL; aWantRetry = rr_do_not_retry; if (aImportMode == im_try_zero_length_secitem) { unicodePw.len = 0; } else { // get file password (unicode) rv = getPKCS12FilePassword(&unicodePw); if (NS_FAILED(rv)) goto finish; if (unicodePw.data == NULL) { handleError(PIP_PKCS12_USER_CANCELED); return NS_OK; } } mToken->GetTokenName(getter_Copies(tokenName)); { NS_ConvertUTF16toUTF8 tokenNameCString(tokenName); slot = PK11_FindSlotByName(tokenNameCString.get()); } if (!slot) { srv = SECFailure; goto finish; } // initialize the decoder dcx = SEC_PKCS12DecoderStart(&unicodePw, slot, NULL, digest_open, digest_close, digest_read, digest_write, this); if (!dcx) { srv = SECFailure; goto finish; } // read input file and feed it to the decoder rv = inputToDecoder(dcx, file); if (NS_FAILED(rv)) { if (NS_ERROR_ABORT == rv) { // inputToDecoder indicated a NSS error srv = SECFailure; } goto finish; } // verify the blob srv = SEC_PKCS12DecoderVerify(dcx); if (srv) goto finish; // validate bags srv = SEC_PKCS12DecoderValidateBags(dcx, nickname_collision); if (srv) goto finish; // import cert and key srv = SEC_PKCS12DecoderImportBags(dcx); if (srv) goto finish; // Later - check to see if this should become default email cert handleError(PIP_PKCS12_RESTORE_OK); finish: // If srv != SECSuccess, NSS probably set a specific error code. // We should use that error code instead of inventing a new one // for every error possible. if (srv != SECSuccess) { if (SEC_ERROR_BAD_PASSWORD == PORT_GetError()) { if (unicodePw.len == sizeof(PRUnichar)) { // no password chars available, // unicodeToItem allocated space for the trailing zero character only. aWantRetry = rr_auto_retry_empty_password_flavors; } else { aWantRetry = rr_bad_password; handleError(PIP_PKCS12_NSS_ERROR); } } else { handleError(PIP_PKCS12_NSS_ERROR); } } else if (NS_FAILED(rv)) { handleError(PIP_PKCS12_RESTORE_FAILED); } if (slot) PK11_FreeSlot(slot); // finish the decoder if (dcx) SEC_PKCS12DecoderFinish(dcx); SECITEM_ZfreeItem(&unicodePw, false); return NS_OK; }
VCardEmulError vcard_emul_init(const VCardEmulOptions *options) { SECStatus rv; PRBool ret, has_readers = PR_FALSE, need_coolkey_module; VReader *vreader; VReaderEmul *vreader_emul; SECMODListLock *module_lock; SECMODModuleList *module_list; SECMODModuleList *mlp; int i; if (vcard_emul_init_called) { return VCARD_EMUL_INIT_ALREADY_INITED; } vcard_emul_init_called = 1; vreader_init(); vevent_queue_init(); if (options == NULL) { options = &default_options; } /* first initialize NSS */ if (options->nss_db) { rv = NSS_Init(options->nss_db); } else { rv = NSS_Init("sql:/etc/pki/nssdb"); } if (rv != SECSuccess) { return VCARD_EMUL_FAIL; } /* Set password callback function */ PK11_SetPasswordFunc(vcard_emul_get_password); /* set up soft cards emulated by software certs rather than physical cards * */ for (i = 0; i < options->vreader_count; i++) { int j; int cert_count; unsigned char **certs; int *cert_len; VCardKey **keys; PK11SlotInfo *slot; slot = PK11_FindSlotByName(options->vreader[i].name); if (slot == NULL) { continue; } vreader_emul = vreader_emul_new(slot, options->vreader[i].card_type, options->vreader[i].type_params); vreader = vreader_new(options->vreader[i].vname, vreader_emul, vreader_emul_delete); vreader_add_reader(vreader); cert_count = options->vreader[i].cert_count; ret = vcard_emul_alloc_arrays(&certs, &cert_len, &keys, options->vreader[i].cert_count); if (ret == PR_FALSE) { continue; } cert_count = 0; for (j = 0; j < options->vreader[i].cert_count; j++) { /* we should have a better way of identifying certs than by * nickname here */ CERTCertificate *cert = PK11_FindCertFromNickname( options->vreader[i].cert_name[j], NULL); if (cert == NULL) { continue; } certs[cert_count] = cert->derCert.data; cert_len[cert_count] = cert->derCert.len; keys[cert_count] = vcard_emul_make_key(slot, cert); /* this is safe because the key is still holding a cert reference */ CERT_DestroyCertificate(cert); cert_count++; } if (cert_count) { VCard *vcard = vcard_emul_make_card(vreader, certs, cert_len, keys, cert_count); vreader_insert_card(vreader, vcard); vcard_emul_init_series(vreader, vcard); /* allow insertion and removal of soft cards */ vreader_emul->saved_vcard = vcard_reference(vcard); vcard_free(vcard); vreader_free(vreader); has_readers = PR_TRUE; } g_free(certs); g_free(cert_len); g_free(keys); } /* if we aren't suppose to use hw, skip looking up hardware tokens */ if (!options->use_hw) { nss_emul_init = has_readers; return has_readers ? VCARD_EMUL_OK : VCARD_EMUL_FAIL; } /* make sure we have some PKCS #11 module loaded */ module_lock = SECMOD_GetDefaultModuleListLock(); module_list = SECMOD_GetDefaultModuleList(); need_coolkey_module = !has_readers; SECMOD_GetReadLock(module_lock); for (mlp = module_list; mlp; mlp = mlp->next) { SECMODModule *module = mlp->module; if (module_has_removable_hw_slots(module)) { need_coolkey_module = PR_FALSE; break; } } SECMOD_ReleaseReadLock(module_lock); if (need_coolkey_module) { SECMODModule *module; module = SECMOD_LoadUserModule( (char *)"library=libcoolkeypk11.so name=Coolkey", NULL, PR_FALSE); if (module == NULL) { return VCARD_EMUL_FAIL; } SECMOD_DestroyModule(module); /* free our reference, Module will still * be on the list. * until we destroy it */ } /* now examine all the slots, finding which should be readers */ /* We should control this with options. For now we mirror out any * removable hardware slot */ default_card_type = options->hw_card_type; default_type_params = strdup(options->hw_type_params); SECMOD_GetReadLock(module_lock); for (mlp = module_list; mlp; mlp = mlp->next) { SECMODModule *module = mlp->module; PRBool has_emul_slots = PR_FALSE; if (module == NULL) { continue; } for (i = 0; i < module->slotCount; i++) { PK11SlotInfo *slot = module->slots[i]; /* only map removable HW slots */ if (slot == NULL || !PK11_IsRemovable(slot) || !PK11_IsHW(slot)) { continue; } vreader_emul = vreader_emul_new(slot, options->hw_card_type, options->hw_type_params); vreader = vreader_new(PK11_GetSlotName(slot), vreader_emul, vreader_emul_delete); vreader_add_reader(vreader); has_readers = PR_TRUE; has_emul_slots = PR_TRUE; if (PK11_IsPresent(slot)) { VCard *vcard; vcard = vcard_emul_mirror_card(vreader); vreader_insert_card(vreader, vcard); vcard_emul_init_series(vreader, vcard); vcard_free(vcard); } } if (has_emul_slots) { vcard_emul_new_event_thread(module); } } SECMOD_ReleaseReadLock(module_lock); nss_emul_init = has_readers; return VCARD_EMUL_OK; }
/* * CreatePk11PinStore */ int CreatePk11PinStore(Pk11PinStore **out, const char *tokenName, const char *pin) { int err = PIN_SUCCESS; Pk11PinStore *store; do { store = (Pk11PinStore*)malloc(sizeof(Pk11PinStore)); if (store == 0) { err = PIN_NOMEMORY; break; } /* Low-level init */ store->key = 0; store->params = 0; store->crypt = 0; /* Use the tokenName to find a PKCS11 slot */ store->slot = PK11_FindSlotByName((char *)tokenName); if (store->slot == 0) { err = PIN_NOSUCHTOKEN; break; } /* Check the password/PIN. This allows access to the token */ { SECStatus rv = PK11_CheckUserPassword(store->slot, (char *)pin); if (rv == SECSuccess) ; else if (rv == SECWouldBlock) { /* NSS returns a blocking error when the pin is wrong */ err = PIN_INCORRECTPW; break; } else { err = PIN_SYSTEMERROR; break; } } /* Find the mechanism that this token can do */ { const mech_item *tp; store->mech = 0; for(tp = table;tp < &table[MECH_TABLE_SIZE];tp++) { if (PK11_DoesMechanism(store->slot, tp->type)) { store->mech = (mech_item *)tp; break; } } /* Default to a mechanism (probably on the internal token */ if (store->mech == 0) { store->mech = &dflt_mech; } } /* Generate a key and parameters to do the encryption */ #if NSS_VMAJOR >= 3 && (NSS_VMINOR <= 9 || (NSS_VMINOR <= 10 && NSS_VPATCH == 0)) store->key = PK11_KeyGen(store->slot, store->mech->type, 0, 0, 0); #else store->key = PK11_TokenKeyGenWithFlags(store->slot, store->mech->type, NULL, 0, NULL, CKF_ENCRYPT|CKF_DECRYPT, PR_FALSE, NULL); #endif if (store->key == 0) { /* PR_SetError(xxx); */ err = PIN_SYSTEMERROR; break; } store->params = PK11_GenerateNewParam(store->mech->type, store->key); if (store->params == 0) { err = PIN_SYSTEMERROR; break; } /* Compute the size of the encrypted data including necessary padding */ { int blocksize = PK11_GetBlockSize(store->mech->type, 0); store->length = strlen(pin)+1; /* Compute padded size - 0 means stream cipher */ if (blocksize != 0) { store->length += blocksize - (store->length % blocksize); } store->crypt = (unsigned char *)malloc(store->length); if (!store->crypt) { err = PIN_NOMEMORY; break; } } /* Encrypt */ { unsigned char *plain; PK11Context *ctx; SECStatus rv; int outLen; plain = (unsigned char *)malloc(store->length); if (!plain) { err = PIN_NOMEMORY; break; } /* Pad with 0 bytes */ memset(plain, 0, store->length); strcpy((char *)plain, pin); ctx = PK11_CreateContextBySymKey(store->mech->type, CKA_ENCRYPT, store->key, store->params); if (!ctx) { err = PIN_SYSTEMERROR; break; } do { rv = PK11_CipherOp(ctx, store->crypt, &outLen, store->length, plain, store->length); if (rv) break; rv = PK11_Finalize(ctx); } while(0); PK11_DestroyContext(ctx, PR_TRUE); memset(plain, 0, store->length); free(plain); if (rv) err = PIN_SYSTEMERROR; } } while(0); if (err) { DestroyPk11PinStore(store); store = 0; } *out = store; return err; }
static char * getPin(SVRCOREPinObj *ctx, const char *tokenName, PRBool retry) { SVRCOREFilePinObj *obj = (SVRCOREFilePinObj*)ctx; PK11SlotInfo *slot; int is_internal_token = 0; FILE *pinfile = 0; char *res = 0; /* In really bad situations, where we cannot allocate memory * for a bad PIN list, the entire PIN object is disabled. */ if (obj->disabled) return 0; /* * If the application is retrying the PIN, the one in the file is * probably wrong. It's important that we avoid returning this * PIN to the caller each time, since that will result in disabling * the token. */ { Node *p; for(p = obj->badPinList;p;p = p->next) if (strcmp(p->tokenName, tokenName) == 0) break; if (p) return 0; } /* Mark it as bad (in the hash table) so that we remember * to never return it again. */ if (retry) { Node *ent = 0; do { ent = (Node *)malloc(sizeof (Node)); if (!ent) break; ent->tokenName = strdup(tokenName); if (!ent->tokenName) { free(ent); ent = 0; } } while(0); /* If adding fails, disable the whole object */ if (!ent) { obj->disabled = PR_TRUE; } if (ent) { /* Add to list */ ent->next = obj->badPinList; obj->badPinList = ent; } return 0; } slot = PK11_FindSlotByName((char *)tokenName); if (slot) { is_internal_token = PK11_IsInternal(slot); PK11_FreeSlot(slot); } do { char line[128]; pinfile = fopen(obj->filename, "rt"); if (!pinfile) break; /* Read lines from the file */ while(fgets(line, sizeof line, pinfile)) { char *pin; char *delim; /* Find the ":" */ delim = strchr(line, ':'); if (!delim) continue; /* Terminate name field and skip ";" */ *delim++ = 0; if (strcmp(line, tokenName) == 0 || (is_internal_token && (strcmp(line, "Communicator Certificate DB") == 0 || strcmp(line, "Internal (Software) Token") == 0))) { pin = delim; delim = strchr(pin, '\n'); if (delim) *delim = 0; res = strdup(pin); break; } } /* Clear any sensitive data */ memset(line, 0, sizeof line); } while(0); if (pinfile) fclose(pinfile); return res; }
static int nss_load_cert(struct ssl_connect_data *ssl, const char *filename, PRBool cacert) { #ifdef HAVE_PK11_CREATEGENERICOBJECT CK_SLOT_ID slotID; PK11SlotInfo * slot = NULL; CK_ATTRIBUTE *attrs; CK_ATTRIBUTE theTemplate[20]; CK_BBOOL cktrue = CK_TRUE; CK_BBOOL ckfalse = CK_FALSE; CK_OBJECT_CLASS objClass = CKO_CERTIFICATE; char slotname[SLOTSIZE]; #endif CERTCertificate *cert; char *nickname = NULL; char *n = NULL; /* If there is no slash in the filename it is assumed to be a regular * NSS nickname. */ if(is_file(filename)) { n = strrchr(filename, '/'); if(n) n++; if(!mod) return 1; } else { /* A nickname from the NSS internal database */ if(cacert) return 0; /* You can't specify an NSS CA nickname this way */ nickname = strdup(filename); if(!nickname) return 0; goto done; } #ifdef HAVE_PK11_CREATEGENERICOBJECT attrs = theTemplate; /* All CA and trust objects go into slot 0. Other slots are used * for storing certificates. With each new user certificate we increment * the slot count. We only support 1 user certificate right now. */ if(cacert) slotID = 0; else slotID = 1; snprintf(slotname, SLOTSIZE, "PEM Token #%ld", slotID); nickname = aprintf("PEM Token #%ld:%s", slotID, n); if(!nickname) return 0; slot = PK11_FindSlotByName(slotname); if(!slot) { free(nickname); return 0; } PK11_SETATTRS(attrs, CKA_CLASS, &objClass, sizeof(objClass) ); attrs++; PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL) ); attrs++; PK11_SETATTRS(attrs, CKA_LABEL, (unsigned char *)filename, strlen(filename)+1); attrs++; if(cacert) { PK11_SETATTRS(attrs, CKA_TRUST, &cktrue, sizeof(CK_BBOOL) ); } else { PK11_SETATTRS(attrs, CKA_TRUST, &ckfalse, sizeof(CK_BBOOL) ); } attrs++; /* This load the certificate in our PEM module into the appropriate * slot. */ ssl->cacert[slotID] = PK11_CreateGenericObject(slot, theTemplate, 4, PR_FALSE /* isPerm */); PK11_FreeSlot(slot); if(ssl->cacert[slotID] == NULL) { free(nickname); return 0; } #else /* We don't have PK11_CreateGenericObject but a file-based cert was passed * in. We need to fail. */ return 0; #endif done: /* Double-check that the certificate or nickname requested exists in * either the token or the NSS certificate database. */ if(!cacert) { cert = PK11_FindCertFromNickname((char *)nickname, NULL); /* An invalid nickname was passed in */ if(cert == NULL) { free(nickname); PR_SetError(SEC_ERROR_UNKNOWN_CERT, 0); return 0; } CERT_DestroyCertificate(cert); } free(nickname); return 1; }
/* * SVRCORE_CreatePk11PinStore */ SVRCOREError SVRCORE_CreatePk11PinStore( SVRCOREPk11PinStore **out, const char *tokenName, const char *pin) { SVRCOREError err; SVRCOREPk11PinStore *store; do { err = SVRCORE_Success; store = (SVRCOREPk11PinStore*)malloc(sizeof *store); if (store == 0) { err = SVRCORE_NoMemory_Error; break; } /* Low-level init */ store->slot = 0; store->key = 0; store->params = 0; store->crypt = 0; /* Use the tokenName to find a PKCS11 slot */ store->slot = PK11_FindSlotByName((char *)tokenName); if (store->slot == 0) { err = SVRCORE_NoSuchToken_Error; break; } /* Check the password/PIN. This allows access to the token */ { SECStatus rv = PK11_CheckUserPassword(store->slot, (char *)pin); if (rv == SECSuccess) ; else if (rv == SECWouldBlock) { err = SVRCORE_IncorrectPassword_Error; break; } else { err = SVRCORE_System_Error; break; } } /* Find the mechanism that this token can do */ { const mech_item *tp; store->mech = 0; for(tp = table;tp < &table[MECH_TABLE_SIZE];tp++) { if (PK11_DoesMechanism(store->slot, tp->type)) { store->mech = tp; break; } } /* Default to a mechanism (probably on the internal token */ if (store->mech == 0) store->mech = &dflt_mech; } /* Generate a key and parameters to do the encryption */ store->key = PK11_TokenKeyGenWithFlags(store->slot, store->mech->type, 0, 0, 0, CKF_ENCRYPT|CKF_DECRYPT, 0, 0); if (store->key == 0) { /* PR_SetError(xxx); */ err = SVRCORE_System_Error; break; } store->params = PK11_GenerateNewParam(store->mech->type, store->key); if (store->params == 0) { err = SVRCORE_System_Error; break; } /* Compute the size of the encrypted data including necessary padding */ { int blocksize = PK11_GetBlockSize(store->mech->type, 0); store->length = strlen(pin)+1; /* Compute padded size - 0 means stream cipher */ if (blocksize != 0) { store->length += blocksize - (store->length % blocksize); } store->crypt = (unsigned char *)malloc(store->length); if (!store->crypt) { err = SVRCORE_NoMemory_Error; break; } } /* Encrypt */ { unsigned char *plain; PK11Context *ctx; SECStatus rv; int outLen; plain = (unsigned char *)malloc(store->length); if (!plain) { err = SVRCORE_NoMemory_Error; break; } /* Pad with 0 bytes */ memset(plain, 0, store->length); strcpy((char *)plain, pin); ctx = PK11_CreateContextBySymKey(store->mech->type, CKA_ENCRYPT, store->key, store->params); if (!ctx) { err = SVRCORE_System_Error; break; } do { rv = PK11_CipherOp(ctx, store->crypt, &outLen, store->length, plain, store->length); if (rv) break; rv = PK11_Finalize(ctx); } while(0); PK11_DestroyContext(ctx, PR_TRUE); memset(plain, 0, store->length); free(plain); if (rv) err = SVRCORE_System_Error; } } while(0); if (err) { SVRCORE_DestroyPk11PinStore(store); store = 0; } *out = store; return err; }
/** * * Callback to pick the SSL client certificate. */ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock, struct CERTDistNamesStr *caNames, struct CERTCertificateStr **pRetCert, struct SECKEYPrivateKeyStr **pRetKey) { struct ssl_connect_data *connssl = (struct ssl_connect_data *)arg; struct SessionHandle *data = connssl->data; const char *nickname = connssl->client_nickname; if(connssl->obj_clicert) { /* use the cert/key provided by PEM reader */ static const char pem_slotname[] = "PEM Token #1"; SECItem cert_der = { 0, NULL, 0 }; void *proto_win = SSL_RevealPinArg(sock); struct CERTCertificateStr *cert; struct SECKEYPrivateKeyStr *key; PK11SlotInfo *slot = PK11_FindSlotByName(pem_slotname); if(NULL == slot) { failf(data, "NSS: PK11 slot not found: %s", pem_slotname); return SECFailure; } if(PK11_ReadRawAttribute(PK11_TypeGeneric, connssl->obj_clicert, CKA_VALUE, &cert_der) != SECSuccess) { failf(data, "NSS: CKA_VALUE not found in PK11 generic object"); PK11_FreeSlot(slot); return SECFailure; } cert = PK11_FindCertFromDERCertItem(slot, &cert_der, proto_win); SECITEM_FreeItem(&cert_der, PR_FALSE); if(NULL == cert) { failf(data, "NSS: client certificate from file not found"); PK11_FreeSlot(slot); return SECFailure; } key = PK11_FindPrivateKeyFromCert(slot, cert, NULL); PK11_FreeSlot(slot); if(NULL == key) { failf(data, "NSS: private key from file not found"); CERT_DestroyCertificate(cert); return SECFailure; } infof(data, "NSS: client certificate from file\n"); display_cert_info(data, cert); *pRetCert = cert; *pRetKey = key; return SECSuccess; } /* use the default NSS hook */ if(SECSuccess != NSS_GetClientAuthData((void *)nickname, sock, caNames, pRetCert, pRetKey) || NULL == *pRetCert) { if(NULL == nickname) failf(data, "NSS: client certificate not found (nickname not " "specified)"); else failf(data, "NSS: client certificate not found: %s", nickname); return SECFailure; } /* get certificate nickname if any */ nickname = (*pRetCert)->nickname; if(NULL == nickname) nickname = "[unknown]"; if(NULL == *pRetKey) { failf(data, "NSS: private key not found for certificate: %s", nickname); return SECFailure; } infof(data, "NSS: using client certificate: %s\n", nickname); display_cert_info(data, *pRetCert); return SECSuccess; }
static int nss_load_key(struct connectdata *conn, char *key_file) { #ifdef HAVE_PK11_CREATEGENERICOBJECT PK11SlotInfo * slot = NULL; PK11GenericObject *rv; CK_ATTRIBUTE *attrs; CK_ATTRIBUTE theTemplate[20]; CK_BBOOL cktrue = CK_TRUE; CK_OBJECT_CLASS objClass = CKO_PRIVATE_KEY; CK_SLOT_ID slotID; char *slotname = NULL; pphrase_arg_t *parg = NULL; attrs = theTemplate; /* FIXME: grok the various file types */ slotID = 1; /* hardcoded for now */ slotname = (char *)malloc(SLOTSIZE); snprintf(slotname, SLOTSIZE, "PEM Token #%ld", slotID); slot = PK11_FindSlotByName(slotname); free(slotname); if(!slot) return 0; PK11_SETATTRS(attrs, CKA_CLASS, &objClass, sizeof(objClass) ); attrs++; PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL) ); attrs++; PK11_SETATTRS(attrs, CKA_LABEL, (unsigned char *)key_file, strlen(key_file)+1); attrs++; /* When adding an encrypted key the PKCS#11 will be set as removed */ rv = PK11_CreateGenericObject(slot, theTemplate, 3, PR_FALSE /* isPerm */); if(rv == NULL) { PR_SetError(SEC_ERROR_BAD_KEY, 0); return 0; } /* This will force the token to be seen as re-inserted */ SECMOD_WaitForAnyTokenEvent(mod, 0, 0); PK11_IsPresent(slot); parg = (pphrase_arg_t *) malloc(sizeof(*parg)); parg->retryCount = 0; parg->data = conn->data; /* parg is initialized in nss_Init_Tokens() */ if(PK11_Authenticate(slot, PR_TRUE, parg) != SECSuccess) { free(parg); return 0; } free(parg); return 1; #else /* If we don't have PK11_CreateGenericObject then we can't load a file-based * key. */ (void)conn; /* unused */ (void)key_file; /* unused */ return 0; #endif }