Skip to content

Commit

Permalink
Merge branch 'tls13/hybrid_key_exchange' into tls13/integration3
Browse files Browse the repository at this point in the history
  • Loading branch information
reneme committed Jun 7, 2022
2 parents 4081b7b + 7b74a14 commit 17c2e54
Show file tree
Hide file tree
Showing 11 changed files with 693 additions and 8 deletions.
3 changes: 2 additions & 1 deletion src/lib/tls/msg_client_hello.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,7 @@ Client_Hello_13::Client_Hello_13(const Policy& policy,

void Client_Hello_13::retry(const Hello_Retry_Request& hrr,
const Transcript_Hash_State& transcript_hash_state,
const Policy& policy,
Callbacks& cb,
RandomNumberGenerator& rng)
{
Expand All @@ -593,7 +594,7 @@ void Client_Hello_13::retry(const Hello_Retry_Request& hrr,
const auto& supported_groups = m_extensions.get<Supported_Groups>()->groups();

if(hrr.extensions().has<Key_Share>())
m_extensions.get<Key_Share>()->retry_offer(*hrr_ks, supported_groups, cb, rng);
m_extensions.get<Key_Share>()->retry_offer(*hrr_ks, supported_groups, policy, cb, rng);

// RFC 8446 4.2.2
// When sending the new ClientHello, the client MUST copy
Expand Down
2 changes: 1 addition & 1 deletion src/lib/tls/tls13/tls_client_impl_13.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ void Client_Impl_13::handle(const Hello_Retry_Request& hrr)
m_transcript_hash = Transcript_Hash_State::recreate_after_hello_retry_request(cipher.value().prf_algo(),
m_transcript_hash);

ch.retry(hrr, m_transcript_hash, callbacks(), rng());
ch.retry(hrr, m_transcript_hash, policy(), callbacks(), rng());

callbacks().tls_examine_extensions(hrr.extensions(), SERVER);

Expand Down
97 changes: 92 additions & 5 deletions src/lib/tls/tls13/tls_extensions_key_share.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@
#include <botan/curve25519.h>
#endif

#if defined(BOTAN_HAS_TLS_13_PQC)
#include <botan/internal/composite_public_key.h>

#if defined(BOTAN_HAS_KYBER) || defined(BOTAN_HAS_KYBER_90S)
#include <botan/kyber.h>
#endif
#endif

#include <botan/dh.h>
#include <botan/ecdh.h>

Expand Down Expand Up @@ -53,6 +61,57 @@ namespace {
group == Group_Params::FFDHE_8192;
}

#if defined(BOTAN_HAS_TLS_13_PQC)
#if defined(BOTAN_HAS_KYBER) || defined(BOTAN_HAS_KYBER_90S)

[[maybe_unused]] constexpr bool is_kyber(const Group_Params group)
{
return
group == Group_Params::KYBER_R3_512 ||
group == Group_Params::KYBER_R3_768 ||
group == Group_Params::KYBER_R3_1024 ||
group == Group_Params::KYBER_90s_R3_512 ||
group == Group_Params::KYBER_90s_R3_768 ||
group == Group_Params::KYBER_90s_R3_1024;
}

[[maybe_unused]] constexpr KyberMode::Mode get_kyber_mode(const Group_Params group)
{
switch(group)
{
case Group_Params::KYBER_R3_512:
return KyberMode::Kyber512;
case Group_Params::KYBER_R3_768:
return KyberMode::Kyber768;
case Group_Params::KYBER_R3_1024:
return KyberMode::Kyber1024;
case Group_Params::KYBER_90s_R3_512:
return KyberMode::Kyber512_90s;
case Group_Params::KYBER_90s_R3_768:
return KyberMode::Kyber768_90s;
case Group_Params::KYBER_90s_R3_1024:
return KyberMode::Kyber1024_90s;
default:
BOTAN_ASSERT(false, "cannot determine kyber mode from non-kyber group ID");
}
}

#endif

[[maybe_unused]] constexpr bool is_composite(const Group_Params group)
{
return
group == Group_Params::X25519_KYBER_R3_512 ||
group == Group_Params::SECP256R1_KYBER_R3_512 ||
group == Group_Params::SECP384R1_KYBER_R3_768 ||
group == Group_Params::SECP521R1_KYBER_R3_1024 ||
group == Group_Params::SECP256R1_KYBER_90s_R3_512 ||
group == Group_Params::SECP384R1_KYBER_90s_R3_768 ||
group == Group_Params::SECP521R1_KYBER_90s_R3_1024;
}

#endif

class Key_Share_Entry
{
public:
Expand All @@ -74,7 +133,7 @@ class Key_Share_Entry
}
}

Key_Share_Entry(const TLS::Group_Params group, Callbacks& cb, RandomNumberGenerator& rng)
Key_Share_Entry(const TLS::Group_Params group, const Policy& policy, Callbacks& cb, RandomNumberGenerator& rng)
: m_group(group)
{
if(is_ecdh(group))
Expand Down Expand Up @@ -112,11 +171,30 @@ class Key_Share_Entry
m_key_exchange = skey->public_value();
m_private_key = std::move(skey);
}
#endif
#if defined(BOTAN_HAS_TLS_13_PQC)
#if defined(BOTAN_HAS_KYBER)
else if(is_kyber(group))
{
auto skey = std::make_unique<Kyber_PrivateKey>(rng, get_kyber_mode(group));
skey->set_binary_encoding(KyberKeyEncoding::Raw);
m_key_exchange = skey->public_key_bits();
m_private_key = std::move(skey);
}
#endif
else if(is_composite(group))
{
auto skey = std::make_unique<Composite_PrivateKey>(rng, group, policy);
m_key_exchange = skey->public_key_bits();
m_private_key = std::move(skey);
}
#endif
else
{
throw Decoding_Error("cannot create a key offering without a group definition");
}

BOTAN_UNUSED(policy);
}

bool empty() const { return (m_group == Group_Params::NONE) && m_key_exchange.empty(); }
Expand Down Expand Up @@ -148,6 +226,14 @@ class Key_Share_Entry
BOTAN_ASSERT_NOMSG(m_private_key != nullptr);
BOTAN_ASSERT_NOMSG(m_group == received.m_group);

#if defined(BOTAN_HAS_KYBER) && defined(BOTAN_HAS_TLS_13_PQC)
if(is_kyber(m_group) || is_composite(m_group))
{
return PK_KEM_Decryptor(*m_private_key, rng, "Raw")
.decrypt(received.m_key_exchange, 0, std::vector<uint8_t>());
}
#endif

PK_Key_Agreement ka(*m_private_key, rng, "Raw");

if(is_ecdh(m_group))
Expand Down Expand Up @@ -302,7 +388,7 @@ class Key_Share_ClientHello
{
continue;
}
m_client_shares.emplace_back(group, cb, rng);
m_client_shares.emplace_back(group, policy, cb, rng);
}
}
~Key_Share_ClientHello() = default;
Expand All @@ -313,7 +399,7 @@ class Key_Share_ClientHello
Key_Share_ClientHello(Key_Share_ClientHello&&) = default;
Key_Share_ClientHello& operator=(Key_Share_ClientHello&&) = default;

