Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/lib/tls/tls_policy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,17 @@ void print_vec(std::ostream& o, const char* key, const std::vector<Certificate_T
o << '\n';
}

void print_vec(std::ostream& o, const char* key, const std::vector<Signature_Scheme>& schemes) {
o << key << " = ";
for(size_t i = 0; i != schemes.size(); ++i) {
o << schemes[i].to_string();
if(i != schemes.size() - 1) {
o << ' ';
}
}
o << '\n';
}

void print_bool(std::ostream& o, const char* key, bool b) {
o << key << " = " << (b ? "true" : "false") << '\n';
}
Expand All @@ -706,6 +717,8 @@ void Policy::print(std::ostream& o) const {
print_vec(o, "macs", allowed_macs());
print_vec(o, "signature_hashes", allowed_signature_hashes());
print_vec(o, "signature_methods", allowed_signature_methods());
print_vec(o, "signature_schemes", allowed_signature_schemes());
print_vec(o, "acceptable_signature_schemes", acceptable_signature_schemes());
print_vec(o, "key_exchange_methods", allowed_key_exchange_methods());
print_vec(o, "key_exchange_groups", key_exchange_groups());
const auto groups_to_offer = key_exchange_groups_to_offer();
Expand Down
11 changes: 11 additions & 0 deletions src/lib/tls/tls_policy.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ class BOTAN_PUBLIC_API(2, 0) Policy /* NOLINT(*-special-member-functions) */ {
*/
virtual std::vector<std::string> allowed_signature_methods() const;

/**
* Returns a list of signature schemes we are willing to use, in order of
* preference. By default, this list contains all supported schemes that
* comply with the outputs of allowed_signature_methods() and
* allowed_signature_hashes().
*/
virtual std::vector<Signature_Scheme> allowed_signature_schemes() const;

/**
Expand Down Expand Up @@ -808,6 +814,10 @@ class BOTAN_PUBLIC_API(2, 0) Text_Policy : public Policy {

std::vector<std::string> allowed_signature_methods() const override;

std::vector<Signature_Scheme> allowed_signature_schemes() const override;

std::vector<Signature_Scheme> acceptable_signature_schemes() const override;

std::vector<Group_Params> key_exchange_groups() const override;

std::vector<Group_Params> key_exchange_groups_to_offer() const override;
Expand Down Expand Up @@ -889,6 +899,7 @@ class BOTAN_PUBLIC_API(2, 0) Text_Policy : public Policy {

std::vector<Group_Params> read_group_list(std::string_view group_str) const;
std::vector<Certificate_Type> read_cert_type_list(const std::string& cert_type_str) const;
std::vector<Signature_Scheme> read_sig_scheme_list(std::string_view sig_scheme_str) const;

size_t get_len(const std::string& key, size_t def) const;

Expand Down
54 changes: 54 additions & 0 deletions src/lib/tls/tls_signature_scheme.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@
#include <botan/assert.h>
#include <botan/tls_signature_scheme.h>

#include <botan/hex.h>
#include <botan/pk_keys.h>
#include <botan/pss_params.h>
#include <botan/tls_version.h>
#include <botan/internal/fmt.h>
#include <botan/internal/loadstor.h>

namespace Botan::TLS {

Expand Down Expand Up @@ -44,6 +47,57 @@ const std::vector<Signature_Scheme>& Signature_Scheme::all_available_schemes() {
return all_schemes;
}

Signature_Scheme Signature_Scheme::from_string(std::string_view str) {
if(str == "RSA_PKCS1_SHA1") {
return RSA_PKCS1_SHA1;
}
if(str == "RSA_PKCS1_SHA256") {
return RSA_PKCS1_SHA256;
}
if(str == "RSA_PKCS1_SHA384") {
return RSA_PKCS1_SHA384;
}
if(str == "RSA_PKCS1_SHA512") {
return RSA_PKCS1_SHA512;
}

if(str == "ECDSA_SHA1") {
return ECDSA_SHA1;
}
if(str == "ECDSA_SHA256") {
return ECDSA_SHA256;
}
if(str == "ECDSA_SHA384") {
return ECDSA_SHA384;
}
if(str == "ECDSA_SHA512") {
return ECDSA_SHA512;
}

if(str == "RSA_PSS_SHA256") {
return RSA_PSS_SHA256;
}
if(str == "RSA_PSS_SHA384") {
return RSA_PSS_SHA384;
}
if(str == "RSA_PSS_SHA512") {
return RSA_PSS_SHA512;
}

// Parse signature schemes passed as hexadecimal code points (e.g. "0x081A")
if(str.size() == 6 && str.starts_with("0x")) {
try {
std::array<uint8_t, 2> wire_code{};
Botan::hex_decode(wire_code, str.substr(2), false /* no white space */);
return Signature_Scheme(load_be(wire_code));
} catch(const Invalid_Argument&) {
// pass, will throw below
}
}

