pk11_kem_unittest.cc (5377B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #include "gtest/gtest.h" 6 #include "nss_scoped_ptrs.h" 7 8 #include "pk11_keygen.h" 9 #include "pk11pub.h" 10 11 #include "blapi.h" 12 #include "secport.h" 13 14 namespace nss_test { 15 16 class Pkcs11KEMTest 17 : public ::testing::Test, 18 public ::testing::WithParamInterface<CK_NSS_KEM_PARAMETER_SET_TYPE> { 19 protected: 20 PK11SymKey *Encapsulate(const ScopedSECKEYPublicKey &pub, 21 CK_MECHANISM_TYPE target, PK11AttrFlags attrFlags, 22 CK_FLAGS opFlags, ScopedSECItem *ciphertext) { 23 PK11SymKey *sharedSecretRawPtr; 24 SECItem *ciphertextRawPtr; 25 26 EXPECT_EQ(SECSuccess, 27 PK11_Encapsulate(pub.get(), target, attrFlags, opFlags, 28 &sharedSecretRawPtr, &ciphertextRawPtr)); 29 30 ciphertext->reset(ciphertextRawPtr); 31 32 return sharedSecretRawPtr; 33 } 34 35 PK11SymKey *Decapsulate(const ScopedSECKEYPrivateKey &priv, 36 const ScopedSECItem &ciphertext, 37 CK_MECHANISM_TYPE target, PK11AttrFlags attrFlags, 38 CK_FLAGS opFlags) { 39 PK11SymKey *sharedSecretRawPtr; 40 41 EXPECT_EQ(SECSuccess, 42 PK11_Decapsulate(priv.get(), ciphertext.get(), target, attrFlags, 43 opFlags, &sharedSecretRawPtr)); 44 45 return sharedSecretRawPtr; 46 } 47 48 SECItem *getRawKeyData(const ScopedPK11SymKey &key) { 49 SECStatus rv = PK11_ExtractKeyValue(key.get()); 50 EXPECT_EQ(SECSuccess, rv); 51 52 SECItem *keyData = PK11_GetKeyData(key.get()); 53 EXPECT_NE(nullptr, keyData); 54 EXPECT_NE(nullptr, keyData->data); 55 56 return keyData; 57 } 58 59 void checkSymKeyAttributeValue(const ScopedPK11SymKey &key, 60 CK_ATTRIBUTE_TYPE attr, 61 uint8_t *expectedValue) { 62 SECItem attrValue; 63 64 EXPECT_EQ(SECSuccess, PK11_ReadRawAttribute(PK11_TypeSymKey, key.get(), 65 attr, &attrValue)); 66 EXPECT_EQ(0, memcmp(expectedValue, attrValue.data, attrValue.len)); 67 68 SECITEM_FreeItem(&attrValue, PR_FALSE); 69 } 70 71 CK_MECHANISM_TYPE keyGenMech() { 72 switch (GetParam()) { 73 case CKP_NSS_KYBER_768_ROUND3: 74 return CKM_NSS_KYBER_KEY_PAIR_GEN; 75 case CKP_NSS_ML_KEM_768: 76 return CKM_NSS_ML_KEM_KEY_PAIR_GEN; 77 case CKP_ML_KEM_768: 78 case CKP_ML_KEM_1024: 79 return CKM_ML_KEM_KEY_PAIR_GEN; 80 default: 81 EXPECT_TRUE(false); 82 return 0; 83 } 84 } 85 86 CK_MECHANISM_TYPE encapsMech() { 87 switch (GetParam()) { 88 case CKP_NSS_KYBER_768_ROUND3: 89 return CKM_NSS_KYBER; 90 case CKP_NSS_ML_KEM_768: 91 return CKM_NSS_ML_KEM; 92 case CKP_ML_KEM_768: 93 case CKP_ML_KEM_1024: 94 return CKM_ML_KEM; 95 default: 96 EXPECT_TRUE(false); 97 return 0; 98 } 99 } 100 }; 101 102 TEST_P(Pkcs11KEMTest, KemConsistencyTest) { 103 Pkcs11KeyPairGenerator generator(keyGenMech()); 104 ScopedSECKEYPrivateKey priv; 105 ScopedSECKEYPublicKey pub; 106 generator.GenerateKey(&priv, &pub, false); 107 108 ASSERT_NE(nullptr, pub); 109 ASSERT_NE(nullptr, priv); 110 111 // Copy the public key to simulate receiving the key as an octet string 112 ScopedSECKEYPublicKey pubCopy(SECKEY_CopyPublicKey(pub.get())); 113 ASSERT_NE(nullptr, pubCopy); 114 115 ScopedPK11SlotInfo slot(PK11_GetBestSlot(encapsMech(), nullptr)); 116 ASSERT_NE(nullptr, slot); 117 std::string name = PK11_GetSlotName(slot.get()); 118 ASSERT_EQ(name, "NSS Internal Cryptographic Services"); 119 120 ASSERT_NE((unsigned int)CK_INVALID_HANDLE, 121 PK11_ImportPublicKey(slot.get(), pubCopy.get(), PR_FALSE)); 122 123 ScopedSECItem ciphertext; 124 ScopedPK11SymKey sharedSecret(Encapsulate( 125 pubCopy, CKM_SALSA20_POLY1305, PK11_ATTR_PRIVATE | PK11_ATTR_UNMODIFIABLE, 126 CKF_ENCRYPT, &ciphertext)); 127 128 ASSERT_EQ(CKM_SALSA20_POLY1305, PK11_GetMechanism(sharedSecret.get())); 129 130 CK_BBOOL ckTrue = CK_TRUE; 131 CK_BBOOL ckFalse = CK_FALSE; 132 checkSymKeyAttributeValue(sharedSecret, CKA_PRIVATE, &ckTrue); 133 checkSymKeyAttributeValue(sharedSecret, CKA_MODIFIABLE, &ckFalse); 134 checkSymKeyAttributeValue(sharedSecret, CKA_ENCRYPT, &ckTrue); 135 136 ScopedPK11SymKey sharedSecret2( 137 Decapsulate(priv, ciphertext, CKM_SALSA20_POLY1305, 138 PK11_ATTR_PRIVATE | PK11_ATTR_UNMODIFIABLE, CKF_ENCRYPT)); 139 140 ASSERT_EQ(CKM_SALSA20_POLY1305, PK11_GetMechanism(sharedSecret2.get())); 141 142 checkSymKeyAttributeValue(sharedSecret2, CKA_PRIVATE, &ckTrue); 143 checkSymKeyAttributeValue(sharedSecret2, CKA_MODIFIABLE, &ckFalse); 144 checkSymKeyAttributeValue(sharedSecret2, CKA_ENCRYPT, &ckTrue); 145 146 SECItem *item1 = getRawKeyData(sharedSecret); 147 SECItem *item2 = getRawKeyData(sharedSecret2); 148 NSS_DECLASSIFY(item1->data, item1->len); 149 NSS_DECLASSIFY(item2->data, item2->len); 150 EXPECT_EQ(0, SECITEM_CompareItem(item1, item2)); 151 } 152 153 #ifndef NSS_DISABLE_KYBER 154 INSTANTIATE_TEST_SUITE_P(Pkcs11KEMTest, Pkcs11KEMTest, 155 ::testing::Values(CKP_NSS_KYBER_768_ROUND3, 156 CKP_NSS_ML_KEM_768, CKP_ML_KEM_768)); 157 #else 158 INSTANTIATE_TEST_SUITE_P(Pkcs11KEMTest, Pkcs11KEMTest, 159 ::testing::Values(CKP_NSS_ML_KEM_768, CKP_ML_KEM_768)); 160 #endif 161 162 } // namespace nss_test