diff -up ./gtests/pk11_gtest/pk11_import_unittest.cc.pub-priv-mech ./gtests/pk11_gtest/pk11_import_unittest.cc --- ./gtests/pk11_gtest/pk11_import_unittest.cc.pub-priv-mech 2019-05-10 14:14:18.000000000 -0700 +++ ./gtests/pk11_gtest/pk11_import_unittest.cc 2019-06-05 16:43:42.276498676 -0700 @@ -78,17 +78,40 @@ class Pk11KeyImportTestBase : public ::t CK_MECHANISM_TYPE mech_; private: + SECItem GetPublicComponent(ScopedSECKEYPublicKey& pub_key) { + SECItem null = { siBuffer, NULL, 0}; + switch(SECKEY_GetPublicKeyType(pub_key.get())) { + case rsaKey: + case rsaPssKey: + case rsaOaepKey: + return pub_key->u.rsa.modulus; + case keaKey: + return pub_key->u.kea.publicValue; + case dsaKey: + return pub_key->u.dsa.publicValue; + case dhKey: + return pub_key->u.dh.publicValue; + case ecKey: + return pub_key->u.ec.publicValue; + case fortezzaKey: /* depricated */ + case nullKey: + /* didn't use default here so we can catch new key types at compile time */ + break; + } + return null; + } void CheckForPublicKey(const ScopedSECKEYPrivateKey& priv_key, const SECItem* expected_public) { // Verify the public key exists. StackSECItem priv_id; + KeyType type = SECKEY_GetPrivateKeyType(priv_key.get()); SECStatus rv = PK11_ReadRawAttribute(PK11_TypePrivKey, priv_key.get(), CKA_ID, &priv_id); ASSERT_EQ(SECSuccess, rv) << "Couldn't read CKA_ID from private key: " << PORT_ErrorToName(PORT_GetError()); CK_ATTRIBUTE_TYPE value_type = CKA_VALUE; - switch (SECKEY_GetPrivateKeyType(priv_key.get())) { + switch (type) { case rsaKey: value_type = CKA_MODULUS; break; @@ -106,6 +129,8 @@ class Pk11KeyImportTestBase : public ::t FAIL() << "unknown key type"; } + // Scan public key objects until we find one with the same CKA_ID as + // priv_key std::unique_ptr objs( PK11_FindGenericObjects(slot_.get(), CKO_PUBLIC_KEY)); ASSERT_NE(nullptr, objs); @@ -128,20 +153,46 @@ class Pk11KeyImportTestBase : public ::t ASSERT_EQ(1U, token.len); ASSERT_NE(0, token.data[0]); - StackSECItem value; - rv = PK11_ReadRawAttribute(PK11_TypeGeneric, obj, value_type, &value); + StackSECItem raw_value; + SECItem decoded_value; + rv = PK11_ReadRawAttribute(PK11_TypeGeneric, obj, value_type, &raw_value); ASSERT_EQ(SECSuccess, rv); + SECItem value = raw_value; + // Decode the EC_POINT and check the output against expected. // CKA_EC_POINT isn't stable, see Bug 1520649. + ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); + ASSERT_TRUE(arena); if (value_type == CKA_EC_POINT) { - continue; - } + // If this fails due to the noted inconsistency, we may need to + // check the whole raw_value, or remove a leading UNCOMPRESSED_POINT tag + rv = SEC_QuickDERDecodeItem(arena.get(), &decoded_value, + SEC_ASN1_GET(SEC_OctetStringTemplate), + &raw_value); + ASSERT_EQ(SECSuccess, rv); + value = decoded_value; + } ASSERT_TRUE(SECITEM_ItemsAreEqual(expected_public, &value)) << "expected: " << DataBuffer(expected_public->data, expected_public->len) << std::endl << "actual: " << DataBuffer(value.data, value.len) << std::endl; + + // Finally, convert the private to public and ensure it matches. + ScopedSECKEYPublicKey pub_key( + SECKEY_ConvertToPublicKey(priv_key.get())); + ASSERT_TRUE(pub_key); + SECItem converted_public = GetPublicComponent(pub_key); + ASSERT_TRUE(converted_public.len != 0); + + ASSERT_TRUE(SECITEM_ItemsAreEqual(expected_public, &converted_public)) + << "expected: " + << DataBuffer(expected_public->data, expected_public->len) + << std::endl + << "actual: " + << DataBuffer(converted_public.data, converted_public.len) + << std::endl; } } diff -up ./lib/cryptohi/seckey.c.pub-priv-mech ./lib/cryptohi/seckey.c --- ./lib/cryptohi/seckey.c.pub-priv-mech 2019-05-10 14:14:18.000000000 -0700 +++ ./lib/cryptohi/seckey.c 2019-06-05 16:43:42.277498676 -0700 @@ -1206,6 +1206,37 @@ SECKEY_CopyPublicKey(const SECKEYPublicK return NULL; } +/* + * Use the private key to find a public key handle. The handle will be on + * the same slot as the private key. + */ +static CK_OBJECT_HANDLE +seckey_FindPublicKeyHandle(SECKEYPrivateKey *privk, SECKEYPublicKey *pubk) +{ + CK_OBJECT_HANDLE keyID; + + /* this helper function is only used below. If we want to make this more + * general, we would need to free up any already cached handles if the + * slot doesn't match up with the private key slot */ + PORT_Assert(pubk->pkcs11ID == CK_INVALID_HANDLE); + + /* first look for a matching public key */ + keyID = PK11_MatchItem(privk->pkcs11Slot, privk->pkcs11ID, CKO_PUBLIC_KEY); + if (keyID != CK_INVALID_HANDLE) { + return keyID; + } + + /* none found, create a temp one, make the pubk the owner */ + pubk->pkcs11ID = PK11_DerivePubKeyFromPrivKey(privk); + if (pubk->pkcs11ID == CK_INVALID_HANDLE) { + /* end of the road. Token doesn't have matching public key, nor can + * token regenerate a new public key from and existing private key. */ + return CK_INVALID_HANDLE; + } + pubk->pkcs11Slot = PK11_ReferenceSlot(privk->pkcs11Slot); + return pubk->pkcs11ID; +} + SECKEYPublicKey * SECKEY_ConvertToPublicKey(SECKEYPrivateKey *privk) { @@ -1213,6 +1244,8 @@ SECKEY_ConvertToPublicKey(SECKEYPrivateK PLArenaPool *arena; CERTCertificate *cert; SECStatus rv; + CK_OBJECT_HANDLE pubKeyHandle; + SECItem decodedPoint; /* * First try to look up the cert. @@ -1243,11 +1276,47 @@ SECKEY_ConvertToPublicKey(SECKEYPrivateK switch (privk->keyType) { case nullKey: - case dhKey: - case dsaKey: /* Nothing to query, if the cert isn't there, we're done -- no way * to get the public key */ break; + case dsaKey: + pubKeyHandle = seckey_FindPublicKeyHandle(privk, pubk); + if (pubKeyHandle == CK_INVALID_HANDLE) + break; + rv = PK11_ReadAttribute(privk->pkcs11Slot, pubKeyHandle, + CKA_BASE, arena, &pubk->u.dsa.params.base); + if (rv != SECSuccess) + break; + rv = PK11_ReadAttribute(privk->pkcs11Slot, pubKeyHandle, + CKA_PRIME, arena, &pubk->u.dsa.params.prime); + if (rv != SECSuccess) + break; + rv = PK11_ReadAttribute(privk->pkcs11Slot, pubKeyHandle, + CKA_SUBPRIME, arena, &pubk->u.dsa.params.subPrime); + if (rv != SECSuccess) + break; + rv = PK11_ReadAttribute(privk->pkcs11Slot, pubKeyHandle, + CKA_VALUE, arena, &pubk->u.dsa.publicValue); + if (rv != SECSuccess) + break; + return pubk; + case dhKey: + pubKeyHandle = seckey_FindPublicKeyHandle(privk, pubk); + if (pubKeyHandle == CK_INVALID_HANDLE) + break; + rv = PK11_ReadAttribute(privk->pkcs11Slot, pubKeyHandle, + CKA_BASE, arena, &pubk->u.dh.base); + if (rv != SECSuccess) + break; + rv = PK11_ReadAttribute(privk->pkcs11Slot, pubKeyHandle, + CKA_PRIME, arena, &pubk->u.dh.prime); + if (rv != SECSuccess) + break; + rv = PK11_ReadAttribute(privk->pkcs11Slot, pubKeyHandle, + CKA_VALUE, arena, &pubk->u.dh.publicValue); + if (rv != SECSuccess) + break; + return pubk; case rsaKey: rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID, CKA_MODULUS, arena, &pubk->u.rsa.modulus); @@ -1258,7 +1327,6 @@ SECKEY_ConvertToPublicKey(SECKEYPrivateK if (rv != SECSuccess) break; return pubk; - break; case ecKey: rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID, CKA_EC_PARAMS, arena, &pubk->u.ec.DEREncodedParams); @@ -1268,7 +1336,23 @@ SECKEY_ConvertToPublicKey(SECKEYPrivateK rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID, CKA_EC_POINT, arena, &pubk->u.ec.publicValue); if (rv != SECSuccess || pubk->u.ec.publicValue.len == 0) { - break; + pubKeyHandle = seckey_FindPublicKeyHandle(privk, pubk); + if (pubKeyHandle == CK_INVALID_HANDLE) + break; + rv = PK11_ReadAttribute(privk->pkcs11Slot, pubKeyHandle, + CKA_EC_POINT, arena, &pubk->u.ec.publicValue); + if (rv != SECSuccess) + break; + } + /* ec.publicValue should be decoded, PKCS #11 defines CKA_EC_POINT + * as encoded, but it's not always. try do decoded it and if it + * succeeds store the decoded value */ + rv = SEC_QuickDERDecodeItem(arena, &decodedPoint, + SEC_ASN1_GET(SEC_OctetStringTemplate), &pubk->u.ec.publicValue); + if (rv == SECSuccess) { + /* both values are in the public key arena, so it's safe to + * overwrite the old value */ + pubk->u.ec.publicValue = decodedPoint; } pubk->u.ec.encoding = ECPoint_Undefined; return pubk; @@ -1276,7 +1360,9 @@ SECKEY_ConvertToPublicKey(SECKEYPrivateK break; } - PORT_FreeArena(arena, PR_FALSE); + /* must use Destroy public key here, because some paths create temporary + * PKCS #11 objects which need to be freed */ + SECKEY_DestroyPublicKey(pubk); return NULL; } diff -up ./lib/pk11wrap/pk11priv.h.pub-priv-mech ./lib/pk11wrap/pk11priv.h --- ./lib/pk11wrap/pk11priv.h.pub-priv-mech 2019-05-10 14:14:18.000000000 -0700 +++ ./lib/pk11wrap/pk11priv.h 2019-06-05 16:43:42.277498676 -0700 @@ -111,6 +111,7 @@ CK_OBJECT_HANDLE PK11_FindObjectForCert( PK11SymKey *pk11_CopyToSlot(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE operation, PK11SymKey *symKey); unsigned int pk11_GetPredefinedKeyLength(CK_KEY_TYPE keyType); +CK_OBJECT_HANDLE PK11_DerivePubKeyFromPrivKey(SECKEYPrivateKey *privKey); /********************************************************************** * Certs diff -up ./lib/pk11wrap/pk11skey.c.pub-priv-mech ./lib/pk11wrap/pk11skey.c --- ./lib/pk11wrap/pk11skey.c.pub-priv-mech 2019-06-05 16:37:38.726685789 -0700 +++ ./lib/pk11wrap/pk11skey.c 2019-06-05 16:43:42.278498675 -0700 @@ -1841,6 +1841,35 @@ loser: } /* + * This regenerate a public key from a private key. This function is currently + * NSS private. If we want to make it public, we need to add and optional + * template or at least flags (a.la. PK11_DeriveWithFlags). + */ +CK_OBJECT_HANDLE +PK11_DerivePubKeyFromPrivKey(SECKEYPrivateKey *privKey) +{ + PK11SlotInfo *slot = privKey->pkcs11Slot; + CK_MECHANISM mechanism; + CK_OBJECT_HANDLE objectID = CK_INVALID_HANDLE; + CK_RV crv; + + mechanism.mechanism = CKM_NSS_PUB_FROM_PRIV; + mechanism.pParameter = NULL; + mechanism.ulParameterLen = 0; + + PK11_EnterSlotMonitor(slot); + crv = PK11_GETTAB(slot)->C_DeriveKey(slot->session, &mechanism, + privKey->pkcs11ID, NULL, 0, + &objectID); + PK11_ExitSlotMonitor(slot); + if (crv != CKR_OK) { + PORT_SetError(PK11_MapError(crv)); + return CK_INVALID_HANDLE; + } + return objectID; +} + +/* * This Generates a wrapping key based on a privateKey, publicKey, and two * random numbers. For Mail usage RandomB should be NULL. In the Sender's * case RandomA is generate, outherwize it is passed. diff -up ./lib/softoken/lowkey.c.pub-priv-mech ./lib/softoken/lowkey.c --- ./lib/softoken/lowkey.c.pub-priv-mech 2019-05-10 14:14:18.000000000 -0700 +++ ./lib/softoken/lowkey.c 2019-06-05 16:44:20.469479019 -0700 @@ -261,6 +261,7 @@ NSSLOWKEYPublicKey * nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk) { NSSLOWKEYPublicKey *pubk; + SECItem publicValue; PLArenaPool *arena; arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); @@ -301,6 +302,19 @@ nsslowkey_ConvertToPublicKey(NSSLOWKEYPr pubk->arena = arena; pubk->keyType = privk->keyType; + /* if the public key value doesn't exist, calculate it */ + if (privk->u.dsa.publicValue.len == 0) { + rv = DH_Derive(&privk->u.dsa.params.base, &privk->u.dsa.params.prime, + &privk->u.dsa.privateValue, &publicValue, 0); + if (rv != SECSuccess) { + break; + } + rv = SECITEM_CopyItem(privk->arena, &privk->u.dsa.publicValue, &publicValue); + SECITEM_FreeItem(&publicValue, PR_FALSE); + if (rv != SECSuccess) { + break; + } + } rv = SECITEM_CopyItem(arena, &pubk->u.dsa.publicValue, &privk->u.dsa.publicValue); if (rv != SECSuccess) @@ -327,6 +341,19 @@ nsslowkey_ConvertToPublicKey(NSSLOWKEYPr pubk->arena = arena; pubk->keyType = privk->keyType; + /* if the public key value doesn't exist, calculate it */ + if (privk->u.dh.publicValue.len == 0) { + rv = DH_Derive(&privk->u.dh.base, &privk->u.dh.prime, + &privk->u.dh.privateValue, &publicValue, 0); + if (rv != SECSuccess) { + break; + } + rv = SECITEM_CopyItem(privk->arena, &privk->u.dh.publicValue, &publicValue); + SECITEM_FreeItem(&publicValue, PR_FALSE); + if (rv != SECSuccess) { + break; + } + } rv = SECITEM_CopyItem(arena, &pubk->u.dh.publicValue, &privk->u.dh.publicValue); if (rv != SECSuccess) diff -up ./lib/softoken/pkcs11c.c.pub-priv-mech ./lib/softoken/pkcs11c.c --- ./lib/softoken/pkcs11c.c.pub-priv-mech 2019-06-05 16:37:38.743685780 -0700 +++ ./lib/softoken/pkcs11c.c 2019-06-05 16:44:20.472479017 -0700 @@ -6569,6 +6569,10 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession extractValue = PR_FALSE; classType = CKO_PRIVATE_KEY; break; + case CKM_NSS_PUB_FROM_PRIV: + extractValue = PR_FALSE; + classType = CKO_PUBLIC_KEY; + break; case CKM_NSS_JPAKE_FINAL_SHA1: /* fall through */ case CKM_NSS_JPAKE_FINAL_SHA256: /* fall through */ case CKM_NSS_JPAKE_FINAL_SHA384: /* fall through */ @@ -6610,6 +6614,35 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession } switch (mechanism) { + /* get a public key from a private key. nsslowkey_ConvertToPublickey() + * will generate the public portion if it doesn't already exist. */ + case CKM_NSS_PUB_FROM_PRIV: { + NSSLOWKEYPrivateKey *privKey; + NSSLOWKEYPublicKey *pubKey; + int error; + + crv = sftk_GetULongAttribute(sourceKey, CKA_KEY_TYPE, &keyType); + if (crv != CKR_OK) { + break; + } + + /* privKey is stored in sourceKey and will be destroyed when + * the sourceKey is freed. */ + privKey = sftk_GetPrivKey(sourceKey, keyType, &crv); + if (privKey == NULL) { + break; + } + pubKey = nsslowkey_ConvertToPublicKey(privKey); + if (pubKey == NULL) { + error = PORT_GetError(); + crv = sftk_MapCryptError(error); + break; + } + crv = sftk_PutPubKey(key, sourceKey, keyType, pubKey); + nsslowkey_DestroyPublicKey(pubKey); + break; + } + case CKM_NSS_IKE_PRF_DERIVE: if (pMechanism->ulParameterLen != sizeof(CK_NSS_IKE_PRF_DERIVE_PARAMS)) { diff -up ./lib/softoken/pkcs11.c.pub-priv-mech ./lib/softoken/pkcs11.c --- ./lib/softoken/pkcs11.c.pub-priv-mech 2019-06-05 16:37:38.728685788 -0700 +++ ./lib/softoken/pkcs11.c 2019-06-05 16:44:20.473479017 -0700 @@ -2206,6 +2206,123 @@ sftk_GetPrivKey(SFTKObject *object, CK_K return priv; } +/* populate a public key object from a lowpublic keys structure */ +CK_RV +sftk_PutPubKey(SFTKObject *publicKey, SFTKObject *privateKey, CK_KEY_TYPE keyType, NSSLOWKEYPublicKey *pubKey) +{ + CK_OBJECT_CLASS classType = CKO_PUBLIC_KEY; + CK_BBOOL cktrue = CK_TRUE; + CK_RV crv = CKR_OK; + sftk_DeleteAttributeType(publicKey, CKA_CLASS); + sftk_DeleteAttributeType(publicKey, CKA_KEY_TYPE); + sftk_DeleteAttributeType(publicKey, CKA_VALUE); + + switch (keyType) { + case CKK_RSA: + sftk_DeleteAttributeType(publicKey, CKA_MODULUS); + sftk_DeleteAttributeType(publicKey, CKA_PUBLIC_EXPONENT); + /* format the keys */ + /* fill in the RSA dependent paramenters in the public key */ + crv = sftk_AddAttributeType(publicKey, CKA_MODULUS, + sftk_item_expand(&pubKey->u.rsa.modulus)); + if (crv != CKR_OK) + break; + crv = sftk_AddAttributeType(publicKey, CKA_PUBLIC_EXPONENT, + sftk_item_expand(&pubKey->u.rsa.publicExponent)); + break; + case CKK_DSA: + sftk_DeleteAttributeType(publicKey, CKA_PRIME); + sftk_DeleteAttributeType(publicKey, CKA_SUBPRIME); + sftk_DeleteAttributeType(publicKey, CKA_BASE); + crv = sftk_AddAttributeType(publicKey, CKA_PRIME, + sftk_item_expand(&pubKey->u.dsa.params.prime)); + if (crv != CKR_OK) { + break; + } + crv = sftk_AddAttributeType(publicKey, CKA_SUBPRIME, + sftk_item_expand(&pubKey->u.dsa.params.subPrime)); + if (crv != CKR_OK) { + break; + } + crv = sftk_AddAttributeType(publicKey, CKA_BASE, + sftk_item_expand(&pubKey->u.dsa.params.base)); + if (crv != CKR_OK) { + break; + } + crv = sftk_AddAttributeType(publicKey, CKA_VALUE, + sftk_item_expand(&pubKey->u.dsa.publicValue)); + break; + + case CKK_DH: + sftk_DeleteAttributeType(publicKey, CKA_PRIME); + sftk_DeleteAttributeType(publicKey, CKA_BASE); + crv = sftk_AddAttributeType(publicKey, CKA_PRIME, + sftk_item_expand(&pubKey->u.dh.prime)); + if (crv != CKR_OK) { + break; + } + crv = sftk_AddAttributeType(publicKey, CKA_BASE, + sftk_item_expand(&pubKey->u.dh.base)); + if (crv != CKR_OK) { + break; + } + crv = sftk_AddAttributeType(publicKey, CKA_VALUE, + sftk_item_expand(&pubKey->u.dh.publicValue)); + break; + + case CKK_EC: + sftk_DeleteAttributeType(publicKey, CKA_EC_PARAMS); + sftk_DeleteAttributeType(publicKey, CKA_EC_POINT); + + crv = sftk_AddAttributeType(publicKey, CKA_EC_PARAMS, + sftk_item_expand(&pubKey->u.ec.ecParams.DEREncoding)); + if (crv != CKR_OK) { + break; + } + + crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT, + sftk_item_expand(&pubKey->u.ec.publicValue)); + break; + + default: + return CKR_KEY_TYPE_INCONSISTENT; + } + crv = sftk_AddAttributeType(publicKey, CKA_CLASS, &classType, + sizeof(CK_OBJECT_CLASS)); + if (crv != CKR_OK) + return crv; + crv = sftk_AddAttributeType(publicKey, CKA_KEY_TYPE, &keyType, + sizeof(CK_KEY_TYPE)); + if (crv != CKR_OK) + return crv; + /* now handle the operator attributes */ + if (sftk_isTrue(privateKey, CKA_DECRYPT)) { + crv = sftk_forceAttribute(publicKey, CKA_ENCRYPT, &cktrue, sizeof(CK_BBOOL)); + if (crv != CKR_OK) { + return crv; + } + } + if (sftk_isTrue(privateKey, CKA_SIGN)) { + crv = sftk_forceAttribute(publicKey, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL)); + if (crv != CKR_OK) { + return crv; + } + } + if (sftk_isTrue(privateKey, CKA_SIGN_RECOVER)) { + crv = sftk_forceAttribute(publicKey, CKA_VERIFY_RECOVER, &cktrue, sizeof(CK_BBOOL)); + if (crv != CKR_OK) { + return crv; + } + } + if (sftk_isTrue(privateKey, CKA_DERIVE)) { + crv = sftk_forceAttribute(publicKey, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL)); + if (crv != CKR_OK) { + return crv; + } + } + return crv; +} + /* **************************** Symetric Key utils ************************ */ diff -up ./lib/softoken/pkcs11i.h.pub-priv-mech ./lib/softoken/pkcs11i.h --- ./lib/softoken/pkcs11i.h.pub-priv-mech 2019-06-05 16:37:38.730685787 -0700 +++ ./lib/softoken/pkcs11i.h 2019-06-05 16:44:20.473479017 -0700 @@ -695,6 +695,9 @@ extern NSSLOWKEYPublicKey *sftk_GetPubKe CK_KEY_TYPE key_type, CK_RV *crvp); extern NSSLOWKEYPrivateKey *sftk_GetPrivKey(SFTKObject *object, CK_KEY_TYPE key_type, CK_RV *crvp); +extern CK_RV sftk_PutPubKey(SFTKObject *publicKey, SFTKObject *privKey, + CK_KEY_TYPE keyType, + NSSLOWKEYPublicKey *pubKey); extern void sftk_FormatDESKey(unsigned char *key, int length); extern PRBool sftk_CheckDESKey(unsigned char *key); extern PRBool sftk_IsWeakKey(unsigned char *key, CK_KEY_TYPE key_type); diff -up ./lib/util/pkcs11n.h.pub-priv-mech ./lib/util/pkcs11n.h --- ./lib/util/pkcs11n.h.pub-priv-mech 2019-06-05 16:37:38.733685785 -0700 +++ ./lib/util/pkcs11n.h 2019-06-05 16:44:54.389461561 -0700 @@ -152,11 +152,6 @@ #define CKM_NSS_HKDF_SHA384 (CKM_NSS + 5) #define CKM_NSS_HKDF_SHA512 (CKM_NSS + 6) -/* IKE mechanism (to be proposed to PKCS #11 */ -#define CKM_NSS_IKE_PRF_PLUS_DERIVE (CKM_NSS + 7) -#define CKM_NSS_IKE_PRF_DERIVE (CKM_NSS + 8) -#define CKM_NSS_IKE1_PRF_DERIVE (CKM_NSS + 9) -#define CKM_NSS_IKE1_APP_B_PRF_DERIVE (CKM_NSS + 10) /* J-PAKE round 1 key generation mechanisms. * @@ -238,6 +233,15 @@ #define CKM_NSS_CHACHA20_CTR (CKM_NSS + 33) +/* IKE mechanism (to be proposed to PKCS #11 */ +#define CKM_NSS_IKE_PRF_PLUS_DERIVE (CKM_NSS + 34) +#define CKM_NSS_IKE_PRF_DERIVE (CKM_NSS + 35) +#define CKM_NSS_IKE1_PRF_DERIVE (CKM_NSS + 36) +#define CKM_NSS_IKE1_APP_B_PRF_DERIVE (CKM_NSS + 37) + +/* Derive a public key from a bare private key */ +#define CKM_NSS_PUB_FROM_PRIV (CKM_NSS + 40) + /* * HISTORICAL: * Do not attempt to use these. They are only used by NETSCAPE's internal