throw Invalid_Argument(fmt("Unknown TLS signature scheme '{}'", str));
}

Signature_Scheme::Signature_Scheme() : m_code(NONE) {}

Signature_Scheme::Signature_Scheme(uint16_t wire_code) : Signature_Scheme(Signature_Scheme::Code(wire_code)) {}
Expand Down
5 changes: 5 additions & 0 deletions src/lib/tls/tls_signature_scheme.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ class BOTAN_PUBLIC_API(3, 0) Signature_Scheme final {
*/
static const std::vector<Signature_Scheme>& all_available_schemes();

/**
* @return the signature scheme corresponding to the given string
*/
static Signature_Scheme from_string(std::string_view str);

/**
* Construct an uninitialized / invalid scheme
*/
Expand Down
19 changes: 19 additions & 0 deletions src/lib/tls/tls_text_policy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include <botan/assert.h>
#include <botan/exceptn.h>
#include <botan/tls_signature_scheme.h>
#include <botan/internal/fmt.h>
#include <botan/internal/parsing.h>
#include <optional>
Expand Down Expand Up @@ -41,6 +42,16 @@ std::vector<std::string> Text_Policy::allowed_signature_methods() const {
return get_list("signature_methods", Policy::allowed_signature_methods());
}

std::vector<Signature_Scheme> Text_Policy::allowed_signature_schemes() const {
const auto sig_schemes_str = get_str("signature_schemes", "");
return (sig_schemes_str.empty()) ? Policy::allowed_signature_schemes() : read_sig_scheme_list(sig_schemes_str);
}

std::vector<Signature_Scheme> Text_Policy::acceptable_signature_schemes() const {
const auto sig_schemes_str = get_str("acceptable_signature_schemes", "");
return (sig_schemes_str.empty()) ? Policy::acceptable_signature_schemes() : read_sig_scheme_list(sig_schemes_str);
}

bool Text_Policy::use_ecc_point_compression() const {
return get_bool("use_ecc_point_compression", Policy::use_ecc_point_compression());
}
Expand Down Expand Up @@ -290,6 +301,14 @@ std::vector<Certificate_Type> Text_Policy::read_cert_type_list(const std::string
return cert_types;
}

std::vector<Signature_Scheme> Text_Policy::read_sig_scheme_list(std::string_view sig_scheme_str) const {
std::vector<Signature_Scheme> sig_schemes;
for(const auto& sig_scheme_name : split_on(sig_scheme_str, ' ')) {
sig_schemes.push_back(Signature_Scheme::from_string(sig_scheme_name));
}
return sig_schemes;
}

size_t Text_Policy::get_len(const std::string& key, size_t def) const {
const std::string v = get_str(key);

Expand Down
3 changes: 1 addition & 2 deletions src/tests/data/tls-policy/rfc8448_1rtt.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ allow_dtls10 = false
allow_dtls12 = false
ciphers = AES-128/GCM ChaCha20Poly1305 AES-256/GCM
macs = AEAD
signature_hashes = SHA-512 SHA-384 SHA-256
signature_methods = ECDSA RSA
signature_schemes = ECDSA_SHA256 ECDSA_SHA384 ECDSA_SHA512 ECDSA_SHA1 RSA_PSS_SHA256 RSA_PSS_SHA384 RSA_PSS_SHA512 RSA_PKCS1_SHA256 RSA_PKCS1_SHA384 RSA_PKCS1_SHA512 RSA_PKCS1_SHA1 0x0402 0x0502 0x0602 0x0202
key_exchange_groups = x25519 secp256r1 secp384r1 secp521r1 ffdhe/ietf/2048 ffdhe/ietf/3072 ffdhe/ietf/4096 ffdhe/ietf/6144 ffdhe/ietf/8192
key_exchange_groups_to_offer = x25519
allow_insecure_renegotiation = false
Expand Down
3 changes: 1 addition & 2 deletions src/tests/data/tls-policy/rfc8448_client_auth_server.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ allow_dtls10 = false
allow_dtls12 = false
ciphers = AES-128/GCM ChaCha20Poly1305 AES-256/GCM
macs = AEAD
signature_hashes = SHA-512 SHA-384 SHA-256
signature_methods = ECDSA RSA
signature_schemes = ECDSA_SHA256 ECDSA_SHA384 ECDSA_SHA512 ECDSA_SHA1 RSA_PSS_SHA256 RSA_PSS_SHA384 RSA_PSS_SHA512 RSA_PKCS1_SHA256 RSA_PKCS1_SHA384 RSA_PKCS1_SHA512 RSA_PKCS1_SHA1 0x0402 0x0502 0x0602 0x0202
key_exchange_groups = x25519 secp256r1 secp384r1 secp521r1 ffdhe/ietf/2048 ffdhe/ietf/3072 ffdhe/ietf/4096 ffdhe/ietf/6144 ffdhe/ietf/8192
key_exchange_groups_to_offer = x25519
allow_insecure_renegotiation = false
Expand Down
3 changes: 1 addition & 2 deletions src/tests/data/tls-policy/rfc8448_compat_client.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ allow_dtls10 = false
allow_dtls12 = false
ciphers = AES-128/GCM ChaCha20Poly1305 AES-256/GCM
macs = AEAD
signature_hashes = SHA-512 SHA-384 SHA-256
signature_methods = ECDSA RSA
signature_schemes = ECDSA_SHA256 ECDSA_SHA384 ECDSA_SHA512 ECDSA_SHA1 RSA_PSS_SHA256 RSA_PSS_SHA384 RSA_PSS_SHA512 RSA_PKCS1_SHA256 RSA_PKCS1_SHA384 RSA_PKCS1_SHA512 RSA_PKCS1_SHA1 0x0402 0x0502 0x0602 0x0202
key_exchange_groups = x25519 secp256r1 secp384r1 secp521r1 ffdhe/ietf/2048 ffdhe/ietf/3072 ffdhe/ietf/4096 ffdhe/ietf/6144 ffdhe/ietf/8192
key_exchange_groups_to_offer = x25519
allow_insecure_renegotiation = false
Expand Down
3 changes: 1 addition & 2 deletions src/tests/data/tls-policy/rfc8448_compat_server.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ allow_dtls10 = false
allow_dtls12 = false
ciphers = AES-128/GCM ChaCha20Poly1305 AES-256/GCM
macs = AEAD
signature_hashes = SHA-512 SHA-384 SHA-256
signature_methods = ECDSA RSA
signature_schemes = ECDSA_SHA256 ECDSA_SHA384 ECDSA_SHA512 ECDSA_SHA1 RSA_PSS_SHA256 RSA_PSS_SHA384 RSA_PSS_SHA512 RSA_PKCS1_SHA256 RSA_PKCS1_SHA384 RSA_PKCS1_SHA512 RSA_PKCS1_SHA1 0x0402 0x0502 0x0602 0x0202
key_exchange_groups = x25519 secp256r1 secp384r1 secp521r1 ffdhe/ietf/2048 ffdhe/ietf/3072 ffdhe/ietf/4096 ffdhe/ietf/6144 ffdhe/ietf/8192
key_exchange_groups_to_offer = x25519
allow_insecure_renegotiation = false
Expand Down
3 changes: 1 addition & 2 deletions src/tests/data/tls-policy/rfc8448_hrr_client.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ allow_dtls10 = false
allow_dtls12 = false
ciphers = AES-128/GCM ChaCha20Poly1305 AES-256/GCM
macs = AEAD
signature_hashes = SHA-512 SHA-384 SHA-256
signature_methods = ECDSA RSA
signature_schemes = ECDSA_SHA256 ECDSA_SHA384 ECDSA_SHA512 ECDSA_SHA1 RSA_PSS_SHA256 RSA_PSS_SHA384 RSA_PSS_SHA512 RSA_PKCS1_SHA256 RSA_PKCS1_SHA384 RSA_PKCS1_SHA512 RSA_PKCS1_SHA1 0x0402 0x0502 0x0602 0x0202
key_exchange_groups = x25519 secp256r1 secp384r1
key_exchange_groups_to_offer = x25519
allow_insecure_renegotiation = false
Expand Down
3 changes: 1 addition & 2 deletions src/tests/data/tls-policy/rfc8448_hrr_server.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ allow_dtls10 = false
allow_dtls12 = false
ciphers = AES-128/GCM ChaCha20Poly1305 AES-256/GCM
macs = AEAD
signature_hashes = SHA-512 SHA-384 SHA-256
signature_methods = ECDSA RSA
signature_schemes = ECDSA_SHA256 ECDSA_SHA384 ECDSA_SHA512 ECDSA_SHA1 RSA_PSS_SHA256 RSA_PSS_SHA384 RSA_PSS_SHA512 RSA_PKCS1_SHA256 RSA_PKCS1_SHA384 RSA_PKCS1_SHA512 RSA_PKCS1_SHA1 0x0402 0x0502 0x0602 0x0202
key_exchange_groups = secp256r1 secp384r1 x25519
allow_insecure_renegotiation = false
include_time_in_hello_random = false
Expand Down
3 changes: 1 addition & 2 deletions src/tests/data/tls-policy/rfc8448_psk_dhe.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ allow_dtls10 = false
allow_dtls12 = false
ciphers = AES-128/GCM ChaCha20Poly1305 AES-256/GCM
macs = AEAD
signature_hashes = SHA-512 SHA-384 SHA-256
signature_methods = ECDSA RSA
signature_schemes = ECDSA_SHA256 ECDSA_SHA384 ECDSA_SHA512 ECDSA_SHA1 RSA_PSS_SHA256 RSA_PSS_SHA384 RSA_PSS_SHA512 RSA_PKCS1_SHA256 RSA_PKCS1_SHA384 RSA_PKCS1_SHA512 RSA_PKCS1_SHA1 0x0402 0x0502 0x0602 0x0202
key_exchange_methods = ECDH DH ECDHE_PSK
key_exchange_groups = x25519 secp256r1 secp384r1
allow_insecure_renegotiation = false
Expand Down
3 changes: 1 addition & 2 deletions src/tests/data/tls-policy/rfc8448_rawpubkey.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ accepted_client_certificate_types=RawPublicKey
require_client_certificate_authentication=true
ciphers = AES-128/GCM ChaCha20Poly1305 AES-256/GCM
macs = AEAD
signature_hashes = SHA-512 SHA-384 SHA-256
signature_methods = ECDSA RSA
signature_schemes = ECDSA_SHA256 ECDSA_SHA384 ECDSA_SHA512 ECDSA_SHA1 RSA_PSS_SHA256 RSA_PSS_SHA384 RSA_PSS_SHA512 RSA_PKCS1_SHA256 RSA_PKCS1_SHA384 RSA_PKCS1_SHA512 RSA_PKCS1_SHA1 0x0402 0x0502 0x0602 0x0202
key_exchange_methods = ECDH DH ECDHE_PSK
key_exchange_groups = x25519 secp256r1 secp384r1
allow_insecure_renegotiation = false
Expand Down
73 changes: 20 additions & 53 deletions src/tests/test_tls_rfc8448.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -494,36 +494,8 @@ class RFC8448_Text_Policy : public Botan::TLS::Text_Policy {
}

public:
explicit RFC8448_Text_Policy(const std::string& policy_file, bool rfc8448 = true) :
Botan::TLS::Text_Policy(read_policy(policy_file)), m_rfc8448(rfc8448) {}

std::vector<Botan::TLS::Signature_Scheme> allowed_signature_schemes() const override {
if(!m_rfc8448) {
return Botan::TLS::Text_Policy::allowed_signature_schemes();
}

// We extend the allowed signature schemes with algorithms that we don't
// actually support. The nature of the RFC 8448 test forces us to generate
// bit-compatible TLS messages. Unfortunately, the test data offers all
// those algorithms in its Client Hellos.
return {
Botan::TLS::Signature_Scheme::ECDSA_SHA256,
Botan::TLS::Signature_Scheme::ECDSA_SHA384,
Botan::TLS::Signature_Scheme::ECDSA_SHA512,
Botan::TLS::Signature_Scheme::ECDSA_SHA1, // not actually supported
Botan::TLS::Signature_Scheme::RSA_PSS_SHA256,
Botan::TLS::Signature_Scheme::RSA_PSS_SHA384,
Botan::TLS::Signature_Scheme::RSA_PSS_SHA512,
Botan::TLS::Signature_Scheme::RSA_PKCS1_SHA256,
Botan::TLS::Signature_Scheme::RSA_PKCS1_SHA384,
Botan::TLS::Signature_Scheme::RSA_PKCS1_SHA512,
Botan::TLS::Signature_Scheme::RSA_PKCS1_SHA1, // not actually supported
Botan::TLS::Signature_Scheme(0x0402), // DSA_SHA256, not actually supported
Botan::TLS::Signature_Scheme(0x0502), // DSA_SHA384, not actually supported
Botan::TLS::Signature_Scheme(0x0602), // DSA_SHA512, not actually supported
Botan::TLS::Signature_Scheme(0x0202), // DSA_SHA1, not actually supported
};
}
explicit RFC8448_Text_Policy(const std::string& policy_file) :
Botan::TLS::Text_Policy(read_policy(policy_file)) {}

// Overriding the key exchange group selection to favour the server's key
// exchange group preference. This is required to enforce a Hello Retry Request
Expand All @@ -540,9 +512,6 @@ class RFC8448_Text_Policy : public Botan::TLS::Text_Policy {

return selected_group != supported_by_us.end() ? *selected_group : Named_Group::NONE;
}

private:
bool m_rfc8448;
};

/**
Expand Down Expand Up @@ -1566,15 +1535,14 @@ class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 {
return {
CHECK("Client Hello",
[&](Test::Result& result) {
ctx = std::make_unique<Client_Context>(
std::move(rng),
std::make_shared<RFC8448_Text_Policy>("rfc8448_psk_dhe", false /* no rfc8448 */),
vars.get_req_u64("CurrentTimestamp"),
sort_our_extensions,
std::nullopt,
ExternalPSK(vars.get_req_str("PskIdentity"),
vars.get_req_str("PskPRF"),
lock(vars.get_req_bin("PskSecret"))));
ctx = std::make_unique<Client_Context>(std::move(rng),
std::make_shared<RFC8448_Text_Policy>("rfc8448_psk_dhe"),
vars.get_req_u64("CurrentTimestamp"),
sort_our_extensions,
std::nullopt,
ExternalPSK(vars.get_req_str("PskIdentity"),
vars.get_req_str("PskPRF"),
lock(vars.get_req_bin("PskSecret"))));

