From b2b55e6c2fdb824f49923b60d2c3ffff8f0fb99a Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Thu, 21 Dec 2017 15:37:39 -0500 Subject: Use enums to represent TLS signature and kex algorithms. Adds support for PSS signatures (currently verifying only). --- src/lib/tls/tls_server.cpp | 83 +++++++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 41 deletions(-) (limited to 'src/lib/tls/tls_server.cpp') diff --git a/src/lib/tls/tls_server.cpp b/src/lib/tls/tls_server.cpp index 38c5cf2ca..61a360ba9 100644 --- a/src/lib/tls/tls_server.cpp +++ b/src/lib/tls/tls_server.cpp @@ -177,8 +177,6 @@ uint16_t choose_ciphersuite( if(!our_choice) std::swap(pref_list, other_list); - const std::set client_sig_algos = client_hello.supported_sig_algos(); - for(auto suite_id : pref_list) { if(!value_exists(other_list, suite_id)) @@ -187,39 +185,50 @@ uint16_t choose_ciphersuite( const Ciphersuite suite = Ciphersuite::by_id(suite_id); if(suite.valid() == false) + { continue; + } - if(suite.ecc_ciphersuite() && have_shared_ecc_curve == false) + if(have_shared_ecc_curve == false && suite.ecc_ciphersuite()) + { continue; + } // For non-anon ciphersuites - if(suite.sig_algo() != "") + if(suite.signature_used()) { + const std::string sig_algo = suite.sig_algo(); + // Do we have any certificates for this sig? - if(cert_chains.count(suite.sig_algo()) == 0) + if(cert_chains.count(sig_algo) == 0) + { continue; + } - // Client reques - if(!client_sig_algos.empty() && client_sig_algos.count(suite.sig_algo()) == 0) - continue; - } + if(version.supports_negotiable_signature_algorithms()) + { + const std::vector allowed = + policy.allowed_signature_schemes(); - if(version.supports_negotiable_signature_algorithms() && suite.sig_algo() != "") - { - const std::vector> client_sig_hash_pairs = - client_hello.supported_algos(); + std::vector client_sig_methods = + client_hello.signature_schemes(); - if(client_hello.supported_algos().empty() == false) - { - bool we_support_some_hash_by_client = false; + if(client_sig_methods.empty()) + { + // If empty, then implicit SHA-1 (TLS v1.2 rules) + client_sig_methods.push_back(Signature_Scheme::RSA_PKCS1_SHA1); + client_sig_methods.push_back(Signature_Scheme::ECDSA_SHA1); + client_sig_methods.push_back(Signature_Scheme::DSA_SHA1); + } + + bool we_support_some_hash_by_client = true; - for(auto&& hash_and_sig : client_hello.supported_algos()) + for(Signature_Scheme scheme : client_sig_methods) { - if(hash_and_sig.second == suite.sig_algo() && - policy.allowed_signature_hash(hash_and_sig.first)) + if(signature_algorithm_of_scheme(scheme) == suite.sig_algo() && + policy.allowed_signature_hash(hash_function_of_scheme(scheme))) { we_support_some_hash_by_client = true; - break; } } @@ -229,13 +238,6 @@ uint16_t choose_ciphersuite( "Policy does not accept any hash function supported by client"); } } - else - { - if(policy.allowed_signature_hash("SHA-1") == false) - throw TLS_Exception(Alert::HANDSHAKE_FAILURE, - "Client did not send signature_algorithms extension " - "and policy prohibits SHA-1 fallback"); - } } #if defined(BOTAN_HAS_SRP6) @@ -247,7 +249,7 @@ uint16_t choose_ciphersuite( client hello message. - RFC 5054 section 2.5.1.2 */ - if(suite.kex_algo() == "SRP_SHA" && client_hello.srp_identifier() == "") + if(suite.kex_method() == Kex_Algo::SRP_SHA && client_hello.srp_identifier() == "") throw TLS_Exception(Alert::UNKNOWN_PSK_IDENTITY, "Client wanted SRP but did not send username"); #endif @@ -806,23 +808,22 @@ void Server::session_create(Server_Handshake_State& pending_state, secure_renegotiation_check(pending_state.server_hello()); - const std::string sig_algo = pending_state.ciphersuite().sig_algo(); - const std::string kex_algo = pending_state.ciphersuite().kex_algo(); + const Ciphersuite& pending_suite = pending_state.ciphersuite(); - if(sig_algo != "") + Private_Key* private_key = nullptr; + + if(pending_suite.signature_used() || pending_suite.kex_method() == Kex_Algo::STATIC_RSA) { - BOTAN_ASSERT(!cert_chains[sig_algo].empty(), - "Attempting to send empty certificate chain"); + const std::string algo_used = + pending_suite.signature_used() ? pending_suite.sig_algo() : "RSA"; + + BOTAN_ASSERT(!cert_chains[algo_used].empty(), + "Attempting to send empty certificate chain"); pending_state.server_certs(new Certificate(pending_state.handshake_io(), pending_state.hash(), - cert_chains[sig_algo])); - } + cert_chains[algo_used])); - Private_Key* private_key = nullptr; - - if(kex_algo == "RSA" || sig_algo != "") - { private_key = m_creds.private_key_for( pending_state.server_certs()->cert_chain()[0], "tls-server", @@ -832,7 +833,7 @@ void Server::session_create(Server_Handshake_State& pending_state, throw Internal_Error("No private key located for associated server cert"); } - if(kex_algo == "RSA") + if(pending_suite.kex_method() == Kex_Algo::STATIC_RSA) { pending_state.set_server_rsa_kex_key(private_key); } @@ -853,7 +854,7 @@ void Server::session_create(Server_Handshake_State& pending_state, client_auth_CAs.insert(client_auth_CAs.end(), subjects.begin(), subjects.end()); } - if(!client_auth_CAs.empty() && pending_state.ciphersuite().sig_algo() != "") + if(!client_auth_CAs.empty() && pending_state.ciphersuite().signature_used()) { pending_state.cert_req( new Certificate_Req(pending_state.handshake_io(), -- cgit v1.2.3