| // 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 "gtest/gtest.h" |
| |
| #include <stdint.h> |
| |
| #include "blapi.h" |
| #include "nss_scoped_ptrs.h" |
| #include "secerr.h" |
| |
| namespace nss_test { |
| |
| class ECLTest : public ::testing::Test { |
| protected: |
| const ECCurveName GetCurveName(std::string name) { |
| if (name == "P256") return ECCurve_NIST_P256; |
| if (name == "P384") return ECCurve_NIST_P384; |
| if (name == "P521") return ECCurve_NIST_P521; |
| return ECCurve_pastLastCurve; |
| } |
| std::vector<uint8_t> hexStringToBytes(std::string s) { |
| std::vector<uint8_t> bytes; |
| for (size_t i = 0; i < s.length(); i += 2) { |
| bytes.push_back(std::stoul(s.substr(i, 2), nullptr, 16)); |
| } |
| return bytes; |
| } |
| std::string bytesToHexString(std::vector<uint8_t> bytes) { |
| std::stringstream s; |
| for (auto b : bytes) { |
| s << std::setfill('0') << std::setw(2) << std::uppercase << std::hex |
| << static_cast<int>(b); |
| } |
| return s.str(); |
| } |
| void ecName2params(const std::string curve, SECItem *params) { |
| SECOidData *oidData = nullptr; |
| |
| switch (GetCurveName(curve)) { |
| case ECCurve_NIST_P256: |
| oidData = SECOID_FindOIDByTag(SEC_OID_ANSIX962_EC_PRIME256V1); |
| break; |
| case ECCurve_NIST_P384: |
| oidData = SECOID_FindOIDByTag(SEC_OID_SECG_EC_SECP384R1); |
| break; |
| case ECCurve_NIST_P521: |
| oidData = SECOID_FindOIDByTag(SEC_OID_SECG_EC_SECP521R1); |
| break; |
| default: |
| FAIL(); |
| } |
| ASSERT_NE(oidData, nullptr); |
| |
| if (SECITEM_AllocItem(nullptr, params, (2 + oidData->oid.len)) == nullptr) { |
| FAIL() << "Couldn't allocate memory for OID."; |
| } |
| params->data[0] = SEC_ASN1_OBJECT_ID; |
| params->data[1] = oidData->oid.len; |
| memcpy(params->data + 2, oidData->oid.data, oidData->oid.len); |
| } |
| |
| void TestECDH_Derive(const std::string p, const std::string secret, |
| const std::string group_name, const std::string result, |
| const SECStatus expected_status) { |
| ECParams ecParams = {0}; |
| ScopedSECItem ecEncodedParams(SECITEM_AllocItem(nullptr, nullptr, 0U)); |
| ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); |
| |
| ASSERT_TRUE(arena && ecEncodedParams); |
| |
| ecName2params(group_name, ecEncodedParams.get()); |
| EC_FillParams(arena.get(), ecEncodedParams.get(), &ecParams); |
| |
| std::vector<uint8_t> p_bytes = hexStringToBytes(p); |
| ASSERT_GT(p_bytes.size(), 0U); |
| SECItem public_value = {siBuffer, p_bytes.data(), |
| static_cast<unsigned int>(p_bytes.size())}; |
| |
| std::vector<uint8_t> secret_bytes = hexStringToBytes(secret); |
| ASSERT_GT(secret_bytes.size(), 0U); |
| SECItem secret_value = {siBuffer, secret_bytes.data(), |
| static_cast<unsigned int>(secret_bytes.size())}; |
| |
| ScopedSECItem derived_secret(SECITEM_AllocItem(nullptr, nullptr, 0U)); |
| |
| SECStatus rv = ECDH_Derive(&public_value, &ecParams, &secret_value, false, |
| derived_secret.get()); |
| ASSERT_EQ(expected_status, rv); |
| if (expected_status != SECSuccess) { |
| // Abort when we expect an error. |
| return; |
| } |
| |
| std::string derived_result = bytesToHexString(std::vector<uint8_t>( |
| derived_secret->data, derived_secret->data + derived_secret->len)); |
| std::cout << "derived secret: " << derived_result << std::endl; |
| EXPECT_EQ(derived_result, result); |
| } |
| }; |
| |
| TEST_F(ECLTest, TestECDH_DeriveP256) { |
| TestECDH_Derive( |
| "045ce5c643dffa402bc1837bbcbc223e51d06f20200470d341adfa9deed1bba10e850a16" |
| "368b673732a5c220a778990b22a0e74cdc3b22c7410b9dd552a5635497", |
| "971", "P256", "0", SECFailure); |
| } |
| TEST_F(ECLTest, TestECDH_DeriveP521) { |
| TestECDH_Derive( |
| "04" |
| "00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b" |
| "5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66" |
| "011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee" |
| "72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650", |
| "01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa5186" |
| "8783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e913863f7", |
| "P521", |
| "01BC33425E72A12779EACB2EDCC5B63D1281F7E86DBC7BF99A7ABD0CFE367DE4666D6EDB" |
| "B8525BFFE5222F0702C3096DEC0884CE572F5A15C423FDF44D01DD99C61D", |
| SECSuccess); |
| } |
| |
| } // nss_test |