result.test_is_true("client not closed", !ctx->client.is_closed());
ctx->check_callback_invocations(result,
Expand Down Expand Up @@ -2495,17 +2463,16 @@ class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 {
}
};

ctx = std::make_unique<Server_Context>(
std::move(rng),
std::make_shared<RFC8448_Text_Policy>("rfc8448_psk_dhe", false /* no rfc8448 */),
vars.get_req_u64("CurrentTimestamp"),
sort_our_extensions,
make_mock_signatures(vars),
false,
std::nullopt,
ExternalPSK(vars.get_req_str("PskIdentity"),
vars.get_req_str("PskPRF"),
lock(vars.get_req_bin("PskSecret"))));
ctx = std::make_unique<Server_Context>(std::move(rng),
std::make_shared<RFC8448_Text_Policy>("rfc8448_psk_dhe"),
vars.get_req_u64("CurrentTimestamp"),
sort_our_extensions,
make_mock_signatures(vars),
false,
std::nullopt,
ExternalPSK(vars.get_req_str("PskIdentity"),
vars.get_req_str("PskPRF"),
lock(vars.get_req_bin("PskSecret"))));
result.test_is_true("server not closed", !ctx->server.is_closed());

ctx->server.received_data(vars.get_req_bin("Record_ClientHello_1"));
Expand Down
Loading
Loading