/* * check the consistancy and initialize a Private Key Object */ static CK_RV lg_createPrivateKeyObject(SDB *sdb, CK_KEY_TYPE key_type, CK_OBJECT_HANDLE *handle, const CK_ATTRIBUTE *templ, CK_ULONG count) { NSSLOWKEYPrivateKey *privKey; char *label; SECStatus rv = SECSuccess; CK_RV crv = CKR_DEVICE_ERROR; SECItem pubKey; NSSLOWKEYDBHandle *keyHandle = lg_getKeyDB(sdb); if (keyHandle == NULL) { return CKR_TOKEN_WRITE_PROTECTED; } privKey = lg_mkPrivKey(sdb, templ, count, key_type, &crv); if (privKey == NULL) return crv; label = lg_getString(CKA_LABEL, templ, count); crv = lg_Attribute2SSecItem(NULL, CKA_NETSCAPE_DB, templ, count, &pubKey); if (crv != CKR_OK) { crv = CKR_TEMPLATE_INCOMPLETE; rv = SECFailure; goto fail; } #ifdef notdef if (keyHandle->version != 3) { unsigned char buf[SHA1_LENGTH]; SHA1_HashBuf(buf, pubKey.data, pubKey.len); PORT_Memcpy(pubKey.data, buf, sizeof(buf)); pubKey.len = sizeof(buf); } #endif /* get the key type */ if (key_type == CKK_RSA) { rv = RSA_PrivateKeyCheck(&privKey->u.rsa); if (rv == SECFailure) { goto fail; } } rv = nsslowkey_StoreKeyByPublicKey(keyHandle, privKey, &pubKey, label, sdb /*->password*/); fail: if (label) PORT_Free(label); *handle = lg_mkHandle(sdb, &pubKey, LG_TOKEN_TYPE_PRIV); if (pubKey.data) PORT_Free(pubKey.data); lg_nsslowkey_DestroyPrivateKey(privKey); if (rv != SECSuccess) return crv; return CKR_OK; }
static DB * lg_getRawDB(SDB *sdb) { NSSLOWCERTCertDBHandle *certDB; NSSLOWKEYDBHandle *keyDB; certDB = lg_getCertDB(sdb); if (certDB) { return certDB->permCertDB; } keyDB = lg_getKeyDB(sdb); if (keyDB) { return keyDB->db; } return NULL; }
/* * check the consistancy and initialize a Secret Key Object */ static CK_RV lg_createSecretKeyObject(SDB *sdb, CK_KEY_TYPE key_type, CK_OBJECT_HANDLE *handle, const CK_ATTRIBUTE *templ, CK_ULONG count) { CK_RV crv; NSSLOWKEYPrivateKey *privKey = NULL; NSSLOWKEYDBHandle *keyHandle = NULL; SECItem pubKey; char *label = NULL; SECStatus rv = SECSuccess; pubKey.data = 0; /* If the object is a TOKEN object, store in the database */ keyHandle = lg_getKeyDB(sdb); if (keyHandle == NULL) { return CKR_TOKEN_WRITE_PROTECTED; } label = lg_getString(CKA_LABEL, templ, count); crv = lg_Attribute2SecItem(NULL, CKA_ID, templ, count, &pubKey); /* Should this be ID? */ if (crv != CKR_OK) goto loser; /* if we don't have an ID, generate one */ if (pubKey.len == 0) { if (pubKey.data) { PORT_Free(pubKey.data); pubKey.data = NULL; } crv = lg_GenerateSecretCKA_ID(keyHandle, &pubKey, label); if (crv != CKR_OK) goto loser; } privKey = lg_mkSecretKeyRep(templ, count, key_type, &pubKey, sdb); if (privKey == NULL) { crv = CKR_HOST_MEMORY; goto loser; } rv = nsslowkey_StoreKeyByPublicKey(keyHandle, privKey, &pubKey, label, sdb /*->password*/); if (rv != SECSuccess) { crv = CKR_DEVICE_ERROR; goto loser; } *handle = lg_mkHandle(sdb, &pubKey, LG_TOKEN_TYPE_KEY); loser: if (label) PORT_Free(label); if (privKey) lg_nsslowkey_DestroyPrivateKey(privKey); if (pubKey.data) PORT_Free(pubKey.data); return crv; }
/* * check the consistancy and initialize a Public Key Object */ static CK_RV lg_createPublicKeyObject(SDB *sdb, CK_KEY_TYPE key_type, CK_OBJECT_HANDLE *handle, const CK_ATTRIBUTE *templ, CK_ULONG count) { CK_ATTRIBUTE_TYPE pubKeyAttr = CKA_VALUE; CK_RV crv = CKR_OK; NSSLOWKEYPrivateKey *priv; SECItem pubKeySpace = { siBuffer, NULL, 0 }; SECItem *pubKey; #ifndef NSS_DISABLE_ECC SECItem pubKey2Space = { siBuffer, NULL, 0 }; PLArenaPool *arena = NULL; #endif /* NSS_DISABLE_ECC */ NSSLOWKEYDBHandle *keyHandle = NULL; switch (key_type) { case CKK_RSA: pubKeyAttr = CKA_MODULUS; break; #ifndef NSS_DISABLE_ECC case CKK_EC: pubKeyAttr = CKA_EC_POINT; break; #endif /* NSS_DISABLE_ECC */ case CKK_DSA: case CKK_DH: break; default: return CKR_ATTRIBUTE_VALUE_INVALID; } pubKey = &pubKeySpace; crv = lg_Attribute2SSecItem(NULL, pubKeyAttr, templ, count, pubKey); if (crv != CKR_OK) return crv; #ifndef NSS_DISABLE_ECC if (key_type == CKK_EC) { SECStatus rv; /* * for ECC, use the decoded key first. */ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (arena == NULL) { crv = CKR_HOST_MEMORY; goto done; } rv = SEC_QuickDERDecodeItem(arena, &pubKey2Space, SEC_ASN1_GET(SEC_OctetStringTemplate), pubKey); if (rv != SECSuccess) { /* decode didn't work, just try the pubKey */ PORT_FreeArena(arena, PR_FALSE); arena = NULL; } else { /* try the decoded pub key first */ pubKey = &pubKey2Space; } } #endif /* NSS_DISABLE_ECC */ PORT_Assert(pubKey->data); if (pubKey->data == NULL) { crv = CKR_ATTRIBUTE_VALUE_INVALID; goto done; } keyHandle = lg_getKeyDB(sdb); if (keyHandle == NULL) { crv = CKR_TOKEN_WRITE_PROTECTED; goto done; } if (keyHandle->version != 3) { unsigned char buf[SHA1_LENGTH]; SHA1_HashBuf(buf, pubKey->data, pubKey->len); PORT_Memcpy(pubKey->data, buf, sizeof(buf)); pubKey->len = sizeof(buf); } /* make sure the associated private key already exists */ /* only works if we are logged in */ priv = nsslowkey_FindKeyByPublicKey(keyHandle, pubKey, sdb /*password*/); #ifndef NSS_DISABLE_ECC if (priv == NULL && pubKey == &pubKey2Space) { /* no match on the decoded key, match the original pubkey */ pubKey = &pubKeySpace; priv = nsslowkey_FindKeyByPublicKey(keyHandle, pubKey, sdb /*password*/); } #endif if (priv == NULL) { /* the legacy database can only 'store' public keys which already * have their corresponding private keys in the database */ crv = CKR_ATTRIBUTE_VALUE_INVALID; goto done; } lg_nsslowkey_DestroyPrivateKey(priv); crv = CKR_OK; *handle = lg_mkHandle(sdb, pubKey, LG_TOKEN_TYPE_PUB); done: PORT_Free(pubKeySpace.data); #ifndef NSS_DISABLE_ECC if (arena) PORT_FreeArena(arena, PR_FALSE); #endif return crv; }
/* * check the consistancy and initialize a Certificate Object */ static CK_RV lg_createCertObject(SDB *sdb, CK_OBJECT_HANDLE *handle, const CK_ATTRIBUTE *templ, CK_ULONG count) { SECItem derCert; NSSLOWCERTCertificate *cert; NSSLOWCERTCertTrust *trust = NULL; NSSLOWCERTCertTrust userTrust = { CERTDB_USER, CERTDB_USER, CERTDB_USER }; NSSLOWCERTCertTrust defTrust = { CERTDB_TRUSTED_UNKNOWN, CERTDB_TRUSTED_UNKNOWN, CERTDB_TRUSTED_UNKNOWN }; char *label = NULL; char *email = NULL; SECStatus rv; CK_RV crv; PRBool inDB = PR_TRUE; NSSLOWCERTCertDBHandle *certHandle = lg_getCertDB(sdb); NSSLOWKEYDBHandle *keyHandle = NULL; CK_CERTIFICATE_TYPE type; const CK_ATTRIBUTE *attribute; /* we can't store any certs private */ if (lg_isTrue(CKA_PRIVATE, templ, count)) { return CKR_ATTRIBUTE_VALUE_INVALID; } /* We only support X.509 Certs for now */ crv = lg_GetULongAttribute(CKA_CERTIFICATE_TYPE, templ, count, &type); if (crv != CKR_OK) { return crv; } if (type != CKC_X_509) { return CKR_ATTRIBUTE_VALUE_INVALID; } /* X.509 Certificate */ if (certHandle == NULL) { return CKR_TOKEN_WRITE_PROTECTED; } /* get the der cert */ attribute = lg_FindAttribute(CKA_VALUE, templ, count); if (!attribute) { return CKR_ATTRIBUTE_VALUE_INVALID; } derCert.type = 0; derCert.data = (unsigned char *)attribute->pValue; derCert.len = attribute->ulValueLen; label = lg_getString(CKA_LABEL, templ, count); cert = nsslowcert_FindCertByDERCert(certHandle, &derCert); if (cert == NULL) { cert = nsslowcert_DecodeDERCertificate(&derCert, label); inDB = PR_FALSE; } if (cert == NULL) { if (label) PORT_Free(label); return CKR_ATTRIBUTE_VALUE_INVALID; } keyHandle = lg_getKeyDB(sdb); if (keyHandle) { if (nsslowkey_KeyForCertExists(keyHandle, cert)) { trust = &userTrust; } } if (!inDB) { if (!trust) trust = &defTrust; rv = nsslowcert_AddPermCert(certHandle, cert, label, trust); } else { rv = trust ? nsslowcert_ChangeCertTrust(certHandle, cert, trust) : SECSuccess; } if (label) PORT_Free(label); if (rv != SECSuccess) { nsslowcert_DestroyCertificate(cert); return CKR_DEVICE_ERROR; } /* * Add a NULL S/MIME profile if necessary. */ email = lg_getString(CKA_NSS_EMAIL, templ, count); if (email) { certDBEntrySMime *entry; entry = nsslowcert_ReadDBSMimeEntry(certHandle, email); if (!entry) { nsslowcert_SaveSMimeProfile(certHandle, email, &cert->derSubject, NULL, NULL); } else { nsslowcert_DestroyDBEntry((certDBEntry *)entry); } PORT_Free(email); } *handle = lg_mkHandle(sdb, &cert->certKey, LG_TOKEN_TYPE_CERT); nsslowcert_DestroyCertificate(cert); return CKR_OK; }