SECKEYPrivateKey* PrivateKeyFromPrivateKeyTemplate(SECItem* aObjID, CK_ATTRIBUTE* aTemplate, CK_ULONG aTemplateSize) { // Create a generic object with the contents of the key ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); if (!slot.get()) { return nullptr; } ScopedPK11GenericObject obj(PK11_CreateGenericObject(slot.get(), aTemplate, aTemplateSize, PR_FALSE)); if (!obj.get()) { return nullptr; } // Have NSS translate the object to a private key by inspection // and make a copy we can own ScopedSECKEYPrivateKey privKey(PK11_FindKeyByKeyID(slot.get(), aObjID, nullptr)); if (!privKey.get()) { return nullptr; } return SECKEY_CopyPrivateKey(privKey.get()); }
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; }
/* 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; }
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; }
SECKEYPrivateKey* CryptoKey::PrivateKeyFromJwk(const JsonWebKey& aJwk, const nsNSSShutDownPreventionLock& /*proofOfLock*/) { if (!aJwk.mKty.WasPassed() || !aJwk.mKty.Value().EqualsLiteral(JWK_TYPE_RSA)) { return nullptr; } // Verify that all of the required parameters are present CryptoBuffer n, e, d, p, q, dp, dq, qi; if (!aJwk.mN.WasPassed() || NS_FAILED(n.FromJwkBase64(aJwk.mN.Value())) || !aJwk.mE.WasPassed() || NS_FAILED(e.FromJwkBase64(aJwk.mE.Value())) || !aJwk.mD.WasPassed() || NS_FAILED(d.FromJwkBase64(aJwk.mD.Value())) || !aJwk.mP.WasPassed() || NS_FAILED(p.FromJwkBase64(aJwk.mP.Value())) || !aJwk.mQ.WasPassed() || NS_FAILED(q.FromJwkBase64(aJwk.mQ.Value())) || !aJwk.mDp.WasPassed() || NS_FAILED(dp.FromJwkBase64(aJwk.mDp.Value())) || !aJwk.mDq.WasPassed() || NS_FAILED(dq.FromJwkBase64(aJwk.mDq.Value())) || !aJwk.mQi.WasPassed() || NS_FAILED(qi.FromJwkBase64(aJwk.mQi.Value()))) { return nullptr; } // Compute the ID for this key // This is generated with a SHA-1 hash, so unlikely to collide ScopedSECItem nItem(n.ToSECItem()); ScopedSECItem objID(PK11_MakeIDFromPubKey(nItem.get())); if (!nItem.get() || !objID.get()) { return nullptr; } // Populate template from parameters CK_OBJECT_CLASS privateKeyValue = CKO_PRIVATE_KEY; CK_KEY_TYPE rsaValue = CKK_RSA; CK_BBOOL falseValue = CK_FALSE; CK_ATTRIBUTE keyTemplate[14] = { { CKA_CLASS, &privateKeyValue, sizeof(privateKeyValue) }, { CKA_KEY_TYPE, &rsaValue, sizeof(rsaValue) }, { CKA_TOKEN, &falseValue, sizeof(falseValue) }, { CKA_SENSITIVE, &falseValue, sizeof(falseValue) }, { CKA_PRIVATE, &falseValue, sizeof(falseValue) }, { CKA_ID, objID->data, objID->len }, { CKA_MODULUS, (void*) n.Elements(), n.Length() }, { CKA_PUBLIC_EXPONENT, (void*) e.Elements(), e.Length() }, { CKA_PRIVATE_EXPONENT, (void*) d.Elements(), d.Length() }, { CKA_PRIME_1, (void*) p.Elements(), p.Length() }, { CKA_PRIME_2, (void*) q.Elements(), q.Length() }, { CKA_EXPONENT_1, (void*) dp.Elements(), dp.Length() }, { CKA_EXPONENT_2, (void*) dq.Elements(), dq.Length() }, { CKA_COEFFICIENT, (void*) qi.Elements(), qi.Length() }, }; // Create a generic object with the contents of the key ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); if (!slot.get()) { return nullptr; } ScopedPK11GenericObject obj(PK11_CreateGenericObject(slot.get(), keyTemplate, PR_ARRAY_SIZE(keyTemplate), PR_FALSE)); if (!obj.get()) { return nullptr; } // Have NSS translate the object to a private key by inspection // and make a copy we can own ScopedSECKEYPrivateKey privKey(PK11_FindKeyByKeyID(slot.get(), objID.get(), nullptr)); if (!privKey.get()) { return nullptr; } return SECKEY_CopyPrivateKey(privKey.get()); }
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 }