/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* 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 "secerr.h"
#include "sslproto.h"
#include "sslexp.h"
#include "tls13hkdf.h"
#include "databuffer.h"
#include "gtest_utils.h"
#include "nss_scoped_ptrs.h"
namespace nss_test {
const uint8_t kKey1Data[] = {
0 x00,
0 x01,
0 x02,
0 x03,
0 x04,
0 x05,
0 x06,
0 x07,
0 x08,
0 x09,
0 x0a,
0 x0b,
0 x0c,
0 x0d,
0 x0e,
0 x0f,
0 x10,
0 x11,
0 x12,
0 x13,
0 x14,
0 x15,
0 x16,
0 x17,
0 x18,
0 x19,
0 x1a,
0 x1b,
0 x1c,
0 x1d,
0 x1e,
0 x1f,
0 x20,
0 x21,
0 x22,
0 x23,
0 x24,
0 x25,
0 x26,
0 x27,
0 x28,
0 x29,
0 x2a,
0 x2b,
0 x2c,
0 x2d,
0 x2e,
0 x2f};
const DataBuffer kKey1(kKey1Data,
sizeof (kKey1Data));
// The same as key1 but with the first byte
// 0x01.
const uint8_t kKey2Data[] = {
0 x01,
0 x01,
0 x02,
0 x03,
0 x04,
0 x05,
0 x06,
0 x07,
0 x08,
0 x09,
0 x0a,
0 x0b,
0 x0c,
0 x0d,
0 x0e,
0 x0f,
0 x10,
0 x11,
0 x12,
0 x13,
0 x14,
0 x15,
0 x16,
0 x17,
0 x18,
0 x19,
0 x1a,
0 x1b,
0 x1c,
0 x1d,
0 x1e,
0 x1f,
0 x20,
0 x21,
0 x22,
0 x23,
0 x24,
0 x25,
0 x26,
0 x27,
0 x28,
0 x29,
0 x2a,
0 x2b,
0 x2c,
0 x2d,
0 x2e,
0 x2f};
const DataBuffer kKey2(kKey2Data,
sizeof (kKey2Data));
const char kLabelMasterSecret[] =
"master secret" ;
const uint8_t kSessionHash[] = {
0 xf0,
0 xf1,
0 xf2,
0 xf3,
0 xf4,
0 xf5,
0 xf6,
0 xf7,
0 xf8,
0 xf9,
0 xfa,
0 xfb,
0 xfc,
0 xfd,
0 xfe,
0 xff,
0 xe0,
0 xe1,
0 xe2,
0 xe3,
0 xe4,
0 xe5,
0 xe6,
0 xe7,
0 xe8,
0 xe9,
0 xea,
0 xeb,
0 xec,
0 xed,
0 xee,
0 xef,
0 xd0,
0 xd1,
0 xd2,
0 xd3,
0 xd4,
0 xd5,
0 xd6,
0 xd7,
0 xd8,
0 xd9,
0 xda,
0 xdb,
0 xdc,
0 xdd,
0 xde,
0 xdf,
0 xe0,
0 xe1,
0 xe2,
0 xe3,
0 xe4,
0 xe5,
0 xe6,
0 xe7,
0 xe8,
0 xe9,
0 xea,
0 xeb,
0 xec,
0 xed,
0 xee,
0 xef,
0 xf0,
0 xf1,
0 xf2,
0 xf3,
0 xf4,
0 xf5,
0 xf6,
0 xf7,
0 xf8,
0 xf9,
0 xfa,
0 xfb,
0 xfc,
0 xfd,
0 xfe,
0 xff,
0 xe0,
0 xe1,
0 xe2,
0 xe3,
0 xe4,
0 xe5,
0 xe6,
0 xe7,
0 xe8,
0 xe9,
0 xea,
0 xeb,
0 xec,
0 xed,
0 xee,
0 xef,
0 xf0,
0 xf1,
0 xf2,
0 xf3,
0 xf4,
0 xf5,
0 xf6,
0 xf7,
0 xf8,
0 xf9,
0 xfa,
0 xfb,
0 xfc,
0 xfd,
0 xfe,
0 xff,
};
const size_t kHashLength[] = {
0 ,
/* ssl_hash_none */
16 ,
/* ssl_hash_md5 */
20 ,
/* ssl_hash_sha1 */
28 ,
/* ssl_hash_sha224 */
32 ,
/* ssl_hash_sha256 */
48 ,
/* ssl_hash_sha384 */
64 ,
/* ssl_hash_sha512 */
};
size_t GetHashLength(SSLHashType hash) {
size_t i =
static_cast <size_t>(hash);
if (i < PR_ARRAY_SIZE(kHashLength)) {
return kHashLength[i];
}
ADD_FAILURE() <<
"Unknown hash: " << hash;
return 0 ;
}
PRUint16 GetSomeCipherSuiteForHash(SSLHashType hash) {
switch (hash) {
case ssl_hash_sha256:
return TLS_AES_128_GCM_SHA256;
case ssl_hash_sha384:
return TLS_AES_256_GCM_SHA384;
default :
ADD_FAILURE() <<
"Unknown hash: " << hash;
}
return 0 ;
}
const std::string kHashName[] = {
"None" ,
"MD5" ,
"SHA-1" ,
"SHA-224" ,
"SHA-256" ,
"SHA-384" ,
"SHA-512" };
static void ImportKey(ScopedPK11SymKey* to,
const DataBuffer& key,
SSLHashType hash_type, PK11SlotInfo* slot) {
ASSERT_LT(hash_type,
sizeof (kHashLength));
ASSERT_LE(kHashLength[hash_type], key.len());
SECItem key_item = {siBuffer,
const_cast <uint8_t*>(key.data()),
static_cast <
unsigned int >(GetHashLength(hash_type))};
PK11SymKey* inner =
PK11_ImportSymKey(slot, CKM_SSL3_MASTER_KEY_DERIVE, PK11_OriginUnwrap,
CKA_DERIVE, &key_item, NULL);
ASSERT_NE(nullptr, inner);
to->reset(inner);
}
static void DumpData(
const std::string& label,
const uint8_t* buf, size_t len) {
DataBuffer d(buf, len);
std::cerr << label <<
": " << d << std::endl;
}
void DumpKey(
const std::string& label, ScopedPK11SymKey& key) {
SECStatus rv = PK11_ExtractKeyValue(key.get());
ASSERT_EQ(SECSuccess, rv);
SECItem* key_data = PK11_GetKeyData(key.get());
ASSERT_NE(nullptr, key_data);
DumpData(label, key_data->data, key_data->len);
}
extern "C" {
extern char ssl_trace;
extern FILE* ssl_trace_iob;
}
class TlsHkdfTest :
public ::testing::Test,
public ::testing::WithParamInterface<SSLHashType> {
public :
TlsHkdfTest()
: k1_(), k2_(), hash_type_(GetParam()), slot_(PK11_GetInternalSlot()) {
EXPECT_NE(nullptr, slot_);
char * ev = getenv(
"SSLTRACE" );
if (ev && ev[
0 ]) {
ssl_trace = atoi(ev);
ssl_trace_iob = stderr;
}
}
void SetUp() {
ImportKey(&k1_, kKey1, hash_type_, slot_.get());
ImportKey(&k2_, kKey2, hash_type_, slot_.get());
}
void VerifyKey(
const ScopedPK11SymKey& key, CK_MECHANISM_TYPE expected_mech,
const DataBuffer& expected_value) {
EXPECT_EQ(expected_mech, PK11_GetMechanism(key.get()));
SECStatus rv = PK11_ExtractKeyValue(key.get());
ASSERT_EQ(SECSuccess, rv);
SECItem* key_data = PK11_GetKeyData(key.get());
ASSERT_NE(nullptr, key_data);
EXPECT_EQ(expected_value.len(), key_data->len);
EXPECT_EQ(
0 , memcmp(expected_value.data(), key_data->data, expected_value.len()));
}
void HkdfExtract(
const ScopedPK11SymKey& ikmk1,
const ScopedPK11SymKey& ikmk2,
SSLHashType base_hash,
const DataBuffer& expected) {
std::cerr <<
"Hash = " << kHashName[base_hash] << std::endl;
PK11SymKey* prk = nullptr;
SECStatus rv = tls13_HkdfExtract(ikmk1.get(), ikmk2.get(), base_hash, &prk);
ASSERT_EQ(SECSuccess, rv);
ScopedPK11SymKey prkk(prk);
DumpKey(
"Output" , prkk);
VerifyKey(prkk, CKM_HKDF_DERIVE, expected);
// Now test the public wrapper.
PRUint16 cs = GetSomeCipherSuiteForHash(base_hash);
rv = SSL_HkdfExtract(SSL_LIBRARY_VERSION_TLS_1_3, cs, ikmk1.get(),
ikmk2.get(), &prk);
ASSERT_EQ(SECSuccess, rv);
ASSERT_NE(nullptr, prk);
VerifyKey(ScopedPK11SymKey(prk), CKM_HKDF_DERIVE, expected);
}
void HkdfExpandLabel(ScopedPK11SymKey* prk, SSLHashType base_hash,
const uint8_t* session_hash, size_t session_hash_len,
const char * label, size_t label_len,
const DataBuffer& expected) {
ASSERT_NE(nullptr, prk);
std::cerr <<
"Hash = " << kHashName[base_hash] << std::endl;
std::vector<uint8_t> output(expected.len());
SECStatus rv = tls13_HkdfExpandLabelRaw(
prk->get(), base_hash, session_hash, session_hash_len, label, label_len,
ssl_variant_stream, &output[
0 ], output.size());
ASSERT_EQ(SECSuccess, rv);
DumpData(
"Output" , &output[
0 ], output.size());
EXPECT_EQ(
0 , memcmp(expected.data(), &output[
0 ], expected.len()))
;
// Verify that the public API produces the same result.
PRUint16 cs = GetSomeCipherSuiteForHash(base_hash);
PK11SymKey* secret;
rv = SSL_HkdfExpandLabel(SSL_LIBRARY_VERSION_TLS_1_3, cs, prk->get(),
session_hash, session_hash_len, label, label_len,
&secret);
EXPECT_EQ(SECSuccess, rv);
ASSERT_NE(nullptr, secret);
VerifyKey(ScopedPK11SymKey(secret), CKM_HKDF_DERIVE, expected);
// Verify that a key can be created with a different key type and size.
rv = SSL_HkdfExpandLabelWithMech(
SSL_LIBRARY_VERSION_TLS_1_3, cs, prk->get(), session_hash,
session_hash_len, label, label_len, CKM_DES3_CBC_PAD, 24 , &secret);
EXPECT_EQ(SECSuccess, rv);
ASSERT_NE(nullptr, secret);
ScopedPK11SymKey with_mech(secret);
EXPECT_EQ(static_cast <CK_MECHANISM_TYPE>(CKM_DES3_CBC_PAD),
PK11_GetMechanism(with_mech.get()));
// Just verify that the key is the right size.
rv = PK11_ExtractKeyValue(with_mech.get());
ASSERT_EQ(SECSuccess, rv);
SECItem* key_data = PK11_GetKeyData(with_mech.get());
ASSERT_NE(nullptr, key_data);
EXPECT_EQ(24 U, key_data->len);
}
protected :
ScopedPK11SymKey k1_;
ScopedPK11SymKey k2_;
SSLHashType hash_type_;
private :
ScopedPK11SlotInfo slot_;
};
TEST_P(TlsHkdfTest, HkdfNullNull) {
const uint8_t tv[][48 ] = {
{/* ssl_hash_none */},
{/* ssl_hash_md5 */},
{/* ssl_hash_sha1 */},
{/* ssl_hash_sha224 */},
{0 x33, 0 xad, 0 x0a, 0 x1c, 0 x60, 0 x7e, 0 xc0, 0 x3b, 0 x09, 0 xe6, 0 xcd,
0 x98, 0 x93, 0 x68, 0 x0c, 0 xe2, 0 x10, 0 xad, 0 xf3, 0 x00, 0 xaa, 0 x1f,
0 x26, 0 x60, 0 xe1, 0 xb2, 0 x2e, 0 x10, 0 xf1, 0 x70, 0 xf9, 0 x2a},
{0 x7e, 0 xe8, 0 x20, 0 x6f, 0 x55, 0 x70, 0 x02, 0 x3e, 0 x6d, 0 xc7, 0 x51, 0 x9e,
0 xb1, 0 x07, 0 x3b, 0 xc4, 0 xe7, 0 x91, 0 xad, 0 x37, 0 xb5, 0 xc3, 0 x82, 0 xaa,
0 x10, 0 xba, 0 x18, 0 xe2, 0 x35, 0 x7e, 0 x71, 0 x69, 0 x71, 0 xf9, 0 x36, 0 x2f,
0 x2c, 0 x2f, 0 xe2, 0 xa7, 0 x6b, 0 xfd, 0 x78, 0 xdf, 0 xec, 0 x4e, 0 xa9, 0 xb5}};
const DataBuffer expected_data(tv[hash_type_], GetHashLength(hash_type_));
HkdfExtract(nullptr, nullptr, hash_type_, expected_data);
}
TEST_P(TlsHkdfTest, HkdfKey1Only) {
const uint8_t tv[][48 ] = {
{/* ssl_hash_none */},
{/* ssl_hash_md5 */},
{/* ssl_hash_sha1 */},
{/* ssl_hash_sha224 */},
{0 x41, 0 x6c, 0 x53, 0 x92, 0 xb9, 0 xf3, 0 x6d, 0 xf1, 0 x88, 0 xe9, 0 x0e,
0 xb1, 0 x4d, 0 x17, 0 xbf, 0 x0d, 0 xa1, 0 x90, 0 xbf, 0 xdb, 0 x7f, 0 x1f,
0 x49, 0 x56, 0 xe6, 0 xe5, 0 x66, 0 xa5, 0 x69, 0 xc8, 0 xb1, 0 x5c},
{0 x51, 0 xb1, 0 xd5, 0 xb4, 0 x59, 0 x79, 0 x79, 0 x08, 0 x4a, 0 x15, 0 xb2, 0 xdb,
0 x84, 0 xd3, 0 xd6, 0 xbc, 0 xfc, 0 x93, 0 x45, 0 xd9, 0 xdc, 0 x74, 0 xda, 0 x1a,
0 x57, 0 xc2, 0 x76, 0 x9f, 0 x3f, 0 x83, 0 x45, 0 x2f, 0 xf6, 0 xf3, 0 x56, 0 x1f,
0 x58, 0 x63, 0 xdb, 0 x88, 0 xda, 0 x40, 0 xce, 0 x63, 0 x7d, 0 x24, 0 x37, 0 xf3}};
const DataBuffer expected_data(tv[hash_type_], GetHashLength(hash_type_));
HkdfExtract(k1_, nullptr, hash_type_, expected_data);
}
TEST_P(TlsHkdfTest, HkdfKey2Only) {
const uint8_t tv[][48 ] = {
{/* ssl_hash_none */},
{/* ssl_hash_md5 */},
{/* ssl_hash_sha1 */},
{/* ssl_hash_sha224 */},
{0 x16, 0 xaf, 0 x00, 0 x54, 0 x3a, 0 x56, 0 xc8, 0 x26, 0 xa2, 0 xa7, 0 xfc,
0 xb6, 0 x34, 0 x66, 0 x8a, 0 xfd, 0 x36, 0 xdc, 0 x8e, 0 xce, 0 xc4, 0 xd2,
0 x6c, 0 x7a, 0 xdc, 0 xe3, 0 x70, 0 x36, 0 x3d, 0 x60, 0 xfa, 0 x0b},
{0 x7b, 0 x40, 0 xf9, 0 xef, 0 x91, 0 xff, 0 xc9, 0 xd1, 0 x29, 0 x24, 0 x5c, 0 xbf,
0 xf8, 0 x82, 0 x76, 0 x68, 0 xae, 0 x4b, 0 x63, 0 xe8, 0 x03, 0 xdd, 0 x39, 0 xa8,
0 xd4, 0 x6a, 0 xf6, 0 xe5, 0 xec, 0 xea, 0 xf8, 0 x7d, 0 x91, 0 x71, 0 x81, 0 xf1,
0 xdb, 0 x3b, 0 xaf, 0 xbf, 0 xde, 0 x71, 0 x61, 0 x15, 0 xeb, 0 xb5, 0 x5f, 0 x68}};
const DataBuffer expected_data(tv[hash_type_], GetHashLength(hash_type_));
HkdfExtract(nullptr, k2_, hash_type_, expected_data);
}
TEST_P(TlsHkdfTest, HkdfKey1Key2) {
const uint8_t tv[][48 ] = {
{/* ssl_hash_none */},
{/* ssl_hash_md5 */},
{/* ssl_hash_sha1 */},
{/* ssl_hash_sha224 */},
{0 xa5, 0 x68, 0 x02, 0 x5a, 0 x95, 0 xc9, 0 x7f, 0 x55, 0 x38, 0 xbc, 0 xf7,
0 x97, 0 xcc, 0 x0f, 0 xd5, 0 xf6, 0 xa8, 0 x8d, 0 x15, 0 xbc, 0 x0e, 0 x85,
0 x74, 0 x70, 0 x3c, 0 xa3, 0 x65, 0 xbd, 0 x76, 0 xcf, 0 x9f, 0 xd3},
{0 x01, 0 x93, 0 xc0, 0 x07, 0 x3f, 0 x6a, 0 x83, 0 x0e, 0 x2e, 0 x4f, 0 xb2, 0 x58,
0 xe4, 0 x00, 0 x08, 0 x5c, 0 x68, 0 x9c, 0 x37, 0 x32, 0 x00, 0 x37, 0 xff, 0 xc3,
0 x1c, 0 x5b, 0 x98, 0 x0b, 0 x02, 0 x92, 0 x3f, 0 xfd, 0 x73, 0 x5a, 0 x6f, 0 x2a,
0 x95, 0 xa3, 0 xee, 0 xf6, 0 xd6, 0 x8e, 0 x6f, 0 x86, 0 xea, 0 x63, 0 xf8, 0 x33}};
const DataBuffer expected_data(tv[hash_type_], GetHashLength(hash_type_));
HkdfExtract(k1_, k2_, hash_type_, expected_data);
}
TEST_P(TlsHkdfTest, HkdfExpandLabel) {
const uint8_t tv[][48 ] = {
{/* ssl_hash_none */},
{/* ssl_hash_md5 */},
{/* ssl_hash_sha1 */},
{/* ssl_hash_sha224 */},
{0 x3e, 0 x4e, 0 x6e, 0 xd0, 0 xbc, 0 xc4, 0 xf4, 0 xff, 0 xf0, 0 xf5, 0 x69,
0 xd0, 0 x6c, 0 x1e, 0 x0e, 0 x10, 0 x32, 0 xaa, 0 xd7, 0 xa3, 0 xef, 0 xf6,
0 xa8, 0 x65, 0 x8e, 0 xbe, 0 xee, 0 xc7, 0 x1f, 0 x01, 0 x6d, 0 x3c},
{0 x41, 0 xea, 0 x77, 0 x09, 0 x8c, 0 x90, 0 x04, 0 x10, 0 xec, 0 xbc, 0 x37, 0 xd8,
0 x5b, 0 x54, 0 xcd, 0 x7b, 0 x08, 0 x15, 0 x13, 0 x20, 0 xed, 0 x1e, 0 x3f, 0 x54,
0 x74, 0 xf7, 0 x8b, 0 x06, 0 x38, 0 x28, 0 x06, 0 x37, 0 x75, 0 x23, 0 xa2, 0 xb7,
0 x34, 0 xb1, 0 x72, 0 x2e, 0 x59, 0 x6d, 0 x5a, 0 x31, 0 xf5, 0 x53, 0 xab, 0 x99}};
const DataBuffer expected_data(tv[hash_type_], GetHashLength(hash_type_));
HkdfExpandLabel(&k1_, hash_type_, kSessionHash, GetHashLength(hash_type_),
kLabelMasterSecret, strlen(kLabelMasterSecret),
expected_data);
}
TEST_P(TlsHkdfTest, HkdfExpandLabelNoHash) {
const uint8_t tv[][48 ] = {
{/* ssl_hash_none */},
{/* ssl_hash_md5 */},
{/* ssl_hash_sha1 */},
{/* ssl_hash_sha224 */},
{0 xb7, 0 x08, 0 x00, 0 xe3, 0 x8e, 0 x48, 0 x68, 0 x91, 0 xb1, 0 x0f, 0 x5e,
0 x6f, 0 x22, 0 x53, 0 x6b, 0 x84, 0 x69, 0 x75, 0 xaa, 0 xa3, 0 x2a, 0 xe7,
0 xde, 0 xaa, 0 xc3, 0 xd1, 0 xb4, 0 x05, 0 x22, 0 x5c, 0 x68, 0 xf5},
{0 x13, 0 xd3, 0 x36, 0 x9f, 0 x3c, 0 x78, 0 xa0, 0 x32, 0 x40, 0 xee, 0 x16, 0 xe9,
0 x11, 0 x12, 0 x66, 0 xc7, 0 x51, 0 xad, 0 xd8, 0 x3c, 0 xa1, 0 xa3, 0 x97, 0 x74,
0 xd7, 0 x45, 0 xff, 0 xa7, 0 x88, 0 x9e, 0 x52, 0 x17, 0 x2e, 0 xaa, 0 x3a, 0 xd2,
0 x35, 0 xd8, 0 xd5, 0 x35, 0 xfd, 0 x65, 0 x70, 0 x9f, 0 xa9, 0 xf9, 0 xfa, 0 x23}};
const DataBuffer expected_data(tv[hash_type_], GetHashLength(hash_type_));
HkdfExpandLabel(&k1_, hash_type_, nullptr, 0 , kLabelMasterSecret,
strlen(kLabelMasterSecret), expected_data);
}
TEST_P(TlsHkdfTest, BadExtractWrapperInput) {
PK11SymKey* key = nullptr;
// Bad version.
EXPECT_EQ(SECFailure,
SSL_HkdfExtract(SSL_LIBRARY_VERSION_TLS_1_2, TLS_AES_128_GCM_SHA256,
k1_.get(), k2_.get(), &key));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
// Bad ciphersuite.
EXPECT_EQ(SECFailure,
SSL_HkdfExtract(SSL_LIBRARY_VERSION_TLS_1_3, TLS_RSA_WITH_NULL_SHA,
k1_.get(), k2_.get(), &key));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
// Old ciphersuite.
EXPECT_EQ(SECFailure, SSL_HkdfExtract(SSL_LIBRARY_VERSION_TLS_1_3,
TLS_RSA_WITH_AES_128_CBC_SHA, k1_.get(),
k2_.get(), &key));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
// NULL outparam..
EXPECT_EQ(SECFailure, SSL_HkdfExtract(SSL_LIBRARY_VERSION_TLS_1_3,
TLS_RSA_WITH_AES_128_CBC_SHA, k1_.get(),
k2_.get(), nullptr));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
EXPECT_EQ(nullptr, key);
}
TEST_P(TlsHkdfTest, BadExpandLabelWrapperInput) {
PK11SymKey* key = nullptr;
static const char * kLabel = "label" ;
// Bad version.
EXPECT_EQ(
SECFailure,
SSL_HkdfExpandLabel(SSL_LIBRARY_VERSION_TLS_1_2, TLS_AES_128_GCM_SHA256,
k1_.get(), nullptr, 0 , kLabel, strlen(kLabel), &key));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
// Bad ciphersuite.
EXPECT_EQ(
SECFailure,
SSL_HkdfExpandLabel(SSL_LIBRARY_VERSION_TLS_1_3, TLS_RSA_WITH_NULL_MD5,
k1_.get(), nullptr, 0 , kLabel, strlen(kLabel), &key));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
// Old ciphersuite.
EXPECT_EQ(SECFailure,
SSL_HkdfExpandLabel(SSL_LIBRARY_VERSION_TLS_1_3,
TLS_RSA_WITH_AES_128_CBC_SHA, k1_.get(),
nullptr, 0 , kLabel, strlen(kLabel), &key));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
// Null PRK.
EXPECT_EQ(SECFailure, SSL_HkdfExpandLabel(
SSL_LIBRARY_VERSION_TLS_1_2, TLS_AES_128_GCM_SHA256,
nullptr, nullptr, 0 , kLabel, strlen(kLabel), &key));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
// Null, non-zero-length handshake hash.
EXPECT_EQ(
SECFailure,
SSL_HkdfExpandLabel(SSL_LIBRARY_VERSION_TLS_1_2, TLS_AES_128_GCM_SHA256,
k1_.get(), nullptr, 2 , kLabel, strlen(kLabel), &key));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
// Null, non-zero-length label.
EXPECT_EQ(SECFailure,
SSL_HkdfExpandLabel(SSL_LIBRARY_VERSION_TLS_1_3,
TLS_AES_128_GCM_SHA256, k1_.get(), nullptr, 0 ,
nullptr, strlen(kLabel), &key));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
// Null, empty label.
EXPECT_EQ(SECFailure, SSL_HkdfExpandLabel(SSL_LIBRARY_VERSION_TLS_1_3,
TLS_AES_128_GCM_SHA256, k1_.get(),
nullptr, 0 , nullptr, 0 , &key));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
// Null key pointer..
EXPECT_EQ(SECFailure,
SSL_HkdfExpandLabel(SSL_LIBRARY_VERSION_TLS_1_3,
TLS_AES_128_GCM_SHA256, k1_.get(), nullptr, 0 ,
kLabel, strlen(kLabel), nullptr));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
EXPECT_EQ(nullptr, key);
}
static const SSLHashType kHashTypes[] = {ssl_hash_sha256, ssl_hash_sha384};
INSTANTIATE_TEST_SUITE_P(AllHashFuncs, TlsHkdfTest,
::testing::ValuesIn(kHashTypes));
} // namespace nss_test
Messung V0.5 in Prozent C=95 H=96 G=95
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet am 2026-06-06)
¤
*© Formatika GbR, Deutschland