-
Notifications
You must be signed in to change notification settings - Fork 161
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Summary: Adds grease ECH extension preparation. Reviewed By: mingtaoy Differential Revision: D65239683 fbshipit-source-id: 8485d318daa65beae0f451f172d0bd7b2b48ac9a
- Loading branch information
1 parent
ea1e6dd
commit 812149c
Showing
7 changed files
with
296 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
/* | ||
* Copyright (c) Meta Platforms, Inc. and affiliates. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
#include <random> | ||
|
||
#include <fizz/protocol/ech/GreaseECH.h> | ||
|
||
#include <fizz/crypto/hpke/Utils.h> | ||
|
||
namespace fizz { | ||
namespace ech { | ||
namespace { | ||
|
||
/** | ||
* A random number generator adaptor based on the Factory. | ||
* Current usage is limited to type size_t. | ||
*/ | ||
class RandomNumberGenerator { | ||
public: | ||
typedef size_t result_type; | ||
|
||
static constexpr size_t min() { | ||
return 0; | ||
} | ||
|
||
static constexpr size_t max() { | ||
return std::numeric_limits<size_t>::max(); | ||
} | ||
|
||
explicit RandomNumberGenerator(const Factory& factory) : factory_{factory} {} | ||
|
||
size_t operator()() const { | ||
size_t number = 0; | ||
factory_.makeRandomBytes( | ||
reinterpret_cast<unsigned char*>(&number), sizeof(number)); | ||
return number; | ||
} | ||
|
||
private: | ||
const Factory& factory_; | ||
}; | ||
|
||
class RandomSelector { | ||
public: | ||
explicit RandomSelector(RandomNumberGenerator&& generator) | ||
: generator_{std::move(generator)} {} | ||
|
||
size_t genNumber(size_t min, size_t max) const { | ||
std::uniform_int_distribution<size_t> distribution(min, max); | ||
return distribution(generator_); | ||
} | ||
|
||
template <typename T> | ||
T select(const std::vector<T>& elems) const { | ||
return elems[genNumber(0, elems.size() - 1)]; | ||
} | ||
|
||
private: | ||
const RandomNumberGenerator generator_; | ||
}; | ||
} // namespace | ||
|
||
OuterECHClientHello generateGreaseECH( | ||
const GreaseECHSetting& setting, | ||
const Factory& factory, | ||
size_t encodedChloSize) { | ||
RandomSelector selector{RandomNumberGenerator{factory}}; | ||
OuterECHClientHello echExtension; | ||
echExtension.cipher_suite = HpkeSymmetricCipherSuite{ | ||
selector.select(setting.kdfs), selector.select(setting.aeads)}; | ||
echExtension.config_id = | ||
selector.genNumber(setting.minConfigId, setting.maxConfigId); | ||
echExtension.enc = factory.makeRandomIOBuf(selector.select(setting.keySizes)); | ||
size_t payloadSize = | ||
selector.genNumber(setting.minPayloadSize, setting.maxPayloadSize); | ||
if (setting.payloadStrategy == PayloadGenerationStrategy::Computed) { | ||
payloadSize += encodedChloSize + | ||
hpke::getCipherOverhead(echExtension.cipher_suite.aead_id); | ||
} | ||
echExtension.payload = factory.makeRandomIOBuf(payloadSize); | ||
return echExtension; | ||
} | ||
} // namespace ech | ||
} // namespace fizz |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/* | ||
* Copyright (c) Meta Platforms, Inc. and affiliates. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <fizz/protocol/Factory.h> | ||
#include <fizz/protocol/ech/ECHExtensions.h> | ||
#include <fizz/protocol/ech/GreaseECHSetting.h> | ||
|
||
namespace fizz { | ||
namespace ech { | ||
OuterECHClientHello generateGreaseECH( | ||
const GreaseECHSetting& setting, | ||
const Factory& factory, | ||
size_t encodedChloSize); | ||
} // namespace ech | ||
} // namespace fizz |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
/* | ||
* Copyright (c) Meta Platforms, Inc. and affiliates. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <fizz/crypto/hpke/Hpke.h> | ||
|
||
namespace fizz { | ||
namespace ech { | ||
|
||
enum class PayloadGenerationStrategy : uint8_t { | ||
/** | ||
* Generates a payload with a size P where P is in the range | ||
* [minPayloadSize, maxPayloadSize]. | ||
*/ | ||
UniformRandom = 0, | ||
|
||
/** | ||
* Generates a payload with size L + C + P bytes where L is the size of the | ||
* encoded inner client hello, C is the ciphertext expansion of the selected | ||
* AEAD schema, and P is the expected padding within the range | ||
* [minPayloadSize, maxPayloadSize]. | ||
*/ | ||
Computed | ||
}; | ||
|
||
struct GreaseECHSetting { | ||
uint8_t minConfigId{0}; | ||
uint8_t maxConfigId{std::numeric_limits<uint8_t>::max()}; | ||
PayloadGenerationStrategy payloadStrategy{ | ||
PayloadGenerationStrategy::UniformRandom}; | ||
size_t minPayloadSize{0}; | ||
size_t maxPayloadSize{0}; | ||
std::vector<uint16_t> keySizes{32, 48, 64}; | ||
std::vector<hpke::KDFId> kdfs{ | ||
hpke::KDFId::Sha256, | ||
hpke::KDFId::Sha384, | ||
hpke::KDFId::Sha512}; | ||
std::vector<hpke::AeadId> aeads{ | ||
hpke::AeadId::TLS_AES_128_GCM_SHA256, | ||
hpke::AeadId::TLS_AES_256_GCM_SHA384, | ||
hpke::AeadId::TLS_CHACHA20_POLY1305_SHA256}; | ||
}; | ||
} // namespace ech | ||
} // namespace fizz |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
/* | ||
* Copyright (c) Meta Platforms, Inc. and affiliates. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
#include <gtest/gtest.h> | ||
|
||
#include <fizz/protocol/ech/GreaseECH.h> | ||
|
||
#include <fizz/crypto/hpke/Utils.h> | ||
#include <fizz/protocol/test/Mocks.h> | ||
#include <fizz/protocol/test/TestUtil.h> | ||
|
||
using namespace fizz::test; | ||
|
||
namespace fizz { | ||
namespace ech { | ||
namespace test { | ||
|
||
TEST(GreaseECHTest, TestGenerateRandomGreaseECH) { | ||
MockFactory factory; | ||
factory.setDefaults(); | ||
|
||
auto chlo = TestMessages::clientHelloPsk(); | ||
auto sni = getExtension<ServerNameList>(chlo.extensions); | ||
|
||
GreaseECHSetting setting{}; | ||
setting.maxPayloadSize = 100; | ||
auto greaseEch = generateGreaseECH(setting, factory, 0); | ||
|
||
std::array<hpke::KDFId, 3> kdfs{ | ||
hpke::KDFId::Sha256, hpke::KDFId::Sha384, hpke::KDFId::Sha512}; | ||
std::array<hpke::AeadId, 3> aeads{ | ||
hpke::AeadId::TLS_AES_128_GCM_SHA256, | ||
hpke::AeadId::TLS_AES_256_GCM_SHA384, | ||
hpke::AeadId::TLS_CHACHA20_POLY1305_SHA256}; | ||
|
||
EXPECT_NE( | ||
kdfs.end(), | ||
std::find(kdfs.begin(), kdfs.end(), greaseEch.cipher_suite.kdf_id)); | ||
EXPECT_NE( | ||
aeads.end(), | ||
std::find(aeads.begin(), aeads.end(), greaseEch.cipher_suite.aead_id)); | ||
|
||
std::array<size_t, 3> keyLengths{32, 48, 64}; | ||
EXPECT_NE( | ||
keyLengths.end(), | ||
std::find( | ||
keyLengths.begin(), | ||
keyLengths.end(), | ||
greaseEch.enc->computeChainDataLength())); | ||
|
||
EXPECT_LE(greaseEch.payload->computeChainDataLength(), 100); | ||
} | ||
|
||
TEST(GreaseECHTest, TestGenerateComputedGreaseECH) { | ||
MockFactory factory; | ||
factory.setDefaults(); | ||
|
||
auto chlo = TestMessages::clientHelloPsk(); | ||
auto sni = getExtension<ServerNameList>(chlo.extensions); | ||
auto encodedChlo = encode(chlo); | ||
|
||
size_t encodedChloSize = encodedChlo->computeChainDataLength(); | ||
GreaseECHSetting setting{ | ||
/* minConfigId = */ 0, | ||
/* maxConfigId = */ 0, | ||
PayloadGenerationStrategy::Computed, | ||
/* minPayloadSize = */ 100, | ||
/* maxPayloadSize = */ 100, | ||
/* keySizes = */ {32}, | ||
/* kdfs = */ {hpke::KDFId::Sha256}, | ||
/* aeads = */ {hpke::AeadId::TLS_AES_128_GCM_SHA256}}; | ||
auto greaseEch = generateGreaseECH(setting, factory, encodedChloSize); | ||
|
||
EXPECT_EQ(hpke::KDFId::Sha256, greaseEch.cipher_suite.kdf_id); | ||
EXPECT_EQ( | ||
hpke::AeadId::TLS_AES_128_GCM_SHA256, greaseEch.cipher_suite.aead_id); | ||
EXPECT_EQ(32, greaseEch.enc->computeChainDataLength()); | ||
|
||
size_t expectedPayloadSize = encodedChloSize + | ||
hpke::getCipherOverhead(greaseEch.cipher_suite.aead_id) + 100; | ||
EXPECT_EQ(expectedPayloadSize, greaseEch.payload->computeChainDataLength()); | ||
} | ||
} // namespace test | ||
} // namespace ech | ||
} // namespace fizz |