void retry_offer(const TLS::Group_Params to_offer, Callbacks& cb, RandomNumberGenerator& rng)
void retry_offer(const TLS::Group_Params to_offer, const Policy& policy, Callbacks& cb, RandomNumberGenerator& rng)
{
// RFC 8446 4.2.8
// The selected_group field [MUST] not correspond to a group which was provided
Expand All @@ -326,7 +412,7 @@ class Key_Share_ClientHello
}

m_client_shares.clear();
m_client_shares.emplace_back(to_offer, cb, rng);
m_client_shares.emplace_back(to_offer, policy, cb, rng);
}

std::vector<uint8_t> serialize() const
Expand Down Expand Up @@ -510,6 +596,7 @@ secure_vector<uint8_t> Key_Share::exchange(const Key_Share& peer_keyshare,

void Key_Share::retry_offer(const Key_Share& retry_request_keyshare,
const std::vector<Named_Group>& supported_groups,
const Policy& policy,
Callbacks& cb,
RandomNumberGenerator& rng)
{
Expand All @@ -524,7 +611,7 @@ void Key_Share::retry_offer(const Key_Share& retry_request_keyshare,
if(!value_exists(supported_groups, selected))
{ throw TLS_Exception(Alert::ILLEGAL_PARAMETER, "group was not advertised as supported"); }

return ch.retry_offer(selected, cb, rng);
return ch.retry_offer(selected, policy, cb, rng);
},
[](const auto&, const auto&)
{
Expand Down
Loading

0 comments on commit 17c2e54

Please sign in to comment.