diff options
author | Jack Lloyd <[email protected]> | 2017-12-04 12:08:01 -0500 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2017-12-04 12:08:01 -0500 |
commit | d3c1f3ba1a9d03ff8e84f0044ee3854804fac86b (patch) | |
tree | 95221f8edfda1f8ed4495449be9a78e8d61cb487 /src | |
parent | 683e105ad25fd862857eee51cd0ac757c45a86f8 (diff) | |
parent | 4477a88dcfa49075fa49a520c429fc1a6c0a3849 (diff) |
Merge #1332 Add callbacks to make it easier to offload TLS pk operations
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/tls/msg_cert_verify.cpp | 12 | ||||
-rw-r--r-- | src/lib/tls/msg_client_hello.cpp | 4 | ||||
-rw-r--r-- | src/lib/tls/msg_client_kex.cpp | 95 | ||||
-rw-r--r-- | src/lib/tls/msg_server_hello.cpp | 10 | ||||
-rw-r--r-- | src/lib/tls/msg_server_kex.cpp | 24 | ||||
-rw-r--r-- | src/lib/tls/tls_callbacks.cpp | 117 | ||||
-rw-r--r-- | src/lib/tls/tls_callbacks.h | 86 | ||||
-rw-r--r-- | src/lib/tls/tls_client.cpp | 25 | ||||
-rw-r--r-- | src/lib/tls/tls_handshake_state.cpp | 2 | ||||
-rw-r--r-- | src/lib/tls/tls_handshake_state.h | 4 | ||||
-rw-r--r-- | src/lib/tls/tls_policy.cpp | 3 | ||||
-rw-r--r-- | src/lib/tls/tls_policy.h | 8 | ||||
-rw-r--r-- | src/lib/tls/tls_text_policy.cpp | 6 | ||||
-rw-r--r-- | src/tests/unit_tls.cpp | 4 |
14 files changed, 294 insertions, 106 deletions
diff --git a/src/lib/tls/msg_cert_verify.cpp b/src/lib/tls/msg_cert_verify.cpp index 4b7ba5662..ce7a30374 100644 --- a/src/lib/tls/msg_cert_verify.cpp +++ b/src/lib/tls/msg_cert_verify.cpp @@ -1,6 +1,7 @@ /* * Certificate Verify Message * (C) 2004,2006,2011,2012 Jack Lloyd +* 2017 Harry Reimann, Rohde & Schwarz Cybersecurity * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -29,9 +30,9 @@ Certificate_Verify::Certificate_Verify(Handshake_IO& io, std::pair<std::string, Signature_Format> format = state.choose_sig_format(*priv_key, m_hash_algo, m_sig_algo, true, policy); - PK_Signer signer(*priv_key, rng, format.first, format.second); - - m_signature = signer.sign_message(state.hash().get_contents(), rng); + m_signature = + state.callbacks().tls_sign_message(*priv_key, rng, format.first, format.second, + state.hash().get_contents()); state.hash().update(io.send(*this)); } @@ -89,10 +90,9 @@ bool Certificate_Verify::verify(const X509_Certificate& cert, state.parse_sig_format(*key.get(), m_hash_algo, m_sig_algo, true, policy); - PK_Verifier verifier(*key, format.first, format.second); - const bool signature_valid = - verifier.verify_message(state.hash().get_contents(), m_signature); + state.callbacks().tls_verify_message(*key, format.first, format.second, + state.hash().get_contents(), m_signature); #if defined(BOTAN_UNSAFE_FUZZER_MODE) return true; diff --git a/src/lib/tls/msg_client_hello.cpp b/src/lib/tls/msg_client_hello.cpp index 3b13cf21d..cde2b737a 100644 --- a/src/lib/tls/msg_client_hello.cpp +++ b/src/lib/tls/msg_client_hello.cpp @@ -2,6 +2,7 @@ * TLS Hello Request and Client Hello Messages * (C) 2004-2011,2015,2016 Jack Lloyd * 2016 Matthias Gierlings +* 2017 Harry Reimann, Rohde & Schwarz Cybersecurity * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -105,7 +106,8 @@ Client_Hello::Client_Hello(Handshake_IO& io, m_extensions.add(new Renegotiation_Extension(reneg_info)); m_extensions.add(new Server_Name_Indicator(client_settings.hostname())); - m_extensions.add(new Certificate_Status_Request({}, {})); + if(policy.support_cert_status_message()) + m_extensions.add(new Certificate_Status_Request({}, {})); if(reneg_info.empty() && !next_protocols.empty()) m_extensions.add(new Application_Layer_Protocol_Notification(next_protocols)); diff --git a/src/lib/tls/msg_client_kex.cpp b/src/lib/tls/msg_client_kex.cpp index 51040e479..0ff99462c 100644 --- a/src/lib/tls/msg_client_kex.cpp +++ b/src/lib/tls/msg_client_kex.cpp @@ -1,13 +1,13 @@ /* * Client Key Exchange Message * (C) 2004-2010,2016 Jack Lloyd +* 2017 Harry Reimann, Rohde & Schwarz Cybersecurity * * Botan is released under the Simplified BSD License (see license.txt) */ #include <botan/tls_messages.h> #include <botan/tls_extensions.h> -#include <botan/oids.h> #include <botan/rng.h> #include <botan/internal/tls_reader.h> @@ -17,16 +17,8 @@ #include <botan/credentials_manager.h> #include <botan/internal/ct_utils.h> -#include <botan/pubkey.h> - -#include <botan/dh.h> -#include <botan/ecdh.h> #include <botan/rsa.h> -#if defined(BOTAN_HAS_CURVE_25519) - #include <botan/curve25519.h> -#endif - #if defined(BOTAN_HAS_CECPQ1) #include <botan/cecpq1.h> #endif @@ -94,49 +86,25 @@ Client_Key_Exchange::Client_Key_Exchange(Handshake_IO& io, if(kex_algo == "DH" || kex_algo == "DHE_PSK") { - BigInt p = BigInt::decode(reader.get_range<uint8_t>(2, 1, 65535)); - BigInt g = BigInt::decode(reader.get_range<uint8_t>(2, 1, 65535)); - BigInt Y = BigInt::decode(reader.get_range<uint8_t>(2, 1, 65535)); + const std::vector<uint8_t> modulus = reader.get_range<uint8_t>(2, 1, 65535); + const std::vector<uint8_t> generator = reader.get_range<uint8_t>(2, 1, 65535); + const std::vector<uint8_t> peer_public_value = reader.get_range<uint8_t>(2, 1, 65535); if(reader.remaining_bytes()) throw Decoding_Error("Bad params size for DH key exchange"); - /* - * A basic check for key validity. As we do not know q here we - * cannot check that Y is in the right subgroup. However since - * our key is ephemeral there does not seem to be any - * advantage to bogus keys anyway. - */ - if(Y <= 1 || Y >= p - 1) - throw TLS_Exception(Alert::INSUFFICIENT_SECURITY, - "Server sent bad DH key for DHE exchange"); - - DL_Group group(p, g); - - if(!group.verify_group(rng, false)) - throw TLS_Exception(Alert::INSUFFICIENT_SECURITY, - "DH group validation failed"); - - DH_PublicKey counterparty_key(group, Y); - - policy.check_peer_key_acceptable(counterparty_key); - - DH_PrivateKey priv_key(rng, group); - - PK_Key_Agreement ka(priv_key, rng, "Raw"); - - secure_vector<uint8_t> dh_secret = CT::strip_leading_zeros( - ka.derive_key(0, counterparty_key.public_value()).bits_of()); + const std::pair<secure_vector<uint8_t>, std::vector<uint8_t>> dh_result = + state.callbacks().tls_dh_agree(modulus, generator, peer_public_value, policy, rng); if(kex_algo == "DH") - m_pre_master = dh_secret; + m_pre_master = dh_result.first; else { - append_tls_length_value(m_pre_master, dh_secret, 2); + append_tls_length_value(m_pre_master, dh_result.first, 2); append_tls_length_value(m_pre_master, psk.bits_of(), 2); } - append_tls_length_value(m_key_material, priv_key.public_value(), 2); + append_tls_length_value(m_key_material, dh_result.second, 2); } else if(kex_algo == "ECDH" || kex_algo == "ECDHE_PSK") { @@ -158,51 +126,20 @@ Client_Key_Exchange::Client_Key_Exchange(Handshake_IO& io, "Server sent ECC curve prohibited by policy"); } - const std::vector<uint8_t> ecdh_key = reader.get_range<uint8_t>(1, 1, 255); - std::vector<uint8_t> our_ecdh_public; - secure_vector<uint8_t> ecdh_secret; - - if(curve_name == "x25519") - { -#if defined(BOTAN_HAS_CURVE_25519) - if(ecdh_key.size() != 32) - throw TLS_Exception(Alert::HANDSHAKE_FAILURE, "Invalid X25519 key size"); - - Curve25519_PublicKey counterparty_key(ecdh_key); - policy.check_peer_key_acceptable(counterparty_key); - Curve25519_PrivateKey priv_key(rng); - PK_Key_Agreement ka(priv_key, rng, "Raw"); - ecdh_secret = ka.derive_key(0, counterparty_key.public_value()).bits_of(); - - // X25519 is always compressed but sent as "uncompressed" in TLS - our_ecdh_public = priv_key.public_value(); -#else - throw Internal_Error("Negotiated X25519 somehow, but it is disabled"); -#endif - } - else - { - EC_Group group(OIDS::lookup(curve_name)); - ECDH_PublicKey counterparty_key(group, OS2ECP(ecdh_key, group.get_curve())); - policy.check_peer_key_acceptable(counterparty_key); - ECDH_PrivateKey priv_key(rng, group); - PK_Key_Agreement ka(priv_key, rng, "Raw"); - ecdh_secret = ka.derive_key(0, counterparty_key.public_value()).bits_of(); - - // follow server's preference for point compression - our_ecdh_public = priv_key.public_value( - state.server_hello()->prefers_compressed_ec_points() ? PointGFp::COMPRESSED : PointGFp::UNCOMPRESSED); - } + const std::vector<uint8_t> peer_public_value = reader.get_range<uint8_t>(1, 1, 255); + const std::pair<secure_vector<uint8_t>, std::vector<uint8_t>> ecdh_result = + state.callbacks().tls_ecdh_agree(curve_name, peer_public_value, policy, rng, + state.server_hello()->prefers_compressed_ec_points()); if(kex_algo == "ECDH") - m_pre_master = ecdh_secret; + m_pre_master = ecdh_result.first; else { - append_tls_length_value(m_pre_master, ecdh_secret, 2); + append_tls_length_value(m_pre_master, ecdh_result.first, 2); append_tls_length_value(m_pre_master, psk.bits_of(), 2); } - append_tls_length_value(m_key_material, our_ecdh_public, 1); + append_tls_length_value(m_key_material, ecdh_result.second, 1); } #if defined(BOTAN_HAS_SRP6) else if(kex_algo == "SRP_SHA") diff --git a/src/lib/tls/msg_server_hello.cpp b/src/lib/tls/msg_server_hello.cpp index 67c3d530f..9eb33645b 100644 --- a/src/lib/tls/msg_server_hello.cpp +++ b/src/lib/tls/msg_server_hello.cpp @@ -2,6 +2,7 @@ * TLS Server Hello and Server Hello Done * (C) 2004-2011,2015,2016 Jack Lloyd * 2016 Matthias Gierlings +* 2017 Harry Reimann, Rohde & Schwarz Cybersecurity * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -37,7 +38,7 @@ Server_Hello::Server_Hello(Handshake_IO& io, m_extensions.add(new Extended_Master_Secret); // Sending the extension back does not commit us to sending a stapled response - if(client_hello.supports_cert_status_message()) + if(client_hello.supports_cert_status_message() && policy.support_cert_status_message()) m_extensions.add(new Certificate_Status_Request); Ciphersuite c = Ciphersuite::by_id(m_ciphersuite); @@ -105,7 +106,7 @@ Server_Hello::Server_Hello(Handshake_IO& io, m_extensions.add(new Extended_Master_Secret); // Sending the extension back does not commit us to sending a stapled response - if(client_hello.supports_cert_status_message()) + if(client_hello.supports_cert_status_message() && policy.support_cert_status_message()) m_extensions.add(new Certificate_Status_Request); if(client_hello.supports_encrypt_then_mac() && policy.negotiate_encrypt_then_mac()) @@ -115,11 +116,6 @@ Server_Hello::Server_Hello(Handshake_IO& io, m_extensions.add(new Encrypt_then_MAC); } - if(client_hello.supports_cert_status_message()) - { - m_extensions.add(new Certificate_Status_Request); - } - if(resumed_session.ciphersuite().ecc_ciphersuite()) { m_extensions.add(new Supported_Point_Formats(policy.use_ecc_point_compression())); diff --git a/src/lib/tls/msg_server_kex.cpp b/src/lib/tls/msg_server_kex.cpp index ab75d3a9b..631273eb7 100644 --- a/src/lib/tls/msg_server_kex.cpp +++ b/src/lib/tls/msg_server_kex.cpp @@ -1,6 +1,7 @@ /* * Server Key Exchange Message * (C) 2004-2010,2012,2015,2016 Jack Lloyd +* 2017 Harry Reimann, Rohde & Schwarz Cybersecurity * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -185,12 +186,14 @@ Server_Key_Exchange::Server_Key_Exchange(Handshake_IO& io, std::pair<std::string, Signature_Format> format = state.choose_sig_format(*signing_key, m_hash_algo, m_sig_algo, false, policy); - PK_Signer signer(*signing_key, rng, format.first, format.second); + std::vector<uint8_t> buf = state.client_hello()->random(); - signer.update(state.client_hello()->random()); - signer.update(state.server_hello()->random()); - signer.update(params()); - m_signature = signer.signature(rng); + buf += state.server_hello()->random(); + buf += params(); + + m_signature = + state.callbacks().tls_sign_message(*signing_key, rng, + format.first, format.second, buf); } state.hash().update(io.send(*this)); @@ -300,13 +303,14 @@ bool Server_Key_Exchange::verify(const Public_Key& server_key, state.parse_sig_format(server_key, m_hash_algo, m_sig_algo, false, policy); - PK_Verifier verifier(server_key, format.first, format.second); + std::vector<uint8_t> buf = state.client_hello()->random(); - verifier.update(state.client_hello()->random()); - verifier.update(state.server_hello()->random()); - verifier.update(params()); + buf += state.server_hello()->random(); + buf += params(); - const bool signature_valid = verifier.check_signature(m_signature); + const bool signature_valid = + state.callbacks().tls_verify_message(server_key, format.first, format.second, + buf, m_signature); #if defined(BOTAN_UNSAFE_FUZZER_MODE) return true; diff --git a/src/lib/tls/tls_callbacks.cpp b/src/lib/tls/tls_callbacks.cpp index 59620aec2..b8f38589e 100644 --- a/src/lib/tls/tls_callbacks.cpp +++ b/src/lib/tls/tls_callbacks.cpp @@ -1,6 +1,7 @@ /* * TLS Callbacks * (C) 2016 Jack Lloyd +* 2017 Harry Reimann, Rohde & Schwarz Cybersecurity * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -9,6 +10,15 @@ #include <botan/tls_policy.h> #include <botan/x509path.h> #include <botan/ocsp.h> +#include <botan/dh.h> +#include <botan/ecdh.h> +#include <botan/oids.h> +#include <botan/tls_exceptn.h> +#include <botan/internal/ct_utils.h> + +#if defined(BOTAN_HAS_CURVE_25519) + #include <botan/curve25519.h> +#endif namespace Botan { @@ -50,4 +60,111 @@ void TLS::Callbacks::tls_verify_cert_chain( throw Exception("Certificate validation failure: " + result.result_string()); } +std::vector<uint8_t> TLS::Callbacks::tls_sign_message( + const Private_Key& key, + RandomNumberGenerator& rng, + const std::string& emsa, + Signature_Format format, + const std::vector<uint8_t>& msg) + { + PK_Signer signer(key, rng, emsa, format); + + return signer.sign_message(msg, rng); + } + +bool TLS::Callbacks::tls_verify_message( + const Public_Key& key, + const std::string& emsa, + Signature_Format format, + const std::vector<uint8_t>& msg, + const std::vector<uint8_t>& sig) + { + PK_Verifier verifier(key, emsa, format); + + return verifier.verify_message(msg, sig); + } + +std::pair<secure_vector<uint8_t>, std::vector<uint8_t>> TLS::Callbacks::tls_dh_agree( + const std::vector<uint8_t>& modulus, + const std::vector<uint8_t>& generator, + const std::vector<uint8_t>& peer_public_value, + const Policy& policy, + RandomNumberGenerator& rng) + { + BigInt p = BigInt::decode(modulus); + BigInt g = BigInt::decode(generator); + BigInt Y = BigInt::decode(peer_public_value); + + /* + * A basic check for key validity. As we do not know q here we + * cannot check that Y is in the right subgroup. However since + * our key is ephemeral there does not seem to be any + * advantage to bogus keys anyway. + */ + if(Y <= 1 || Y >= p - 1) + throw TLS_Exception(Alert::INSUFFICIENT_SECURITY, + "Server sent bad DH key for DHE exchange"); + + DL_Group group(p, g); + + if(!group.verify_group(rng, false)) + throw TLS_Exception(Alert::INSUFFICIENT_SECURITY, + "DH group validation failed"); + + DH_PublicKey peer_key(group, Y); + + policy.check_peer_key_acceptable(peer_key); + + DH_PrivateKey priv_key(rng, group); + PK_Key_Agreement ka(priv_key, rng, "Raw"); + secure_vector<uint8_t> dh_secret = CT::strip_leading_zeros( + ka.derive_key(0, peer_key.public_value()).bits_of()); + + return std::make_pair(dh_secret, priv_key.public_value()); + } + +std::pair<secure_vector<uint8_t>, std::vector<uint8_t>> TLS::Callbacks::tls_ecdh_agree( + const std::string& curve_name, + const std::vector<uint8_t>& peer_public_value, + const Policy& policy, + RandomNumberGenerator& rng, + bool compressed) + { + secure_vector<uint8_t> ecdh_secret; + std::vector<uint8_t> our_public_value; + + if(curve_name == "x25519") + { +#if defined(BOTAN_HAS_CURVE_25519) + if(peer_public_value.size() != 32) + { + throw TLS_Exception(Alert::HANDSHAKE_FAILURE, "Invalid X25519 key size"); + } + + Curve25519_PublicKey peer_key(peer_public_value); + policy.check_peer_key_acceptable(peer_key); + Curve25519_PrivateKey priv_key(rng); + PK_Key_Agreement ka(priv_key, rng, "Raw"); + ecdh_secret = ka.derive_key(0, peer_key.public_value()).bits_of(); + + // X25519 is always compressed but sent as "uncompressed" in TLS + our_public_value = priv_key.public_value(); +#else + throw Internal_Error("Negotiated X25519 somehow, but it is disabled"); +#endif + } + else + { + EC_Group group(OIDS::lookup(curve_name)); + ECDH_PublicKey peer_key(group, OS2ECP(peer_public_value, group.get_curve())); + policy.check_peer_key_acceptable(peer_key); + ECDH_PrivateKey priv_key(rng, group); + PK_Key_Agreement ka(priv_key, rng, "Raw"); + ecdh_secret = ka.derive_key(0, peer_key.public_value()).bits_of(); + our_public_value = priv_key.public_value(compressed ? PointGFp::COMPRESSED : PointGFp::UNCOMPRESSED); + } + + return std::make_pair(ecdh_secret, our_public_value); + } + } diff --git a/src/lib/tls/tls_callbacks.h b/src/lib/tls/tls_callbacks.h index 962bb2489..4437a222a 100644 --- a/src/lib/tls/tls_callbacks.h +++ b/src/lib/tls/tls_callbacks.h @@ -2,6 +2,7 @@ * TLS Callbacks * (C) 2016 Matthias Gierlings * 2016 Jack Lloyd +* 2017 Harry Reimann, Rohde & Schwarz Cybersecurity * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -11,6 +12,7 @@ #include <botan/tls_session.h> #include <botan/tls_alert.h> +#include <botan/pubkey.h> #include <functional> namespace Botan { @@ -140,6 +142,90 @@ class BOTAN_PUBLIC_API(2,0) Callbacks } /** + * Optional callback with default impl: sign a message + * + * Default implementation uses PK_Signer::sign_message(). + * Override to provide a different approach, e.g. using an external device. + * + * @param key the private key of the signer + * @param rng a random number generator + * @param emsa the encoding method to be applied to the message + * @param format the signature format + * @param msg the input data for the signature + * + * @return the signature + */ + virtual std::vector<uint8_t> tls_sign_message( + const Private_Key& key, + RandomNumberGenerator& rng, + const std::string& emsa, + Signature_Format format, + const std::vector<uint8_t>& msg); + + /** + * Optional callback with default impl: verify a message signature + * + * Default implementation uses PK_Verifier::verify_message(). + * Override to provide a different approach, e.g. using an external device. + * + * @param key the public key of the signer + * @param emsa the encoding method to be applied to the message + * @param format the signature format + * @param msg the input data for the signature + * @param sig the signature to be checked + * + * @return true if the signature is valid, false otherwise + */ + virtual bool tls_verify_message( + const Public_Key& key, + const std::string& emsa, + Signature_Format format, + const std::vector<uint8_t>& msg, + const std::vector<uint8_t>& sig); + + /** + * Optional callback with default impl: client side DH agreement + * + * Default implementation uses PK_Key_Agreement::derive_key(). + * Override to provide a different approach, e.g. using an external device. + * + * @param modulus the modulus p of the discrete logarithm group + * @param generator the generator of the DH subgroup + * @param peer_public_value the public value of the peer + * @param policy the TLS policy associated with the session being established + * @param rng a random number generator + * + * @return a pair consisting of the agreed raw secret and our public value + */ + virtual std::pair<secure_vector<uint8_t>, std::vector<uint8_t>> tls_dh_agree( + const std::vector<uint8_t>& modulus, + const std::vector<uint8_t>& generator, + const std::vector<uint8_t>& peer_public_value, + const Policy& policy, + RandomNumberGenerator& rng); + + /** + * Optional callback with default impl: client side ECDH agreement + * + * Default implementation uses PK_Key_Agreement::derive_key(). + * Override to provide a different approach, e.g. using an external device. + * + * @param curve_name the name of the elliptic curve + * @param peer_public_value the public value of the peer + * @param policy the TLS policy associated with the session being established + * @param rng a random number generator + * @param compressed the compression preference for our public value + * + * @return a pair consisting of the agreed raw secret and our public value + */ + virtual std::pair<secure_vector<uint8_t>, std::vector<uint8_t>> tls_ecdh_agree( + const std::string& curve_name, + const std::vector<uint8_t>& peer_public_value, + const Policy& policy, + RandomNumberGenerator& rng, + bool compressed); + + /** * Optional callback: inspect handshake message * Throw an exception to abort the handshake. * Default simply ignores the message. diff --git a/src/lib/tls/tls_client.cpp b/src/lib/tls/tls_client.cpp index 0e620a279..ad8fdfa2d 100644 --- a/src/lib/tls/tls_client.cpp +++ b/src/lib/tls/tls_client.cpp @@ -2,6 +2,7 @@ * TLS Client * (C) 2004-2011,2012,2015,2016 Jack Lloyd * 2016 Matthias Gierlings +* 2017 Harry Reimann, Rohde & Schwarz Cybersecurity * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -386,7 +387,8 @@ void Client::process_handshake_msg(const Handshake_State* active_state, "Client: No certificates sent by server"); /* - Certificate verification happens after we receive the server hello done, + If the server supports certificate status messages, + certificate verification happens after we receive the server hello done, in case an OCSP response was also available */ @@ -412,6 +414,24 @@ void Client::process_handshake_msg(const Handshake_State* active_state, { state.set_expected_next(CERTIFICATE_STATUS); // optional } + else + { + try + { + auto trusted_CAs = m_creds.trusted_certificate_authorities("tls-client", m_info.hostname()); + + callbacks().tls_verify_cert_chain(server_certs, + {}, + trusted_CAs, + Usage_Type::TLS_SERVER_AUTH, + m_info.hostname(), + policy()); + } + catch(std::exception& e) + { + throw TLS_Exception(Alert::BAD_CERTIFICATE, e.what()); + } + } } else if(type == CERTIFICATE_STATUS) { @@ -459,7 +479,8 @@ void Client::process_handshake_msg(const Handshake_State* active_state, { state.server_hello_done(new Server_Hello_Done(contents)); - if(state.server_certs() != nullptr) + if(state.server_certs() != nullptr && + state.server_hello()->supports_certificate_status_message()) { try { diff --git a/src/lib/tls/tls_handshake_state.cpp b/src/lib/tls/tls_handshake_state.cpp index 442d499d1..0fcf0d2ab 100644 --- a/src/lib/tls/tls_handshake_state.cpp +++ b/src/lib/tls/tls_handshake_state.cpp @@ -1,6 +1,7 @@ /* * TLS Handshaking * (C) 2004-2006,2011,2012,2015,2016 Jack Lloyd +* 2017 Harry Reimann, Rohde & Schwarz Cybersecurity * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -8,7 +9,6 @@ #include <botan/internal/tls_handshake_state.h> #include <botan/internal/tls_record.h> #include <botan/tls_messages.h> -#include <botan/tls_callbacks.h> #include <botan/kdf.h> #include <sstream> diff --git a/src/lib/tls/tls_handshake_state.h b/src/lib/tls/tls_handshake_state.h index e15e3a92f..437625ced 100644 --- a/src/lib/tls/tls_handshake_state.h +++ b/src/lib/tls/tls_handshake_state.h @@ -1,6 +1,7 @@ /* * TLS Handshake State * (C) 2004-2006,2011,2012 Jack Lloyd +* 2017 Harry Reimann, Rohde & Schwarz Cybersecurity * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -14,6 +15,7 @@ #include <botan/tls_ciphersuite.h> #include <botan/tls_exceptn.h> #include <botan/tls_handshake_msg.h> +#include <botan/tls_callbacks.h> #include <botan/pk_keys.h> #include <botan/pubkey.h> #include <functional> @@ -160,6 +162,8 @@ class Handshake_State const Session_Keys& session_keys() const { return m_session_keys; } + Callbacks& callbacks() const { return m_callbacks; } + void compute_session_keys(); void compute_session_keys(const secure_vector<uint8_t>& resume_master_secret); diff --git a/src/lib/tls/tls_policy.cpp b/src/lib/tls/tls_policy.cpp index 5d82eee0c..d849faf9d 100644 --- a/src/lib/tls/tls_policy.cpp +++ b/src/lib/tls/tls_policy.cpp @@ -2,6 +2,7 @@ * Policies for TLS * (C) 2004-2010,2012,2015,2016 Jack Lloyd * 2016 Christian Mainka +* 2017 Harry Reimann, Rohde & Schwarz Cybersecurity * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -341,6 +342,7 @@ bool Policy::include_time_in_hello_random() const { return true; } bool Policy::hide_unknown_users() const { return false; } bool Policy::server_uses_own_ciphersuite_preferences() const { return true; } bool Policy::negotiate_encrypt_then_mac() const { return true; } +bool Policy::support_cert_status_message() const { return true; } // 1 second initial timeout, 60 second max - see RFC 6347 sec 4.2.4.1 size_t Policy::dtls_initial_timeout() const { return 1*1000; } @@ -552,6 +554,7 @@ void Policy::print(std::ostream& o) const print_bool(o, "hide_unknown_users", hide_unknown_users()); print_bool(o, "server_uses_own_ciphersuite_preferences", server_uses_own_ciphersuite_preferences()); print_bool(o, "negotiate_encrypt_then_mac", negotiate_encrypt_then_mac()); + print_bool(o, "support_cert_status_message", support_cert_status_message()); o << "session_ticket_lifetime = " << session_ticket_lifetime() << '\n'; o << "dh_group = " << dh_group() << '\n'; o << "minimum_dh_group_size = " << minimum_dh_group_size() << '\n'; diff --git a/src/lib/tls/tls_policy.h b/src/lib/tls/tls_policy.h index db2cbb3bb..786cdeea8 100644 --- a/src/lib/tls/tls_policy.h +++ b/src/lib/tls/tls_policy.h @@ -1,6 +1,7 @@ /* * Hooks for application level policies on TLS connections * (C) 2004-2006,2013 Jack Lloyd +* 2017 Harry Reimann, Rohde & Schwarz Cybersecurity * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -288,6 +289,11 @@ class BOTAN_PUBLIC_API(2,0) Policy virtual bool negotiate_encrypt_then_mac() const; /** + * Indicates whether certificate status messages should be supported + */ + virtual bool support_cert_status_message() const; + + /** * Return allowed ciphersuites, in order of preference */ virtual std::vector<uint16_t> ciphersuite_list(Protocol_Version version, @@ -502,6 +508,8 @@ class BOTAN_PUBLIC_API(2,0) Text_Policy : public Policy bool negotiate_encrypt_then_mac() const override; + bool support_cert_status_message() const override; + std::string dh_group() const override; size_t minimum_ecdh_group_size() const override; diff --git a/src/lib/tls/tls_text_policy.cpp b/src/lib/tls/tls_text_policy.cpp index 345e6005f..97a6da31a 100644 --- a/src/lib/tls/tls_text_policy.cpp +++ b/src/lib/tls/tls_text_policy.cpp @@ -1,6 +1,7 @@ /* * Text-Based TLS Policy * (C) 2016,2017 Jack Lloyd +* 2017 Harry Reimann, Rohde & Schwarz Cybersecurity * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -103,6 +104,11 @@ bool Text_Policy::negotiate_encrypt_then_mac() const return get_bool("negotiate_encrypt_then_mac", Policy::negotiate_encrypt_then_mac()); } +bool Text_Policy::support_cert_status_message() const + { + return get_bool("support_cert_status_message", Policy::support_cert_status_message()); + } + std::string Text_Policy::dh_group() const { return get_str("dh_group", Policy::dh_group()); diff --git a/src/tests/unit_tls.cpp b/src/tests/unit_tls.cpp index b22028a0e..a154d2e18 100644 --- a/src/tests/unit_tls.cpp +++ b/src/tests/unit_tls.cpp @@ -2,6 +2,7 @@ * (C) 2014,2015 Jack Lloyd * 2016 Matthias Gierlings * 2017 René Korthaus, Rohde & Schwarz Cybersecurity +* 2017 Harry Reimann, Rohde & Schwarz Cybersecurity * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -1308,6 +1309,9 @@ class TLS_Unit_Tests final : public Test test_modern_versions(results, *client_ses, *server_ses, *creds, "ECDH", "AES-128/GCM", "AEAD", { { "signature_methods", "RSA" } }); + test_modern_versions(results, *client_ses, *server_ses, *creds, "ECDH", "AES-128/GCM", "AEAD", + { { "support_cert_status_message", "false" } }); + #if defined(BOTAN_HAS_DSA) test_modern_versions(results, *client_ses, *server_ses, *creds, "DH", "AES-128/GCM", "AEAD", { { "signature_methods", "DSA" } }); |