tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ecl_unittest.cc (4545B)


      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 
      7 #include <stdint.h>
      8 
      9 #include "blapi.h"
     10 #include "nss_scoped_ptrs.h"
     11 #include "secerr.h"
     12 
     13 namespace nss_test {
     14 
     15 class ECLTest : public ::testing::Test {
     16 protected:
     17  ECCurveName GetCurveName(std::string name) {
     18    if (name == "P256") return ECCurve_NIST_P256;
     19    if (name == "P384") return ECCurve_NIST_P384;
     20    if (name == "P521") return ECCurve_NIST_P521;
     21    return ECCurve_pastLastCurve;
     22  }
     23  std::vector<uint8_t> hexStringToBytes(std::string s) {
     24    std::vector<uint8_t> bytes;
     25    for (size_t i = 0; i < s.length(); i += 2) {
     26      bytes.push_back(std::stoul(s.substr(i, 2), nullptr, 16));
     27    }
     28    return bytes;
     29  }
     30  std::string bytesToHexString(std::vector<uint8_t> bytes) {
     31    std::stringstream s;
     32    for (auto b : bytes) {
     33      s << std::setfill('0') << std::setw(2) << std::uppercase << std::hex
     34        << static_cast<int>(b);
     35    }
     36    return s.str();
     37  }
     38  void ecName2params(const std::string curve, SECItem *params) {
     39    SECOidData *oidData = nullptr;
     40 
     41    switch (GetCurveName(curve)) {
     42      case ECCurve_NIST_P256:
     43        oidData = SECOID_FindOIDByTag(SEC_OID_ANSIX962_EC_PRIME256V1);
     44        break;
     45      case ECCurve_NIST_P384:
     46        oidData = SECOID_FindOIDByTag(SEC_OID_SECG_EC_SECP384R1);
     47        break;
     48      case ECCurve_NIST_P521:
     49        oidData = SECOID_FindOIDByTag(SEC_OID_SECG_EC_SECP521R1);
     50        break;
     51      default:
     52        FAIL();
     53    }
     54    ASSERT_NE(oidData, nullptr);
     55 
     56    if (SECITEM_AllocItem(nullptr, params, (2 + oidData->oid.len)) == nullptr) {
     57      FAIL() << "Couldn't allocate memory for OID.";
     58    }
     59    params->data[0] = SEC_ASN1_OBJECT_ID;
     60    params->data[1] = oidData->oid.len;
     61    memcpy(params->data + 2, oidData->oid.data, oidData->oid.len);
     62  }
     63 
     64  void TestECDH_Derive(const std::string p, const std::string secret,
     65                       const std::string group_name, const std::string result,
     66                       const SECStatus expected_status) {
     67    ECParams ecParams = {0};
     68    ScopedSECItem ecEncodedParams(SECITEM_AllocItem(nullptr, nullptr, 0U));
     69    ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
     70 
     71    ASSERT_TRUE(arena && ecEncodedParams);
     72 
     73    ecName2params(group_name, ecEncodedParams.get());
     74    EC_FillParams(arena.get(), ecEncodedParams.get(), &ecParams);
     75 
     76    std::vector<uint8_t> p_bytes = hexStringToBytes(p);
     77    ASSERT_GT(p_bytes.size(), 0U);
     78    SECItem public_value = {siBuffer, p_bytes.data(),
     79                            static_cast<unsigned int>(p_bytes.size())};
     80 
     81    std::vector<uint8_t> secret_bytes = hexStringToBytes(secret);
     82    ASSERT_GT(secret_bytes.size(), 0U);
     83    SECItem secret_value = {siBuffer, secret_bytes.data(),
     84                            static_cast<unsigned int>(secret_bytes.size())};
     85 
     86    ScopedSECItem derived_secret(SECITEM_AllocItem(nullptr, nullptr, 0U));
     87 
     88    SECStatus rv = ECDH_Derive(&public_value, &ecParams, &secret_value, false,
     89                               derived_secret.get());
     90    ASSERT_EQ(expected_status, rv);
     91    if (expected_status != SECSuccess) {
     92      // Abort when we expect an error.
     93      return;
     94    }
     95 
     96    std::string derived_result = bytesToHexString(std::vector<uint8_t>(
     97        derived_secret->data, derived_secret->data + derived_secret->len));
     98    std::cout << "derived secret: " << derived_result << std::endl;
     99    EXPECT_EQ(derived_result, result);
    100  }
    101 };
    102 
    103 TEST_F(ECLTest, TestECDH_DeriveP256) {
    104  TestECDH_Derive(
    105      "045ce5c643dffa402bc1837bbcbc223e51d06f20200470d341adfa9deed1bba10e850a16"
    106      "368b673732a5c220a778990b22a0e74cdc3b22c7410b9dd552a5635497",
    107      "971", "P256", "0", SECFailure);
    108 }
    109 TEST_F(ECLTest, TestECDH_DeriveP521) {
    110  TestECDH_Derive(
    111      "04"
    112      "00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b"
    113      "5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66"
    114      "011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee"
    115      "72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650",
    116      "01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa5186"
    117      "8783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e913863f7",
    118      "P521",
    119      "01BC33425E72A12779EACB2EDCC5B63D1281F7E86DBC7BF99A7ABD0CFE367DE4666D6EDB"
    120      "B8525BFFE5222F0702C3096DEC0884CE572F5A15C423FDF44D01DD99C61D",
    121      SECSuccess);
    122 }
    123 
    124 }  // namespace nss_test