tor-browser

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

tls_hkdf_unittest.cc (17278B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include <memory>
      8 #include "nss.h"
      9 #include "pk11pub.h"
     10 #include "secerr.h"
     11 #include "sslproto.h"
     12 #include "sslexp.h"
     13 #include "tls13hkdf.h"
     14 
     15 #include "databuffer.h"
     16 #include "gtest_utils.h"
     17 #include "nss_scoped_ptrs.h"
     18 
     19 namespace nss_test {
     20 
     21 const uint8_t kKey1Data[] = {
     22    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
     23    0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
     24    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
     25    0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f};
     26 const DataBuffer kKey1(kKey1Data, sizeof(kKey1Data));
     27 
     28 // The same as key1 but with the first byte
     29 // 0x01.
     30 const uint8_t kKey2Data[] = {
     31    0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
     32    0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
     33    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
     34    0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f};
     35 const DataBuffer kKey2(kKey2Data, sizeof(kKey2Data));
     36 
     37 const char kLabelMasterSecret[] = "master secret";
     38 
     39 const uint8_t kSessionHash[] = {
     40    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb,
     41    0xfc, 0xfd, 0xfe, 0xff, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
     42    0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xd0, 0xd1, 0xd2, 0xd3,
     43    0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
     44    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb,
     45    0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
     46    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0xe0, 0xe1, 0xe2, 0xe3,
     47    0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
     48    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb,
     49    0xfc, 0xfd, 0xfe, 0xff,
     50 };
     51 
     52 const size_t kHashLength[] = {
     53    0,  /* ssl_hash_none   */
     54    16, /* ssl_hash_md5    */
     55    20, /* ssl_hash_sha1   */
     56    28, /* ssl_hash_sha224 */
     57    32, /* ssl_hash_sha256 */
     58    48, /* ssl_hash_sha384 */
     59    64, /* ssl_hash_sha512 */
     60 };
     61 
     62 size_t GetHashLength(SSLHashType hash) {
     63  size_t i = static_cast<size_t>(hash);
     64  if (i < PR_ARRAY_SIZE(kHashLength)) {
     65    return kHashLength[i];
     66  }
     67  ADD_FAILURE() << "Unknown hash: " << hash;
     68  return 0;
     69 }
     70 
     71 PRUint16 GetSomeCipherSuiteForHash(SSLHashType hash) {
     72  switch (hash) {
     73    case ssl_hash_sha256:
     74      return TLS_AES_128_GCM_SHA256;
     75    case ssl_hash_sha384:
     76      return TLS_AES_256_GCM_SHA384;
     77    default:
     78      ADD_FAILURE() << "Unknown hash: " << hash;
     79  }
     80  return 0;
     81 }
     82 
     83 const std::string kHashName[] = {"None",    "MD5",     "SHA-1",  "SHA-224",
     84                                 "SHA-256", "SHA-384", "SHA-512"};
     85 
     86 static void ImportKey(ScopedPK11SymKey* to, const DataBuffer& key,
     87                      SSLHashType hash_type, PK11SlotInfo* slot) {
     88  ASSERT_LT(hash_type, sizeof(kHashLength));
     89  ASSERT_LE(kHashLength[hash_type], key.len());
     90  SECItem key_item = {siBuffer, const_cast<uint8_t*>(key.data()),
     91                      static_cast<unsigned int>(GetHashLength(hash_type))};
     92 
     93  PK11SymKey* inner =
     94      PK11_ImportSymKey(slot, CKM_SSL3_MASTER_KEY_DERIVE, PK11_OriginUnwrap,
     95                        CKA_DERIVE, &key_item, NULL);
     96  ASSERT_NE(nullptr, inner);
     97  to->reset(inner);
     98 }
     99 
    100 static void DumpData(const std::string& label, const uint8_t* buf, size_t len) {
    101  DataBuffer d(buf, len);
    102 
    103  std::cerr << label << ": " << d << std::endl;
    104 }
    105 
    106 void DumpKey(const std::string& label, ScopedPK11SymKey& key) {
    107  SECStatus rv = PK11_ExtractKeyValue(key.get());
    108  ASSERT_EQ(SECSuccess, rv);
    109 
    110  SECItem* key_data = PK11_GetKeyData(key.get());
    111  ASSERT_NE(nullptr, key_data);
    112 
    113  DumpData(label, key_data->data, key_data->len);
    114 }
    115 
    116 extern "C" {
    117 extern char ssl_trace;
    118 extern FILE* ssl_trace_iob;
    119 }
    120 
    121 class TlsHkdfTest : public ::testing::Test,
    122                    public ::testing::WithParamInterface<SSLHashType> {
    123 public:
    124  TlsHkdfTest()
    125      : k1_(), k2_(), hash_type_(GetParam()), slot_(PK11_GetInternalSlot()) {
    126    EXPECT_NE(nullptr, slot_);
    127    char* ev = getenv("SSLTRACE");
    128    if (ev && ev[0]) {
    129      ssl_trace = atoi(ev);
    130      ssl_trace_iob = stderr;
    131    }
    132  }
    133 
    134  void SetUp() {
    135    ImportKey(&k1_, kKey1, hash_type_, slot_.get());
    136    ImportKey(&k2_, kKey2, hash_type_, slot_.get());
    137  }
    138 
    139  void VerifyKey(const ScopedPK11SymKey& key, CK_MECHANISM_TYPE expected_mech,
    140                 const DataBuffer& expected_value) {
    141    EXPECT_EQ(expected_mech, PK11_GetMechanism(key.get()));
    142 
    143    SECStatus rv = PK11_ExtractKeyValue(key.get());
    144    ASSERT_EQ(SECSuccess, rv);
    145 
    146    SECItem* key_data = PK11_GetKeyData(key.get());
    147    ASSERT_NE(nullptr, key_data);
    148 
    149    EXPECT_EQ(expected_value.len(), key_data->len);
    150    EXPECT_EQ(
    151        0, memcmp(expected_value.data(), key_data->data, expected_value.len()));
    152  }
    153 
    154  void HkdfExtract(const ScopedPK11SymKey& ikmk1, const ScopedPK11SymKey& ikmk2,
    155                   SSLHashType base_hash, const DataBuffer& expected) {
    156    std::cerr << "Hash = " << kHashName[base_hash] << std::endl;
    157 
    158    PK11SymKey* prk = nullptr;
    159    SECStatus rv = tls13_HkdfExtract(ikmk1.get(), ikmk2.get(), base_hash, &prk);
    160    ASSERT_EQ(SECSuccess, rv);
    161    ScopedPK11SymKey prkk(prk);
    162 
    163    DumpKey("Output", prkk);
    164    VerifyKey(prkk, CKM_HKDF_DERIVE, expected);
    165 
    166    // Now test the public wrapper.
    167    PRUint16 cs = GetSomeCipherSuiteForHash(base_hash);
    168    rv = SSL_HkdfExtract(SSL_LIBRARY_VERSION_TLS_1_3, cs, ikmk1.get(),
    169                         ikmk2.get(), &prk);
    170    ASSERT_EQ(SECSuccess, rv);
    171    ASSERT_NE(nullptr, prk);
    172    VerifyKey(ScopedPK11SymKey(prk), CKM_HKDF_DERIVE, expected);
    173  }
    174 
    175  void HkdfExpandLabel(ScopedPK11SymKey* prk, SSLHashType base_hash,
    176                       const uint8_t* session_hash, size_t session_hash_len,
    177                       const char* label, size_t label_len,
    178                       const DataBuffer& expected) {
    179    ASSERT_NE(nullptr, prk);
    180    std::cerr << "Hash = " << kHashName[base_hash] << std::endl;
    181 
    182    std::vector<uint8_t> output(expected.len());
    183 
    184    SECStatus rv = tls13_HkdfExpandLabelRaw(
    185        prk->get(), base_hash, session_hash, session_hash_len, label, label_len,
    186        ssl_variant_stream, &output[0], output.size());
    187    ASSERT_EQ(SECSuccess, rv);
    188    DumpData("Output", &output[0], output.size());
    189    EXPECT_EQ(0, memcmp(expected.data(), &output[0], expected.len()));
    190 
    191    // Verify that the public API produces the same result.
    192    PRUint16 cs = GetSomeCipherSuiteForHash(base_hash);
    193    PK11SymKey* secret;
    194    rv = SSL_HkdfExpandLabel(SSL_LIBRARY_VERSION_TLS_1_3, cs, prk->get(),
    195                             session_hash, session_hash_len, label, label_len,
    196                             &secret);
    197    EXPECT_EQ(SECSuccess, rv);
    198    ASSERT_NE(nullptr, secret);
    199    VerifyKey(ScopedPK11SymKey(secret), CKM_HKDF_DERIVE, expected);
    200 
    201    // Verify that a key can be created with a different key type and size.
    202    rv = SSL_HkdfExpandLabelWithMech(
    203        SSL_LIBRARY_VERSION_TLS_1_3, cs, prk->get(), session_hash,
    204        session_hash_len, label, label_len, CKM_DES3_CBC_PAD, 24, &secret);
    205    EXPECT_EQ(SECSuccess, rv);
    206    ASSERT_NE(nullptr, secret);
    207    ScopedPK11SymKey with_mech(secret);
    208    EXPECT_EQ(static_cast<CK_MECHANISM_TYPE>(CKM_DES3_CBC_PAD),
    209              PK11_GetMechanism(with_mech.get()));
    210    // Just verify that the key is the right size.
    211    rv = PK11_ExtractKeyValue(with_mech.get());
    212    ASSERT_EQ(SECSuccess, rv);
    213    SECItem* key_data = PK11_GetKeyData(with_mech.get());
    214    ASSERT_NE(nullptr, key_data);
    215    EXPECT_EQ(24U, key_data->len);
    216  }
    217 
    218 protected:
    219  ScopedPK11SymKey k1_;
    220  ScopedPK11SymKey k2_;
    221  SSLHashType hash_type_;
    222 
    223 private:
    224  ScopedPK11SlotInfo slot_;
    225 };
    226 
    227 TEST_P(TlsHkdfTest, HkdfNullNull) {
    228  const uint8_t tv[][48] = {
    229      {/* ssl_hash_none   */},
    230      {/* ssl_hash_md5    */},
    231      {/* ssl_hash_sha1   */},
    232      {/* ssl_hash_sha224 */},
    233      {0x33, 0xad, 0x0a, 0x1c, 0x60, 0x7e, 0xc0, 0x3b, 0x09, 0xe6, 0xcd,
    234       0x98, 0x93, 0x68, 0x0c, 0xe2, 0x10, 0xad, 0xf3, 0x00, 0xaa, 0x1f,
    235       0x26, 0x60, 0xe1, 0xb2, 0x2e, 0x10, 0xf1, 0x70, 0xf9, 0x2a},
    236      {0x7e, 0xe8, 0x20, 0x6f, 0x55, 0x70, 0x02, 0x3e, 0x6d, 0xc7, 0x51, 0x9e,
    237       0xb1, 0x07, 0x3b, 0xc4, 0xe7, 0x91, 0xad, 0x37, 0xb5, 0xc3, 0x82, 0xaa,
    238       0x10, 0xba, 0x18, 0xe2, 0x35, 0x7e, 0x71, 0x69, 0x71, 0xf9, 0x36, 0x2f,
    239       0x2c, 0x2f, 0xe2, 0xa7, 0x6b, 0xfd, 0x78, 0xdf, 0xec, 0x4e, 0xa9, 0xb5}};
    240 
    241  const DataBuffer expected_data(tv[hash_type_], GetHashLength(hash_type_));
    242  HkdfExtract(nullptr, nullptr, hash_type_, expected_data);
    243 }
    244 
    245 TEST_P(TlsHkdfTest, HkdfKey1Only) {
    246  const uint8_t tv[][48] = {
    247      {/* ssl_hash_none   */},
    248      {/* ssl_hash_md5    */},
    249      {/* ssl_hash_sha1   */},
    250      {/* ssl_hash_sha224 */},
    251      {0x41, 0x6c, 0x53, 0x92, 0xb9, 0xf3, 0x6d, 0xf1, 0x88, 0xe9, 0x0e,
    252       0xb1, 0x4d, 0x17, 0xbf, 0x0d, 0xa1, 0x90, 0xbf, 0xdb, 0x7f, 0x1f,
    253       0x49, 0x56, 0xe6, 0xe5, 0x66, 0xa5, 0x69, 0xc8, 0xb1, 0x5c},
    254      {0x51, 0xb1, 0xd5, 0xb4, 0x59, 0x79, 0x79, 0x08, 0x4a, 0x15, 0xb2, 0xdb,
    255       0x84, 0xd3, 0xd6, 0xbc, 0xfc, 0x93, 0x45, 0xd9, 0xdc, 0x74, 0xda, 0x1a,
    256       0x57, 0xc2, 0x76, 0x9f, 0x3f, 0x83, 0x45, 0x2f, 0xf6, 0xf3, 0x56, 0x1f,
    257       0x58, 0x63, 0xdb, 0x88, 0xda, 0x40, 0xce, 0x63, 0x7d, 0x24, 0x37, 0xf3}};
    258 
    259  const DataBuffer expected_data(tv[hash_type_], GetHashLength(hash_type_));
    260  HkdfExtract(k1_, nullptr, hash_type_, expected_data);
    261 }
    262 
    263 TEST_P(TlsHkdfTest, HkdfKey2Only) {
    264  const uint8_t tv[][48] = {
    265      {/* ssl_hash_none   */},
    266      {/* ssl_hash_md5    */},
    267      {/* ssl_hash_sha1   */},
    268      {/* ssl_hash_sha224 */},
    269      {0x16, 0xaf, 0x00, 0x54, 0x3a, 0x56, 0xc8, 0x26, 0xa2, 0xa7, 0xfc,
    270       0xb6, 0x34, 0x66, 0x8a, 0xfd, 0x36, 0xdc, 0x8e, 0xce, 0xc4, 0xd2,
    271       0x6c, 0x7a, 0xdc, 0xe3, 0x70, 0x36, 0x3d, 0x60, 0xfa, 0x0b},
    272      {0x7b, 0x40, 0xf9, 0xef, 0x91, 0xff, 0xc9, 0xd1, 0x29, 0x24, 0x5c, 0xbf,
    273       0xf8, 0x82, 0x76, 0x68, 0xae, 0x4b, 0x63, 0xe8, 0x03, 0xdd, 0x39, 0xa8,
    274       0xd4, 0x6a, 0xf6, 0xe5, 0xec, 0xea, 0xf8, 0x7d, 0x91, 0x71, 0x81, 0xf1,
    275       0xdb, 0x3b, 0xaf, 0xbf, 0xde, 0x71, 0x61, 0x15, 0xeb, 0xb5, 0x5f, 0x68}};
    276 
    277  const DataBuffer expected_data(tv[hash_type_], GetHashLength(hash_type_));
    278  HkdfExtract(nullptr, k2_, hash_type_, expected_data);
    279 }
    280 
    281 TEST_P(TlsHkdfTest, HkdfKey1Key2) {
    282  const uint8_t tv[][48] = {
    283      {/* ssl_hash_none   */},
    284      {/* ssl_hash_md5    */},
    285      {/* ssl_hash_sha1   */},
    286      {/* ssl_hash_sha224 */},
    287      {0xa5, 0x68, 0x02, 0x5a, 0x95, 0xc9, 0x7f, 0x55, 0x38, 0xbc, 0xf7,
    288       0x97, 0xcc, 0x0f, 0xd5, 0xf6, 0xa8, 0x8d, 0x15, 0xbc, 0x0e, 0x85,
    289       0x74, 0x70, 0x3c, 0xa3, 0x65, 0xbd, 0x76, 0xcf, 0x9f, 0xd3},
    290      {0x01, 0x93, 0xc0, 0x07, 0x3f, 0x6a, 0x83, 0x0e, 0x2e, 0x4f, 0xb2, 0x58,
    291       0xe4, 0x00, 0x08, 0x5c, 0x68, 0x9c, 0x37, 0x32, 0x00, 0x37, 0xff, 0xc3,
    292       0x1c, 0x5b, 0x98, 0x0b, 0x02, 0x92, 0x3f, 0xfd, 0x73, 0x5a, 0x6f, 0x2a,
    293       0x95, 0xa3, 0xee, 0xf6, 0xd6, 0x8e, 0x6f, 0x86, 0xea, 0x63, 0xf8, 0x33}};
    294 
    295  const DataBuffer expected_data(tv[hash_type_], GetHashLength(hash_type_));
    296  HkdfExtract(k1_, k2_, hash_type_, expected_data);
    297 }
    298 
    299 TEST_P(TlsHkdfTest, HkdfExpandLabel) {
    300  const uint8_t tv[][48] = {
    301      {/* ssl_hash_none   */},
    302      {/* ssl_hash_md5    */},
    303      {/* ssl_hash_sha1   */},
    304      {/* ssl_hash_sha224 */},
    305      {0x3e, 0x4e, 0x6e, 0xd0, 0xbc, 0xc4, 0xf4, 0xff, 0xf0, 0xf5, 0x69,
    306       0xd0, 0x6c, 0x1e, 0x0e, 0x10, 0x32, 0xaa, 0xd7, 0xa3, 0xef, 0xf6,
    307       0xa8, 0x65, 0x8e, 0xbe, 0xee, 0xc7, 0x1f, 0x01, 0x6d, 0x3c},
    308      {0x41, 0xea, 0x77, 0x09, 0x8c, 0x90, 0x04, 0x10, 0xec, 0xbc, 0x37, 0xd8,
    309       0x5b, 0x54, 0xcd, 0x7b, 0x08, 0x15, 0x13, 0x20, 0xed, 0x1e, 0x3f, 0x54,
    310       0x74, 0xf7, 0x8b, 0x06, 0x38, 0x28, 0x06, 0x37, 0x75, 0x23, 0xa2, 0xb7,
    311       0x34, 0xb1, 0x72, 0x2e, 0x59, 0x6d, 0x5a, 0x31, 0xf5, 0x53, 0xab, 0x99}};
    312 
    313  const DataBuffer expected_data(tv[hash_type_], GetHashLength(hash_type_));
    314  HkdfExpandLabel(&k1_, hash_type_, kSessionHash, GetHashLength(hash_type_),
    315                  kLabelMasterSecret, strlen(kLabelMasterSecret),
    316                  expected_data);
    317 }
    318 
    319 TEST_P(TlsHkdfTest, HkdfExpandLabelNoHash) {
    320  const uint8_t tv[][48] = {
    321      {/* ssl_hash_none   */},
    322      {/* ssl_hash_md5    */},
    323      {/* ssl_hash_sha1   */},
    324      {/* ssl_hash_sha224 */},
    325      {0xb7, 0x08, 0x00, 0xe3, 0x8e, 0x48, 0x68, 0x91, 0xb1, 0x0f, 0x5e,
    326       0x6f, 0x22, 0x53, 0x6b, 0x84, 0x69, 0x75, 0xaa, 0xa3, 0x2a, 0xe7,
    327       0xde, 0xaa, 0xc3, 0xd1, 0xb4, 0x05, 0x22, 0x5c, 0x68, 0xf5},
    328      {0x13, 0xd3, 0x36, 0x9f, 0x3c, 0x78, 0xa0, 0x32, 0x40, 0xee, 0x16, 0xe9,
    329       0x11, 0x12, 0x66, 0xc7, 0x51, 0xad, 0xd8, 0x3c, 0xa1, 0xa3, 0x97, 0x74,
    330       0xd7, 0x45, 0xff, 0xa7, 0x88, 0x9e, 0x52, 0x17, 0x2e, 0xaa, 0x3a, 0xd2,
    331       0x35, 0xd8, 0xd5, 0x35, 0xfd, 0x65, 0x70, 0x9f, 0xa9, 0xf9, 0xfa, 0x23}};
    332 
    333  const DataBuffer expected_data(tv[hash_type_], GetHashLength(hash_type_));
    334  HkdfExpandLabel(&k1_, hash_type_, nullptr, 0, kLabelMasterSecret,
    335                  strlen(kLabelMasterSecret), expected_data);
    336 }
    337 
    338 TEST_P(TlsHkdfTest, BadExtractWrapperInput) {
    339  PK11SymKey* key = nullptr;
    340 
    341  // Bad version.
    342  EXPECT_EQ(SECFailure,
    343            SSL_HkdfExtract(SSL_LIBRARY_VERSION_TLS_1_2, TLS_AES_128_GCM_SHA256,
    344                            k1_.get(), k2_.get(), &key));
    345  EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
    346 
    347  // Bad ciphersuite.
    348  EXPECT_EQ(SECFailure,
    349            SSL_HkdfExtract(SSL_LIBRARY_VERSION_TLS_1_3, TLS_RSA_WITH_NULL_SHA,
    350                            k1_.get(), k2_.get(), &key));
    351  EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
    352 
    353  // Old ciphersuite.
    354  EXPECT_EQ(SECFailure, SSL_HkdfExtract(SSL_LIBRARY_VERSION_TLS_1_3,
    355                                        TLS_RSA_WITH_AES_128_CBC_SHA, k1_.get(),
    356                                        k2_.get(), &key));
    357  EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
    358 
    359  // NULL outparam..
    360  EXPECT_EQ(SECFailure, SSL_HkdfExtract(SSL_LIBRARY_VERSION_TLS_1_3,
    361                                        TLS_RSA_WITH_AES_128_CBC_SHA, k1_.get(),
    362                                        k2_.get(), nullptr));
    363  EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
    364 
    365  EXPECT_EQ(nullptr, key);
    366 }
    367 
    368 TEST_P(TlsHkdfTest, BadExpandLabelWrapperInput) {
    369  PK11SymKey* key = nullptr;
    370  static const char* kLabel = "label";
    371 
    372  // Bad version.
    373  EXPECT_EQ(
    374      SECFailure,
    375      SSL_HkdfExpandLabel(SSL_LIBRARY_VERSION_TLS_1_2, TLS_AES_128_GCM_SHA256,
    376                          k1_.get(), nullptr, 0, kLabel, strlen(kLabel), &key));
    377  EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
    378 
    379  // Bad ciphersuite.
    380  EXPECT_EQ(
    381      SECFailure,
    382      SSL_HkdfExpandLabel(SSL_LIBRARY_VERSION_TLS_1_3, TLS_RSA_WITH_NULL_MD5,
    383                          k1_.get(), nullptr, 0, kLabel, strlen(kLabel), &key));
    384  EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
    385 
    386  // Old ciphersuite.
    387  EXPECT_EQ(SECFailure,
    388            SSL_HkdfExpandLabel(SSL_LIBRARY_VERSION_TLS_1_3,
    389                                TLS_RSA_WITH_AES_128_CBC_SHA, k1_.get(),
    390                                nullptr, 0, kLabel, strlen(kLabel), &key));
    391  EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
    392 
    393  // Null PRK.
    394  EXPECT_EQ(SECFailure, SSL_HkdfExpandLabel(
    395                            SSL_LIBRARY_VERSION_TLS_1_2, TLS_AES_128_GCM_SHA256,
    396                            nullptr, nullptr, 0, kLabel, strlen(kLabel), &key));
    397  EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
    398 
    399  // Null, non-zero-length handshake hash.
    400  EXPECT_EQ(
    401      SECFailure,
    402      SSL_HkdfExpandLabel(SSL_LIBRARY_VERSION_TLS_1_2, TLS_AES_128_GCM_SHA256,
    403                          k1_.get(), nullptr, 2, kLabel, strlen(kLabel), &key));
    404 
    405  EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
    406  // Null, non-zero-length label.
    407  EXPECT_EQ(SECFailure,
    408            SSL_HkdfExpandLabel(SSL_LIBRARY_VERSION_TLS_1_3,
    409                                TLS_AES_128_GCM_SHA256, k1_.get(), nullptr, 0,
    410                                nullptr, strlen(kLabel), &key));
    411  EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
    412 
    413  // Null, empty label.
    414  EXPECT_EQ(SECFailure, SSL_HkdfExpandLabel(SSL_LIBRARY_VERSION_TLS_1_3,
    415                                            TLS_AES_128_GCM_SHA256, k1_.get(),
    416                                            nullptr, 0, nullptr, 0, &key));
    417  EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
    418 
    419  // Null key pointer..
    420  EXPECT_EQ(SECFailure,
    421            SSL_HkdfExpandLabel(SSL_LIBRARY_VERSION_TLS_1_3,
    422                                TLS_AES_128_GCM_SHA256, k1_.get(), nullptr, 0,
    423                                kLabel, strlen(kLabel), nullptr));
    424  EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
    425 
    426  EXPECT_EQ(nullptr, key);
    427 }
    428 
    429 static const SSLHashType kHashTypes[] = {ssl_hash_sha256, ssl_hash_sha384};
    430 INSTANTIATE_TEST_SUITE_P(AllHashFuncs, TlsHkdfTest,
    431                         ::testing::ValuesIn(kHashTypes));
    432 
    433 }  // namespace nss_test