Commit 01cb1c86 authored by Victor Vasiliev's avatar Victor Vasiliev Committed by Commit Bot

Migrate all of non-QUIC uses of crypto::HKDF to a new API

crypto::HKDF was originally written for QUIC and has QUIC-specific
assumptions in it, and hence it's moved into the QUIC codebase.

The new API is just a thin wrapper around BoringSSL's HKDF
implementation.  I intend to do the same to crypto::HKDF itself, but for
now it's parked in QUIC platform impl directory.

Change-Id: Ie60072dab4570bc840d9e6aaa5b1fef72fb387a2
Reviewed-on: https://chromium-review.googlesource.com/1122698
Commit-Queue: Victor Vasiliev <vasilvv@chromium.org>
Reviewed-by: default avatarRyan Sleevi <rsleevi@chromium.org>
Reviewed-by: default avatarJun Choi <hongjunchoi@chromium.org>
Reviewed-by: default avatarPeter Beverloo <peter@chromium.org>
Reviewed-by: default avatarTim Song <tengs@chromium.org>
Reviewed-by: default avatarDavid Benjamin <davidben@chromium.org>
Cr-Commit-Position: refs/heads/master@{#573403}
parent 5438c80c
......@@ -30,15 +30,10 @@ const char kResponderPurpose[] = "responder";
SessionKeys::SessionKeys(const std::string& master_symmetric_key) {
std::string salt(reinterpret_cast<const char*>(&kSalt[0]), sizeof(kSalt));
// We set the key_length to the length of the expected output and then take
// the result from the first key, which is the client write key.
crypto::HKDF initiator_encode(master_symmetric_key, salt, kInitiatorPurpose,
kKeySize, 0, 0);
initiator_encode_key_ = initiator_encode.client_write_key().as_string();
crypto::HKDF responder_encode(master_symmetric_key, salt, kResponderPurpose,
kKeySize, 0, 0);
responder_encode_key_ = responder_encode.client_write_key().as_string();
initiator_encode_key_ = crypto::HkdfSha256(master_symmetric_key, salt,
kInitiatorPurpose, kKeySize);
responder_encode_key_ = crypto::HkdfSha256(master_symmetric_key, salt,
kResponderPurpose, kKeySize);
}
SessionKeys::SessionKeys() {}
......
......@@ -25,12 +25,9 @@ bool GetHkdfSubkeySecret(size_t subkey_length,
if (!X25519(shared_secret, private_key, public_key))
return false;
crypto::HKDF hkdf(base::StringPiece(reinterpret_cast<char*>(shared_secret),
sizeof(shared_secret)),
"" /* salt */, hkdf_label, 0 /* key bytes */,
0 /* iv bytes */, subkey_length);
*secret = hkdf.subkey_secret().as_string();
base::StringPiece hkdf_input(reinterpret_cast<char*>(shared_secret),
sizeof(shared_secret));
*secret = crypto::HkdfSha256(hkdf_input, "", hkdf_label, subkey_length);
return true;
}
......
......@@ -59,12 +59,7 @@ class WebPushEncryptionDraft03
// This deliberately copies over the NUL terminus.
base::StringPiece info(kInfo, sizeof(kInfo));
crypto::HKDF hkdf(ecdh_shared_secret, auth_secret, info,
32, /* key_bytes_to_generate */
0, /* iv_bytes_to_generate */
0 /* subkey_secret_bytes_to_generate */);
return hkdf.client_write_key().as_string();
return crypto::HkdfSha256(ecdh_shared_secret, auth_secret, info, 32);
}
// Creates the info parameter for an HKDF value for the given
......@@ -202,12 +197,7 @@ class WebPushEncryptionDraft08
recipient_public_key.AppendToString(&info);
sender_public_key.AppendToString(&info);
crypto::HKDF hkdf(ecdh_shared_secret, auth_secret, info,
32, /* key_bytes_to_generate */
0, /* iv_bytes_to_generate */
0 /* subkey_secret_bytes_to_generate */);
return hkdf.client_write_key().as_string();
return crypto::HkdfSha256(ecdh_shared_secret, auth_secret, info, 32);
}
// The info string used for generating the content encryption key and the
......@@ -459,11 +449,9 @@ std::string GCMMessageCryptographer::DeriveContentEncryptionKey(
EncryptionScheme::EncodingType::CONTENT_ENCRYPTION_KEY,
recipient_public_key, sender_public_key);
crypto::HKDF hkdf(ecdh_shared_secret, salt, content_encryption_key_info,
kContentEncryptionKeySize, 0, /* iv_bytes_to_generate */
0 /* subkey_secret_bytes_to_generate */);
return hkdf.client_write_key().as_string();
return crypto::HkdfSha256(ecdh_shared_secret, salt,
content_encryption_key_info,
kContentEncryptionKeySize);
}
std::string GCMMessageCryptographer::DeriveNonce(
......@@ -475,16 +463,12 @@ std::string GCMMessageCryptographer::DeriveNonce(
EncryptionScheme::EncodingType::NONCE, recipient_public_key,
sender_public_key);
crypto::HKDF hkdf(ecdh_shared_secret, salt, nonce_info, kNonceSize,
0, /* iv_bytes_to_generate */
0 /* subkey_secret_bytes_to_generate */);
// https://tools.ietf.org/html/draft-ietf-httpbis-encryption-encoding-02
// defines that the result should be XOR'ed with the record's sequence number,
// however, Web Push encryption is limited to a single record per
// https://tools.ietf.org/html/draft-ietf-webpush-encryption-03.
return hkdf.client_write_key().as_string();
return crypto::HkdfSha256(ecdh_shared_secret, salt, nonce_info, kNonceSize);
}
} // namespace gcm
......@@ -133,7 +133,6 @@ test("crypto_unittests") {
"ec_private_key_unittest.cc",
"ec_signature_creator_unittest.cc",
"encryptor_unittest.cc",
"hkdf_unittest.cc",
"hmac_unittest.cc",
"nss_key_util_unittest.cc",
"nss_util_unittest.cc",
......
......@@ -11,125 +11,24 @@
#include "base/logging.h"
#include "crypto/hmac.h"
#include "third_party/boringssl/src/include/openssl/digest.h"
#include "third_party/boringssl/src/include/openssl/hkdf.h"
namespace crypto {
const size_t kSHA256HashLength = 32;
HKDF::HKDF(base::StringPiece secret,
base::StringPiece salt,
base::StringPiece info,
size_t key_bytes_to_generate,
size_t iv_bytes_to_generate,
size_t subkey_secret_bytes_to_generate)
: HKDF(secret,
salt,
info,
key_bytes_to_generate,
key_bytes_to_generate,
iv_bytes_to_generate,
iv_bytes_to_generate,
subkey_secret_bytes_to_generate) {}
HKDF::HKDF(base::StringPiece secret,
base::StringPiece salt,
base::StringPiece info,
size_t client_key_bytes_to_generate,
size_t server_key_bytes_to_generate,
size_t client_iv_bytes_to_generate,
size_t server_iv_bytes_to_generate,
size_t subkey_secret_bytes_to_generate) {
// https://tools.ietf.org/html/rfc5869#section-2.2
base::StringPiece actual_salt = salt;
char zeros[kSHA256HashLength];
if (actual_salt.empty()) {
// If salt is not given, HashLength zeros are used.
memset(zeros, 0, sizeof(zeros));
actual_salt.set(zeros, sizeof(zeros));
}
// Perform the Extract step to transform the input key and
// salt into the pseudorandom key (PRK) used for Expand.
HMAC prk_hmac(HMAC::SHA256);
bool result = prk_hmac.Init(actual_salt);
DCHECK(result);
// |prk| is a pseudorandom key (of kSHA256HashLength octets).
uint8_t prk[kSHA256HashLength];
DCHECK_EQ(sizeof(prk), prk_hmac.DigestLength());
result = prk_hmac.Sign(secret, prk, sizeof(prk));
DCHECK(result);
// https://tools.ietf.org/html/rfc5869#section-2.3
// Perform the Expand phase to turn the pseudorandom key
// and info into the output keying material.
const size_t material_length =
client_key_bytes_to_generate + client_iv_bytes_to_generate +
server_key_bytes_to_generate + server_iv_bytes_to_generate +
subkey_secret_bytes_to_generate;
const size_t n =
(material_length + kSHA256HashLength - 1) / kSHA256HashLength;
DCHECK_LT(n, 256u);
output_.resize(n * kSHA256HashLength);
base::StringPiece previous;
std::unique_ptr<char[]> buf(new char[kSHA256HashLength + info.size() + 1]);
uint8_t digest[kSHA256HashLength];
HMAC hmac(HMAC::SHA256);
result = hmac.Init(prk, sizeof(prk));
std::string HkdfSha256(base::StringPiece secret,
base::StringPiece salt,
base::StringPiece info,
size_t derived_key_size) {
std::string key;
key.resize(derived_key_size);
int result = ::HKDF(
reinterpret_cast<uint8_t*>(&key[0]), derived_key_size, EVP_sha256(),
reinterpret_cast<const uint8_t*>(secret.data()), secret.size(),
reinterpret_cast<const uint8_t*>(salt.data()), salt.size(),
reinterpret_cast<const uint8_t*>(info.data()), info.size());
DCHECK(result);
for (size_t i = 0; i < n; i++) {
memcpy(buf.get(), previous.data(), previous.size());
size_t j = previous.size();
memcpy(buf.get() + j, info.data(), info.size());
j += info.size();
buf[j++] = static_cast<char>(i + 1);
result = hmac.Sign(base::StringPiece(buf.get(), j), digest, sizeof(digest));
DCHECK(result);
memcpy(&output_[i*sizeof(digest)], digest, sizeof(digest));
previous = base::StringPiece(reinterpret_cast<char*>(digest),
sizeof(digest));
}
size_t j = 0;
// On Windows, when the size of output_ is zero, dereference of 0'th element
// results in a crash. C++11 solves this problem by adding a data() getter
// method to std::vector.
if (client_key_bytes_to_generate) {
client_write_key_ = base::StringPiece(reinterpret_cast<char*>(&output_[j]),
client_key_bytes_to_generate);
j += client_key_bytes_to_generate;
}
if (server_key_bytes_to_generate) {
server_write_key_ = base::StringPiece(reinterpret_cast<char*>(&output_[j]),
server_key_bytes_to_generate);
j += server_key_bytes_to_generate;
}
if (client_iv_bytes_to_generate) {
client_write_iv_ = base::StringPiece(reinterpret_cast<char*>(&output_[j]),
client_iv_bytes_to_generate);
j += client_iv_bytes_to_generate;
}
if (server_iv_bytes_to_generate) {
server_write_iv_ = base::StringPiece(reinterpret_cast<char*>(&output_[j]),
server_iv_bytes_to_generate);
j += server_iv_bytes_to_generate;
}
if (subkey_secret_bytes_to_generate) {
subkey_secret_ = base::StringPiece(reinterpret_cast<char*>(&output_[j]),
subkey_secret_bytes_to_generate);
}
return key;
}
HKDF::~HKDF() = default;
} // namespace crypto
......@@ -6,78 +6,19 @@
#define CRYPTO_HKDF_H_
#include <stddef.h>
#include <stdint.h>
#include <vector>
#include <string>
#include "base/strings/string_piece.h"
#include "crypto/crypto_export.h"
namespace crypto {
// HKDF implements the key derivation function specified in RFC 5869 (using
// SHA-256) and outputs key material, as needed by QUIC.
// See https://tools.ietf.org/html/rfc5869 for details.
class CRYPTO_EXPORT HKDF {
public:
// |secret|: the input shared secret (or, from RFC 5869, the IKM).
// |salt|: an (optional) public salt / non-secret random value. While
// optional, callers are strongly recommended to provide a salt. There is no
// added security value in making this larger than the SHA-256 block size of
// 64 bytes.
// |info|: an (optional) label to distinguish different uses of HKDF. It is
// optional context and application specific information (can be a zero-length
// string).
// |key_bytes_to_generate|: the number of bytes of key material to generate
// for both client and server.
// |iv_bytes_to_generate|: the number of bytes of IV to generate for both
// client and server.
// |subkey_secret_bytes_to_generate|: the number of bytes of subkey secret to
// generate, shared between client and server.
HKDF(base::StringPiece secret,
base::StringPiece salt,
base::StringPiece info,
size_t key_bytes_to_generate,
size_t iv_bytes_to_generate,
size_t subkey_secret_bytes_to_generate);
// An alternative constructor that allows the client and server key/IV
// lengths to be different.
HKDF(base::StringPiece secret,
base::StringPiece salt,
base::StringPiece info,
size_t client_key_bytes_to_generate,
size_t server_key_bytes_to_generate,
size_t client_iv_bytes_to_generate,
size_t server_iv_bytes_to_generate,
size_t subkey_secret_bytes_to_generate);
~HKDF();
base::StringPiece client_write_key() const {
return client_write_key_;
}
base::StringPiece client_write_iv() const {
return client_write_iv_;
}
base::StringPiece server_write_key() const {
return server_write_key_;
}
base::StringPiece server_write_iv() const {
return server_write_iv_;
}
base::StringPiece subkey_secret() const {
return subkey_secret_;
}
private:
std::vector<uint8_t> output_;
base::StringPiece client_write_key_;
base::StringPiece server_write_key_;
base::StringPiece client_write_iv_;
base::StringPiece server_write_iv_;
base::StringPiece subkey_secret_;
};
CRYPTO_EXPORT
std::string HkdfSha256(base::StringPiece secret,
base::StringPiece salt,
base::StringPiece info,
size_t derived_key_size);
} // namespace crypto
......
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "crypto/hkdf.h"
#include <stddef.h>
#include <stdint.h>
#include <string>
#include "base/macros.h"
#include "base/strings/string_number_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
using crypto::HKDF;
namespace test {
namespace {
struct HKDFTest {
const char* key_hex;
const char* salt_hex;
const char* info_hex;
const char* output_hex;
};
// These test cases are taken from
// https://tools.ietf.org/html/rfc5869#appendix-A.
static const HKDFTest kHKDFTests[] = {{
"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
"000102030405060708090a0b0c",
"f0f1f2f3f4f5f6f7f8f9",
"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5"
"b887185865",
}, {
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021222324"
"25262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243444546474849"
"4a4b4c4d4e4f",
"606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f8081828384"
"85868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9"
"aaabacadaeaf",
"b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4"
"d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9"
"fafbfcfdfeff",
"b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99ca"
"c7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c"
"01d5c1f3434f1d87",
}, {
"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
"",
"",
"8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395fa"
"a4b61a96c8",
},
};
TEST(HKDFTest, HKDF) {
for (size_t i = 0; i < arraysize(kHKDFTests); i++) {
const HKDFTest& test(kHKDFTests[i]);
SCOPED_TRACE(i);
std::vector<uint8_t> data;
ASSERT_TRUE(base::HexStringToBytes(test.key_hex, &data));
const std::string key(reinterpret_cast<char*>(&data[0]), data.size());
data.clear();
// |salt_hex| is optional and may be empty.
std::string salt(test.salt_hex);
if (!salt.empty()) {
ASSERT_TRUE(base::HexStringToBytes(salt, &data));
salt.assign(reinterpret_cast<char*>(&data[0]), data.size());
}
data.clear();
// |info_hex| is optional and may be empty.
std::string info(test.info_hex);
if (!info.empty()) {
ASSERT_TRUE(base::HexStringToBytes(info, &data));
info.assign(reinterpret_cast<char*>(&data[0]), data.size());
}
data.clear();
ASSERT_TRUE(base::HexStringToBytes(test.output_hex, &data));
const std::string expected(reinterpret_cast<char*>(&data[0]), data.size());
// We set the key_length to the length of the expected output and then take
// the result from the first key, which is the client write key.
HKDF hkdf(key, salt, info, expected.size(), 0, 0);
ASSERT_EQ(expected.size(), hkdf.client_write_key().size());
EXPECT_EQ(0, memcmp(expected.data(), hkdf.client_write_key().data(),
expected.size()));
}
}
} // namespace
} // namespace test
......@@ -37,8 +37,7 @@ constexpr size_t kCableHandshakeMacMessageSize = 16;
std::string GenerateKey(base::StringPiece secret,
base::StringPiece salt,
base::StringPiece info) {
crypto::HKDF key_generator(secret, salt, info, 32, 0, 0);
return std::string(key_generator.client_write_key());
return crypto::HkdfSha256(secret, salt, info, 32);
}
base::Optional<std::array<uint8_t, kClientHelloMessageSize>>
......
......@@ -120,14 +120,12 @@ std::string GetExpectedEncryptionKey(
fido_parsing_utils::Materialize(kTestNonce);
fido_parsing_utils::Append(&nonce_message, client_random_nonce);
fido_parsing_utils::Append(&nonce_message, kAuthenticatorSessionRandom);
crypto::HKDF key_generator(
return crypto::HkdfSha256(
fido_parsing_utils::ConvertToStringPiece(kTestSessionPreKey),
fido_parsing_utils::ConvertToStringPiece(
fido_parsing_utils::CreateSHA256Hash(
fido_parsing_utils::ConvertToStringPiece(nonce_message))),
kCableDeviceEncryptionKeyInfo, 32, 0, 0);
return std::string(key_generator.client_write_key().begin(),
key_generator.client_write_key().end());
kCableDeviceEncryptionKeyInfo, 32);
}
// Given a hello message and handshake key from the authenticator, construct
......@@ -177,12 +175,10 @@ std::vector<uint8_t> ConstructSerializedOutgoingFragment(
class FakeCableAuthenticator {
public:
FakeCableAuthenticator() {
crypto::HKDF key_generator(
handshake_key_ = crypto::HkdfSha256(
fido_parsing_utils::ConvertToStringPiece(kTestSessionPreKey),
fido_parsing_utils::ConvertToStringPiece(kTestNonce),
kCableHandshakeKeyInfo, 32, 0, 0);
handshake_key_ = std::string(key_generator.client_write_key().begin(),
key_generator.client_write_key().end());
kCableHandshakeKeyInfo, 32);
}
// Receives handshake message from the client, check its validity and if the
......
......@@ -1528,6 +1528,7 @@ component("net") {
"third_party/quic/platform/impl/quic_flag_utils_impl.h",
"third_party/quic/platform/impl/quic_flags_impl.cc",
"third_party/quic/platform/impl/quic_flags_impl.h",
"third_party/quic/platform/impl/quic_hkdf_impl.cc",
"third_party/quic/platform/impl/quic_hkdf_impl.h",
"third_party/quic/platform/impl/quic_hostname_utils_impl.cc",
"third_party/quic/platform/impl/quic_hostname_utils_impl.h",
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/third_party/quic/platform/impl/quic_hkdf_impl.h"
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include "base/logging.h"
#include "crypto/hmac.h"
using crypto::HMAC;
namespace quic {
const size_t kSHA256HashLength = 32;
QuicHKDFImpl::QuicHKDFImpl(base::StringPiece secret,
base::StringPiece salt,
base::StringPiece info,
size_t key_bytes_to_generate,
size_t iv_bytes_to_generate,
size_t subkey_secret_bytes_to_generate)
: QuicHKDFImpl(secret,
salt,
info,
key_bytes_to_generate,
key_bytes_to_generate,
iv_bytes_to_generate,
iv_bytes_to_generate,
subkey_secret_bytes_to_generate) {}
QuicHKDFImpl::QuicHKDFImpl(base::StringPiece secret,
base::StringPiece salt,
base::StringPiece info,
size_t client_key_bytes_to_generate,
size_t server_key_bytes_to_generate,
size_t client_iv_bytes_to_generate,
size_t server_iv_bytes_to_generate,
size_t subkey_secret_bytes_to_generate) {
// https://tools.ietf.org/html/rfc5869#section-2.2
base::StringPiece actual_salt = salt;
char zeros[kSHA256HashLength];
if (actual_salt.empty()) {
// If salt is not given, HashLength zeros are used.
memset(zeros, 0, sizeof(zeros));
actual_salt.set(zeros, sizeof(zeros));
}
// Perform the Extract step to transform the input key and
// salt into the pseudorandom key (PRK) used for Expand.
HMAC prk_hmac(HMAC::SHA256);
bool result = prk_hmac.Init(actual_salt);
DCHECK(result);
// |prk| is a pseudorandom key (of kSHA256HashLength octets).
uint8_t prk[kSHA256HashLength];
DCHECK_EQ(sizeof(prk), prk_hmac.DigestLength());
result = prk_hmac.Sign(secret, prk, sizeof(prk));
DCHECK(result);
// https://tools.ietf.org/html/rfc5869#section-2.3
// Perform the Expand phase to turn the pseudorandom key
// and info into the output keying material.
const size_t material_length =
client_key_bytes_to_generate + client_iv_bytes_to_generate +
server_key_bytes_to_generate + server_iv_bytes_to_generate +
subkey_secret_bytes_to_generate;
const size_t n =
(material_length + kSHA256HashLength - 1) / kSHA256HashLength;
DCHECK_LT(n, 256u);
output_.resize(n * kSHA256HashLength);
base::StringPiece previous;
std::unique_ptr<char[]> buf(new char[kSHA256HashLength + info.size() + 1]);
uint8_t digest[kSHA256HashLength];
HMAC hmac(HMAC::SHA256);
result = hmac.Init(prk, sizeof(prk));
DCHECK(result);
for (size_t i = 0; i < n; i++) {
memcpy(buf.get(), previous.data(), previous.size());
size_t j = previous.size();
memcpy(buf.get() + j, info.data(), info.size());
j += info.size();
buf[j++] = static_cast<char>(i + 1);
result = hmac.Sign(base::StringPiece(buf.get(), j), digest, sizeof(digest));
DCHECK(result);
memcpy(&output_[i * sizeof(digest)], digest, sizeof(digest));
previous =
base::StringPiece(reinterpret_cast<char*>(digest), sizeof(digest));
}
size_t j = 0;
// On Windows, when the size of output_ is zero, dereference of 0'th element
// results in a crash. C++11 solves this problem by adding a data() getter
// method to std::vector.
if (client_key_bytes_to_generate) {
client_write_key_ = base::StringPiece(reinterpret_cast<char*>(&output_[j]),
client_key_bytes_to_generate);
j += client_key_bytes_to_generate;
}
if (server_key_bytes_to_generate) {
server_write_key_ = base::StringPiece(reinterpret_cast<char*>(&output_[j]),
server_key_bytes_to_generate);
j += server_key_bytes_to_generate;
}
if (client_iv_bytes_to_generate) {
client_write_iv_ = base::StringPiece(reinterpret_cast<char*>(&output_[j]),
client_iv_bytes_to_generate);
j += client_iv_bytes_to_generate;
}
if (server_iv_bytes_to_generate) {
server_write_iv_ = base::StringPiece(reinterpret_cast<char*>(&output_[j]),
server_iv_bytes_to_generate);
j += server_iv_bytes_to_generate;
}
if (subkey_secret_bytes_to_generate) {
subkey_secret_ = base::StringPiece(reinterpret_cast<char*>(&output_[j]),
subkey_secret_bytes_to_generate);
}
}
QuicHKDFImpl::~QuicHKDFImpl() = default;
} // namespace quic
......@@ -5,11 +5,64 @@
#ifndef NET_THIRD_PARTY_QUIC_PLATFORM_IMPL_QUIC_HKDF_IMPL_H_
#define NET_THIRD_PARTY_QUIC_PLATFORM_IMPL_QUIC_HKDF_IMPL_H_
#include "crypto/hkdf.h"
#include "base/strings/string_piece.h"
#include "net/base/net_export.h"
namespace quic {
using QuicHKDFImpl = crypto::HKDF;
// HKDF implements the key derivation function specified in RFC 5869 (using
// SHA-256) and outputs key material, as needed by QUIC.
// See https://tools.ietf.org/html/rfc5869 for details.
class NET_EXPORT QuicHKDFImpl {
public:
// |secret|: the input shared secret (or, from RFC 5869, the IKM).
// |salt|: an (optional) public salt / non-secret random value. While
// optional, callers are strongly recommended to provide a salt. There is no
// added security value in making this larger than the SHA-256 block size of
// 64 bytes.
// |info|: an (optional) label to distinguish different uses of HKDF. It is
// optional context and application specific information (can be a zero-length
// string).
// |key_bytes_to_generate|: the number of bytes of key material to generate
// for both client and server.
// |iv_bytes_to_generate|: the number of bytes of IV to generate for both
// client and server.
// |subkey_secret_bytes_to_generate|: the number of bytes of subkey secret to
// generate, shared between client and server.
QuicHKDFImpl(base::StringPiece secret,
base::StringPiece salt,
base::StringPiece info,
size_t key_bytes_to_generate,
size_t iv_bytes_to_generate,
size_t subkey_secret_bytes_to_generate);
// An alternative constructor that allows the client and server key/IV
// lengths to be different.
QuicHKDFImpl(base::StringPiece secret,
base::StringPiece salt,
base::StringPiece info,
size_t client_key_bytes_to_generate,
size_t server_key_bytes_to_generate,
size_t client_iv_bytes_to_generate,
size_t server_iv_bytes_to_generate,
size_t subkey_secret_bytes_to_generate);
~QuicHKDFImpl();
base::StringPiece client_write_key() const { return client_write_key_; }
base::StringPiece client_write_iv() const { return client_write_iv_; }
base::StringPiece server_write_key() const { return server_write_key_; }
base::StringPiece server_write_iv() const { return server_write_iv_; }
base::StringPiece subkey_secret() const { return subkey_secret_; }
private:
std::vector<uint8_t> output_;
base::StringPiece client_write_key_;
base::StringPiece server_write_key_;
base::StringPiece client_write_iv_;
base::StringPiece server_write_iv_;
base::StringPiece subkey_secret_;
};
} // namespace quic
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment