blob: d3f3c37c43c38a43b33d04f87d531e2ece899c89 [file] [log] [blame]
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <memory>
#include "nss.h"
#include "pk11pub.h"
#include "prerror.h"
#include "cpputil.h"
#include "nss_scoped_ptrs.h"
#include "testvectors/curve25519-vectors.h"
#include "gtest/gtest.h"
namespace nss_test {
class Pkcs11Curve25519Test
: public ::testing::TestWithParam<EcdhTestVectorStr> {
protected:
void Derive(const uint8_t* pkcs8, size_t pkcs8_len, const uint8_t* spki,
size_t spki_len, const uint8_t* secret, size_t secret_len,
bool expect_success) {
ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot());
ASSERT_TRUE(slot);
SECItem pkcs8_item = {siBuffer, toUcharPtr(pkcs8),
static_cast<unsigned int>(pkcs8_len)};
SECKEYPrivateKey* key = nullptr;
SECStatus rv = PK11_ImportDERPrivateKeyInfoAndReturnKey(
slot.get(), &pkcs8_item, nullptr, nullptr, false, false, KU_ALL, &key,
nullptr);
EXPECT_EQ(SECSuccess, rv);
ScopedSECKEYPrivateKey priv_key_sess(key);
ASSERT_TRUE(priv_key_sess);
SECItem spki_item = {siBuffer, toUcharPtr(spki),
static_cast<unsigned int>(spki_len)};
ScopedCERTSubjectPublicKeyInfo cert_spki(
SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item));
if (!expect_success && !cert_spki) {
return;
}
ASSERT_TRUE(cert_spki);
ScopedSECKEYPublicKey pub_key_remote(
SECKEY_ExtractPublicKey(cert_spki.get()));
ASSERT_TRUE(pub_key_remote);
// sym_key_sess = ECDH(session_import(private_test), public_test)
ScopedPK11SymKey sym_key_sess(PK11_PubDeriveWithKDF(
priv_key_sess.get(), pub_key_remote.get(), false, nullptr, nullptr,
CKM_ECDH1_DERIVE, CKM_SHA512_HMAC, CKA_DERIVE, 0, CKD_NULL, nullptr,
nullptr));
ASSERT_EQ(expect_success, !!sym_key_sess);
if (expect_success) {
rv = PK11_ExtractKeyValue(sym_key_sess.get());
EXPECT_EQ(SECSuccess, rv);
SECItem* key_data = PK11_GetKeyData(sym_key_sess.get());
EXPECT_EQ(secret_len, key_data->len);
EXPECT_EQ(memcmp(key_data->data, secret, secret_len), 0);
// Perform wrapped export on the imported private, import it as
// permanent, and verify we derive the same shared secret
static const uint8_t pw[] = "pw";
SECItem pwItem = {siBuffer, toUcharPtr(pw), sizeof(pw)};
ScopedSECKEYEncryptedPrivateKeyInfo epki(PK11_ExportEncryptedPrivKeyInfo(
slot.get(), SEC_OID_AES_256_CBC, &pwItem, priv_key_sess.get(), 1,
nullptr));
ASSERT_NE(nullptr, epki) << "PK11_ExportEncryptedPrivKeyInfo failed: "
<< PORT_ErrorToName(PORT_GetError());
ScopedSECKEYPublicKey pub_key_local(
SECKEY_ConvertToPublicKey(priv_key_sess.get()));
SECKEYPrivateKey* priv_key_tok = nullptr;
rv = PK11_ImportEncryptedPrivateKeyInfoAndReturnKey(
slot.get(), epki.get(), &pwItem, nullptr,
&pub_key_local->u.ec.publicValue, PR_TRUE, PR_TRUE, ecKey, 0,
&priv_key_tok, nullptr);
ASSERT_EQ(SECSuccess, rv) << "PK11_ImportEncryptedPrivateKeyInfo failed "
<< PORT_ErrorToName(PORT_GetError());
ASSERT_TRUE(priv_key_tok);
// sym_key_tok = ECDH(token_import(export(private_test)),
// public_test)
ScopedPK11SymKey sym_key_tok(PK11_PubDeriveWithKDF(
priv_key_tok, pub_key_remote.get(), false, nullptr, nullptr,
CKM_ECDH1_DERIVE, CKM_SHA512_HMAC, CKA_DERIVE, 0, CKD_NULL, nullptr,
nullptr));
EXPECT_TRUE(sym_key_tok);
if (sym_key_tok) {
rv = PK11_ExtractKeyValue(sym_key_tok.get());
EXPECT_EQ(SECSuccess, rv);
key_data = PK11_GetKeyData(sym_key_tok.get());
EXPECT_EQ(secret_len, key_data->len);
EXPECT_EQ(memcmp(key_data->data, secret, secret_len), 0);
}
rv = PK11_DeleteTokenPrivateKey(priv_key_tok, true);
EXPECT_EQ(SECSuccess, rv);
}
};
void Derive(const EcdhTestVectorStr testvector) {
Derive(testvector.private_key.data(), testvector.private_key.size(),
testvector.public_key.data(), testvector.public_key.size(),
testvector.secret.data(), testvector.secret.size(),
testvector.valid);
};
};
TEST_P(Pkcs11Curve25519Test, TestVectors) { Derive(GetParam()); }
INSTANTIATE_TEST_SUITE_P(NSSTestVector, Pkcs11Curve25519Test,
::testing::ValuesIn(kCurve25519Vectors));
INSTANTIATE_TEST_SUITE_P(WycheproofTestVector, Pkcs11Curve25519Test,
::testing::ValuesIn(kCurve25519WycheproofVectors));
} // namespace nss_test