mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1106087 - Recreate newly generated ECDH private keys with an CKA_EC_POINT attribute to support JWK and PKCS8 export r=rbarnes
This commit is contained in:
parent
1c1e0bfe72
commit
a339ca0ee1
@ -63,6 +63,29 @@ StringToUsage(const nsString& aUsage, CryptoKey::KeyUsage& aUsageOut)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
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) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ScopedPK11GenericObject obj(PK11_CreateGenericObject(slot,
|
||||
aTemplate,
|
||||
aTemplateSize,
|
||||
PR_FALSE));
|
||||
if (!obj) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Have NSS translate the object to a private key.
|
||||
return PK11_FindKeyByKeyID(slot, aObjID, nullptr);
|
||||
}
|
||||
|
||||
CryptoKey::CryptoKey(nsIGlobalObject* aGlobal)
|
||||
: mGlobal(aGlobal)
|
||||
, mAttributes(0)
|
||||
@ -223,6 +246,73 @@ CryptoKey::SetExtractable(bool aExtractable)
|
||||
}
|
||||
}
|
||||
|
||||
// NSS exports private EC keys without the CKA_EC_POINT attribute, i.e. the
|
||||
// public value. To properly export the private key to JWK or PKCS #8 we need
|
||||
// the public key data though and so we use this method to augment a private
|
||||
// key with data from the given public key.
|
||||
nsresult
|
||||
CryptoKey::AddPublicKeyData(SECKEYPublicKey* aPublicKey)
|
||||
{
|
||||
// This should be a private key.
|
||||
MOZ_ASSERT(GetKeyType() == PRIVATE);
|
||||
// There should be a private NSS key with type 'EC'.
|
||||
MOZ_ASSERT(mPrivateKey && mPrivateKey->keyType == ecKey);
|
||||
// The given public key should have the same key type.
|
||||
MOZ_ASSERT(aPublicKey->keyType == mPrivateKey->keyType);
|
||||
|
||||
nsNSSShutDownPreventionLock locker;
|
||||
|
||||
ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
|
||||
if (!slot) {
|
||||
return NS_ERROR_DOM_OPERATION_ERR;
|
||||
}
|
||||
|
||||
// Generate a random 160-bit object ID.
|
||||
ScopedSECItem objID(::SECITEM_AllocItem(nullptr, nullptr, 20));
|
||||
SECStatus rv = PK11_GenerateRandomOnSlot(slot, objID->data, objID->len);
|
||||
if (rv != SECSuccess) {
|
||||
return NS_ERROR_DOM_OPERATION_ERR;
|
||||
}
|
||||
|
||||
// Read EC params.
|
||||
ScopedSECItem params(::SECITEM_AllocItem(nullptr, nullptr, 0));
|
||||
rv = PK11_ReadRawAttribute(PK11_TypePrivKey, mPrivateKey, CKA_EC_PARAMS,
|
||||
params);
|
||||
if (rv != SECSuccess) {
|
||||
return NS_ERROR_DOM_OPERATION_ERR;
|
||||
}
|
||||
|
||||
// Read private value.
|
||||
ScopedSECItem value(::SECITEM_AllocItem(nullptr, nullptr, 0));
|
||||
rv = PK11_ReadRawAttribute(PK11_TypePrivKey, mPrivateKey, CKA_VALUE, value);
|
||||
if (rv != SECSuccess) {
|
||||
return NS_ERROR_DOM_OPERATION_ERR;
|
||||
}
|
||||
|
||||
SECItem* point = &aPublicKey->u.ec.publicValue;
|
||||
CK_OBJECT_CLASS privateKeyValue = CKO_PRIVATE_KEY;
|
||||
CK_BBOOL falseValue = CK_FALSE;
|
||||
CK_KEY_TYPE ecValue = CKK_EC;
|
||||
|
||||
CK_ATTRIBUTE keyTemplate[9] = {
|
||||
{ CKA_CLASS, &privateKeyValue, sizeof(privateKeyValue) },
|
||||
{ CKA_KEY_TYPE, &ecValue, sizeof(ecValue) },
|
||||
{ CKA_TOKEN, &falseValue, sizeof(falseValue) },
|
||||
{ CKA_SENSITIVE, &falseValue, sizeof(falseValue) },
|
||||
{ CKA_PRIVATE, &falseValue, sizeof(falseValue) },
|
||||
{ CKA_ID, objID->data, objID->len },
|
||||
{ CKA_EC_PARAMS, params->data, params->len },
|
||||
{ CKA_EC_POINT, point->data, point->len },
|
||||
{ CKA_VALUE, value->data, value->len },
|
||||
};
|
||||
|
||||
mPrivateKey = PrivateKeyFromPrivateKeyTemplate(objID, keyTemplate,
|
||||
PR_ARRAY_SIZE(keyTemplate));
|
||||
NS_ENSURE_TRUE(mPrivateKey, NS_ERROR_DOM_OPERATION_ERR);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
CryptoKey::ClearUsages()
|
||||
{
|
||||
@ -367,6 +457,9 @@ CryptoKey::PrivateKeyFromPkcs8(CryptoBuffer& aKeyData,
|
||||
{
|
||||
SECKEYPrivateKey* privKey;
|
||||
ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
|
||||
if (!slot) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
|
||||
if (!arena) {
|
||||
@ -582,36 +675,6 @@ CreateECPointForCoordinates(const CryptoBuffer& aX,
|
||||
return point;
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
SECKEYPrivateKey*
|
||||
CryptoKey::PrivateKeyFromJwk(const JsonWebKey& aJwk,
|
||||
const nsNSSShutDownPreventionLock& /*proofOfLock*/)
|
||||
|
@ -116,6 +116,7 @@ public:
|
||||
nsresult SetType(const nsString& aType);
|
||||
void SetType(KeyType aType);
|
||||
void SetExtractable(bool aExtractable);
|
||||
nsresult AddPublicKeyData(SECKEYPublicKey* point);
|
||||
void ClearUsages();
|
||||
nsresult AddUsage(const nsString& aUsage);
|
||||
nsresult AddUsageIntersecting(const nsString& aUsage, uint32_t aUsageMask);
|
||||
|
@ -2331,6 +2331,14 @@ private:
|
||||
|
||||
mKeyPair.mPrivateKey.get()->SetPrivateKey(mPrivateKey);
|
||||
mKeyPair.mPublicKey.get()->SetPublicKey(mPublicKey);
|
||||
|
||||
// PK11_GenerateKeyPair() does not set a CKA_EC_POINT attribute on the
|
||||
// private key, we need this later when exporting to PKCS8 and JWK though.
|
||||
if (mMechanism == CKM_EC_KEY_PAIR_GEN) {
|
||||
nsresult rv = mKeyPair.mPrivateKey->AddPublicKeyData(mPublicKey);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_OPERATION_ERR);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user