diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/asn1/asn1_obj.h | 1 | ||||
-rw-r--r-- | src/lib/tls/tls_cbc/tls_cbc.cpp | 4 | ||||
-rw-r--r-- | src/lib/tls/tls_ciphersuite.cpp | 24 | ||||
-rw-r--r-- | src/lib/tls/tls_ciphersuite.h | 2 | ||||
-rw-r--r-- | src/lib/tls/tls_client.cpp | 1 | ||||
-rw-r--r-- | src/lib/tls/tls_extensions.h | 2 | ||||
-rw-r--r-- | src/lib/tls/tls_magic.h | 3 | ||||
-rw-r--r-- | src/lib/tls/tls_record.cpp | 84 | ||||
-rw-r--r-- | src/lib/tls/tls_record.h | 12 | ||||
-rw-r--r-- | src/lib/tls/tls_session_key.cpp | 46 | ||||
-rw-r--r-- | src/lib/tls/tls_session_key.h | 43 | ||||
-rw-r--r-- | src/lib/tls/tls_suite_info.cpp | 4 | ||||
-rw-r--r-- | src/lib/x509/crl_ent.h | 1 | ||||
-rwxr-xr-x | src/scripts/tls_suite_info.py | 8 |
14 files changed, 126 insertions, 109 deletions
diff --git a/src/lib/asn1/asn1_obj.h b/src/lib/asn1/asn1_obj.h index e44b30771..41228a2d8 100644 --- a/src/lib/asn1/asn1_obj.h +++ b/src/lib/asn1/asn1_obj.h @@ -18,6 +18,7 @@ class DER_Encoder; /** * ASN.1 Type and Class Tags +* This will become an enum class in a future major release */ enum ASN1_Tag : uint32_t { UNIVERSAL = 0x00, diff --git a/src/lib/tls/tls_cbc/tls_cbc.cpp b/src/lib/tls/tls_cbc/tls_cbc.cpp index e14f2ab86..b23718d89 100644 --- a/src/lib/tls/tls_cbc/tls_cbc.cpp +++ b/src/lib/tls/tls_cbc/tls_cbc.cpp @@ -94,8 +94,8 @@ void TLS_CBC_HMAC_AEAD_Mode::key_schedule(const uint8_t key[], size_t keylen) if(keylen != m_cipher_keylen + m_mac_keylen) throw Invalid_Key_Length(name(), keylen); - cbc().set_key(&key[0], m_cipher_keylen); - mac().set_key(&key[m_cipher_keylen], m_mac_keylen); + mac().set_key(&key[0], m_mac_keylen); + cbc().set_key(&key[m_mac_keylen], m_cipher_keylen); } void TLS_CBC_HMAC_AEAD_Mode::start_msg(const uint8_t nonce[], size_t nonce_len) diff --git a/src/lib/tls/tls_ciphersuite.cpp b/src/lib/tls/tls_ciphersuite.cpp index 88837387e..cf284e565 100644 --- a/src/lib/tls/tls_ciphersuite.cpp +++ b/src/lib/tls/tls_ciphersuite.cpp @@ -37,6 +37,30 @@ size_t Ciphersuite::nonce_bytes_from_handshake() const throw Invalid_State("In Ciphersuite::nonce_bytes_from_handshake invalid enum value"); } +size_t Ciphersuite::nonce_bytes_from_record(Protocol_Version version) const + { + switch(m_nonce_format) + { + case Nonce_Format::CBC_MODE: + { + if(version.supports_explicit_cbc_ivs()) + { + return cipher_algo() == "3DES" ? 8 : 16; + } + else + { + return 0; + } + } + case Nonce_Format::AEAD_IMPLICIT_4: + return 8; + case Nonce_Format::AEAD_XOR_12: + return 0; + } + + throw Invalid_State("In Ciphersuite::nonce_bytes_from_handshake invalid enum value"); + } + bool Ciphersuite::is_scsv(uint16_t suite) { // TODO: derive from IANA file in script diff --git a/src/lib/tls/tls_ciphersuite.h b/src/lib/tls/tls_ciphersuite.h index 7ef7623bb..1d23a6c4a 100644 --- a/src/lib/tls/tls_ciphersuite.h +++ b/src/lib/tls/tls_ciphersuite.h @@ -114,6 +114,8 @@ class BOTAN_PUBLIC_API(2,0) Ciphersuite final size_t nonce_bytes_from_handshake() const; + size_t nonce_bytes_from_record(Protocol_Version version) const; + Nonce_Format nonce_format() const { return m_nonce_format; } size_t mac_keylen() const { return m_mac_keylen; } diff --git a/src/lib/tls/tls_client.cpp b/src/lib/tls/tls_client.cpp index eb6d21b14..82991d8fc 100644 --- a/src/lib/tls/tls_client.cpp +++ b/src/lib/tls/tls_client.cpp @@ -235,7 +235,6 @@ void Client::process_handshake_msg(const Handshake_State* active_state, { Hello_Request hello_request(contents); - // Ignore request entirely if we are currently negotiating a handshake if(state.client_hello()) { throw TLS_Exception(Alert::HANDSHAKE_FAILURE, "Cannot renegotiate during a handshake"); diff --git a/src/lib/tls/tls_extensions.h b/src/lib/tls/tls_extensions.h index 7dda6aaa0..686aaad5d 100644 --- a/src/lib/tls/tls_extensions.h +++ b/src/lib/tls/tls_extensions.h @@ -28,6 +28,7 @@ class Policy; class TLS_Data_Reader; +// This will become an enum class in a future major release enum Handshake_Extension_Type { TLSEXT_SERVER_NAME_INDICATION = 0, TLSEXT_CERT_STATUS_REQUEST = 5, @@ -482,7 +483,6 @@ class BOTAN_UNSTABLE_API Unknown_Extension final : public Extension private: Handshake_Extension_Type m_type; std::vector<uint8_t> m_value; - }; /** diff --git a/src/lib/tls/tls_magic.h b/src/lib/tls/tls_magic.h index f9643f004..48bb34f4a 100644 --- a/src/lib/tls/tls_magic.h +++ b/src/lib/tls/tls_magic.h @@ -24,8 +24,10 @@ enum Size_Limits { MAX_CIPHERTEXT_SIZE = MAX_COMPRESSED_SIZE + 1024, }; +// This will become an enum class in a future major release enum Connection_Side { CLIENT = 1, SERVER = 2 }; +// This will become an enum class in a future major release enum Record_Type { CHANGE_CIPHER_SPEC = 20, ALERT = 21, @@ -35,6 +37,7 @@ enum Record_Type { NO_RECORD = 256 }; +// This will become an enum class in a future major release enum Handshake_Type { HELLO_REQUEST = 0, CLIENT_HELLO = 1, diff --git a/src/lib/tls/tls_record.cpp b/src/lib/tls/tls_record.cpp index 730751855..27714af0b 100644 --- a/src/lib/tls/tls_record.cpp +++ b/src/lib/tls/tls_record.cpp @@ -1,6 +1,6 @@ /* * TLS Record Handling -* (C) 2012,2013,2014,2015,2016 Jack Lloyd +* (C) 2012,2013,2014,2015,2016,2019 Jack Lloyd * 2016 Juraj Somorovsky * 2016 Matthias Gierlings * @@ -33,25 +33,14 @@ Connection_Cipher_State::Connection_Cipher_State(Protocol_Version version, bool uses_encrypt_then_mac) : m_start_time(std::chrono::system_clock::now()) { - SymmetricKey mac_key, cipher_key; - InitializationVector iv; + m_nonce_format = suite.nonce_format(); + m_nonce_bytes_from_record = suite.nonce_bytes_from_record(version); + m_nonce_bytes_from_handshake = suite.nonce_bytes_from_handshake(); - if(side == CLIENT) - { - cipher_key = keys.client_cipher_key(); - iv = keys.client_iv(); - mac_key = keys.client_mac_key(); - } - else - { - cipher_key = keys.server_cipher_key(); - iv = keys.server_iv(); - mac_key = keys.server_mac_key(); - } + const secure_vector<uint8_t>& aead_key = keys.aead_key(side); + m_nonce = keys.nonce(side); - m_nonce = unlock(iv.bits_of()); - m_nonce_bytes_from_handshake = m_nonce.size(); - m_nonce_format = suite.nonce_format(); + BOTAN_ASSERT_NOMSG(m_nonce.size() == m_nonce_bytes_from_handshake); if(nonce_format() == Nonce_Format::CBC_MODE) { @@ -81,14 +70,6 @@ Connection_Cipher_State::Connection_Cipher_State(Protocol_Version version, uses_encrypt_then_mac)); } - m_aead->set_key(cipher_key + mac_key); - - m_nonce_bytes_from_record = 0; - - if(version.supports_explicit_cbc_ivs()) - m_nonce_bytes_from_record = m_nonce_bytes_from_handshake; - else if(our_side == false) - m_aead->start(iv.bits_of()); #else throw Internal_Error("Negotiated disabled TLS CBC+HMAC ciphersuite"); #endif @@ -96,19 +77,9 @@ Connection_Cipher_State::Connection_Cipher_State(Protocol_Version version, else { m_aead = AEAD_Mode::create_or_throw(suite.cipher_algo(), our_side ? ENCRYPTION : DECRYPTION); - - m_aead->set_key(cipher_key + mac_key); - - if(nonce_format() == Nonce_Format::AEAD_IMPLICIT_4) - { - m_nonce_bytes_from_record = 8; - m_nonce.resize(m_nonce.size() + 8); - } - else if(nonce_format() != Nonce_Format::AEAD_XOR_12) - { - throw Invalid_State("Invalid AEAD nonce format used"); - } } + + m_aead->set_key(aead_key); } std::vector<uint8_t> Connection_Cipher_State::aead_nonce(uint64_t seq, RandomNumberGenerator& rng) @@ -136,7 +107,9 @@ std::vector<uint8_t> Connection_Cipher_State::aead_nonce(uint64_t seq, RandomNum } case Nonce_Format::AEAD_IMPLICIT_4: { - std::vector<uint8_t> nonce = m_nonce; + BOTAN_ASSERT_NOMSG(m_nonce.size() == 4); + std::vector<uint8_t> nonce(12); + copy_mem(&nonce[0], m_nonce.data(), 4); store_be(seq, &nonce[nonce_bytes_from_handshake()]); return nonce; } @@ -152,6 +125,12 @@ Connection_Cipher_State::aead_nonce(const uint8_t record[], size_t record_len, u { case Nonce_Format::CBC_MODE: { + if(nonce_bytes_from_record() == 0 && m_nonce.size()) + { + std::vector<uint8_t> nonce; + nonce.swap(m_nonce); + return nonce; + } if(record_len < nonce_bytes_from_record()) throw Decoding_Error("Invalid CBC packet too short to be valid"); std::vector<uint8_t> nonce(record, record + nonce_bytes_from_record()); @@ -166,9 +145,11 @@ Connection_Cipher_State::aead_nonce(const uint8_t record[], size_t record_len, u } case Nonce_Format::AEAD_IMPLICIT_4: { + BOTAN_ASSERT_NOMSG(m_nonce.size() == 4); if(record_len < nonce_bytes_from_record()) throw Decoding_Error("Invalid AEAD packet too short to be valid"); - std::vector<uint8_t> nonce = m_nonce; + std::vector<uint8_t> nonce(12); + copy_mem(&nonce[0], m_nonce.data(), 4); copy_mem(&nonce[nonce_bytes_from_handshake()], record, nonce_bytes_from_record()); return nonce; } @@ -233,14 +214,14 @@ void write_record(secure_vector<uint8_t>& output, return; } - AEAD_Mode* aead = cs->aead(); + AEAD_Mode& aead = cs->aead(); std::vector<uint8_t> aad = cs->format_ad(seq, msg.get_type(), version, static_cast<uint16_t>(msg.get_size())); - const size_t ctext_size = aead->output_length(msg.get_size()); + const size_t ctext_size = aead.output_length(msg.get_size()); const size_t rec_size = ctext_size + cs->nonce_bytes_from_record(); - aead->set_ad(aad); + aead.set_ad(aad); const std::vector<uint8_t> nonce = cs->aead_nonce(seq, rng); @@ -257,8 +238,8 @@ void write_record(secure_vector<uint8_t>& output, const size_t header_size = output.size(); output += std::make_pair(msg.get_data(), msg.get_size()); - aead->start(nonce); - aead->finish(output, header_size); + aead.start(nonce); + aead.finish(output, header_size); BOTAN_ASSERT(output.size() < MAX_CIPHERTEXT_SIZE, "Produced ciphertext larger than protocol allows"); @@ -292,8 +273,7 @@ void decrypt_record(secure_vector<uint8_t>& output, Record_Type record_type, Connection_Cipher_State& cs) { - AEAD_Mode* aead = cs.aead(); - BOTAN_ASSERT(aead, "Cannot decrypt without cipher"); + AEAD_Mode& aead = cs.aead(); const std::vector<uint8_t> nonce = cs.aead_nonce(record_contents, record_len, record_sequence); const uint8_t* msg = &record_contents[cs.nonce_bytes_from_record()]; @@ -306,23 +286,23 @@ void decrypt_record(secure_vector<uint8_t>& output, * tools which are attempting automated detection of padding oracles, * including older versions of TLS-Attacker. */ - if(msg_length < aead->minimum_final_size()) + if(msg_length < aead.minimum_final_size()) throw TLS_Exception(Alert::BAD_RECORD_MAC, "AEAD packet is shorter than the tag"); - const size_t ptext_size = aead->output_length(msg_length); + const size_t ptext_size = aead.output_length(msg_length); - aead->set_associated_data_vec( + aead.set_associated_data_vec( cs.format_ad(record_sequence, static_cast<uint8_t>(record_type), record_version, static_cast<uint16_t>(ptext_size)) ); - aead->start(nonce); + aead.start(nonce); const size_t offset = output.size(); output += std::make_pair(msg, msg_length); - aead->finish(output, offset); + aead.finish(output, offset); } size_t read_tls_record(secure_vector<uint8_t>& readbuf, diff --git a/src/lib/tls/tls_record.h b/src/lib/tls/tls_record.h index 7ccd78b86..d0ffc0270 100644 --- a/src/lib/tls/tls_record.h +++ b/src/lib/tls/tls_record.h @@ -42,7 +42,11 @@ class Connection_Cipher_State final const Session_Keys& keys, bool uses_encrypt_then_mac); - AEAD_Mode* aead() { return m_aead.get(); } + AEAD_Mode& aead() + { + BOTAN_ASSERT_NONNULL(m_aead.get()); + return *m_aead.get(); + } std::vector<uint8_t> aead_nonce(uint64_t seq, RandomNumberGenerator& rng); @@ -68,9 +72,9 @@ class Connection_Cipher_State final std::unique_ptr<AEAD_Mode> m_aead; std::vector<uint8_t> m_nonce; - Nonce_Format m_nonce_format = Nonce_Format::CBC_MODE; - size_t m_nonce_bytes_from_handshake = 0; - size_t m_nonce_bytes_from_record = 0; + Nonce_Format m_nonce_format; + size_t m_nonce_bytes_from_handshake; + size_t m_nonce_bytes_from_record; }; class Record final diff --git a/src/lib/tls/tls_session_key.cpp b/src/lib/tls/tls_session_key.cpp index 469d1d387..206681041 100644 --- a/src/lib/tls/tls_session_key.cpp +++ b/src/lib/tls/tls_session_key.cpp @@ -1,6 +1,6 @@ /* * TLS Session Key -* (C) 2004-2006,2011,2016 Jack Lloyd +* (C) 2004-2006,2011,2016,2019 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -48,17 +48,17 @@ Session_Keys::Session_Keys(const Handshake_State* state, } else { - secure_vector<uint8_t> salt; - secure_vector<uint8_t> label; + std::vector<uint8_t> salt; + std::vector<uint8_t> label; if(extended_master_secret) { - label += std::make_pair(EXT_MASTER_SECRET_MAGIC, sizeof(EXT_MASTER_SECRET_MAGIC)); + label.assign(EXT_MASTER_SECRET_MAGIC, EXT_MASTER_SECRET_MAGIC + sizeof(EXT_MASTER_SECRET_MAGIC)); salt += state->hash().final(state->version(), state->ciphersuite().prf_algo()); } else { - label += std::make_pair(MASTER_SECRET_MAGIC, sizeof(MASTER_SECRET_MAGIC)); + label.assign(MASTER_SECRET_MAGIC, MASTER_SECRET_MAGIC + sizeof(MASTER_SECRET_MAGIC)); salt += state->client_hello()->random(); salt += state->server_hello()->random(); } @@ -66,32 +66,34 @@ Session_Keys::Session_Keys(const Handshake_State* state, m_master_sec = prf->derive_key(48, pre_master_secret, salt, label); } - secure_vector<uint8_t> salt; - secure_vector<uint8_t> label; - label += std::make_pair(KEY_GEN_MAGIC, sizeof(KEY_GEN_MAGIC)); + std::vector<uint8_t> salt; + std::vector<uint8_t> label; + label.assign(KEY_GEN_MAGIC, KEY_GEN_MAGIC + sizeof(KEY_GEN_MAGIC)); salt += state->server_hello()->random(); salt += state->client_hello()->random(); - SymmetricKey keyblock = prf->derive_key(prf_gen, m_master_sec, salt, label); + const secure_vector<uint8_t> prf_output = prf->derive_key( + prf_gen, + m_master_sec.data(), m_master_sec.size(), + salt.data(), salt.size(), + label.data(), label.size()); - const uint8_t* key_data = keyblock.begin(); + const uint8_t* key_data = prf_output.data(); - m_c_mac = SymmetricKey(key_data, mac_keylen); - key_data += mac_keylen; + m_c_aead.resize(mac_keylen + cipher_keylen); + m_s_aead.resize(mac_keylen + cipher_keylen); - m_s_mac = SymmetricKey(key_data, mac_keylen); - key_data += mac_keylen; + copy_mem(&m_c_aead[0], key_data, mac_keylen); + copy_mem(&m_s_aead[0], key_data + mac_keylen, mac_keylen); - m_c_cipher = SymmetricKey(key_data, cipher_keylen); - key_data += cipher_keylen; + copy_mem(&m_c_aead[mac_keylen], key_data + 2*mac_keylen, cipher_keylen); + copy_mem(&m_s_aead[mac_keylen], key_data + 2*mac_keylen + cipher_keylen, cipher_keylen); - m_s_cipher = SymmetricKey(key_data, cipher_keylen); - key_data += cipher_keylen; + m_c_nonce.resize(cipher_nonce_bytes); + m_s_nonce.resize(cipher_nonce_bytes); - m_c_iv = InitializationVector(key_data, cipher_nonce_bytes); - key_data += cipher_nonce_bytes; - - m_s_iv = InitializationVector(key_data, cipher_nonce_bytes); + copy_mem(&m_c_nonce[0], key_data + 2*(mac_keylen + cipher_keylen), cipher_nonce_bytes); + copy_mem(&m_s_nonce[0], key_data + 2*(mac_keylen + cipher_keylen) + cipher_nonce_bytes, cipher_nonce_bytes); } } diff --git a/src/lib/tls/tls_session_key.h b/src/lib/tls/tls_session_key.h index 2c1eac523..0ea6d81cd 100644 --- a/src/lib/tls/tls_session_key.h +++ b/src/lib/tls/tls_session_key.h @@ -8,7 +8,8 @@ #ifndef BOTAN_TLS_SESSION_KEYS_H_ #define BOTAN_TLS_SESSION_KEYS_H_ -#include <botan/symkey.h> +#include <botan/secmem.h> +#include <botan/tls_magic.h> namespace Botan { @@ -23,40 +24,40 @@ class Session_Keys final { public: /** - * @return client encipherment key + * @return client AEAD key */ - const SymmetricKey& client_cipher_key() const { return m_c_cipher; } + const secure_vector<uint8_t>& client_aead_key() const { return m_c_aead; } /** - * @return client encipherment key + * @return server AEAD key */ - const SymmetricKey& server_cipher_key() const { return m_s_cipher; } + const secure_vector<uint8_t>& server_aead_key() const { return m_s_aead; } /** - * @return client MAC key + * @return client nonce */ - const SymmetricKey& client_mac_key() const { return m_c_mac; } + const std::vector<uint8_t>& client_nonce() const { return m_c_nonce; } /** - * @return server MAC key + * @return server nonce */ - const SymmetricKey& server_mac_key() const { return m_s_mac; } - - /** - * @return client IV - */ - const InitializationVector& client_iv() const { return m_c_iv; } - - /** - * @return server IV - */ - const InitializationVector& server_iv() const { return m_s_iv; } + const std::vector<uint8_t>& server_nonce() const { return m_s_nonce; } /** * @return TLS master secret */ const secure_vector<uint8_t>& master_secret() const { return m_master_sec; } + const secure_vector<uint8_t>& aead_key(Connection_Side side) const + { + return (side == Connection_Side::CLIENT) ? client_aead_key() : server_aead_key(); + } + + const std::vector<uint8_t>& nonce(Connection_Side side) const + { + return (side == Connection_Side::CLIENT) ? client_nonce() : server_nonce(); + } + Session_Keys() = default; /** @@ -70,8 +71,8 @@ class Session_Keys final private: secure_vector<uint8_t> m_master_sec; - SymmetricKey m_c_cipher, m_s_cipher, m_c_mac, m_s_mac; - InitializationVector m_c_iv, m_s_iv; + secure_vector<uint8_t> m_c_aead, m_s_aead; + std::vector<uint8_t> m_c_nonce, m_s_nonce; }; } diff --git a/src/lib/tls/tls_suite_info.cpp b/src/lib/tls/tls_suite_info.cpp index 574b4e5b8..f55b7cce1 100644 --- a/src/lib/tls/tls_suite_info.cpp +++ b/src/lib/tls/tls_suite_info.cpp @@ -2,8 +2,8 @@ * TLS cipher suite information * * This file was automatically generated from the IANA assignments -* (tls-parameters.txt hash ac96406c0080f669ca9442b0f5efcb31549ecb2e) -* by ./src/scripts/tls_suite_info.py on 2017-11-05 +* (tls-parameters.txt hash fe1ef8f3492b0708f3b14c9e8f8de55188c1b3c0) +* by ./src/scripts/tls_suite_info.py on 2019-05-24 * * Botan is released under the Simplified BSD License (see license.txt) */ diff --git a/src/lib/x509/crl_ent.h b/src/lib/x509/crl_ent.h index 9c9e86c03..ea64ee21a 100644 --- a/src/lib/x509/crl_ent.h +++ b/src/lib/x509/crl_ent.h @@ -18,6 +18,7 @@ struct CRL_Entry_Data; /** * X.509v2 CRL Reason Code. +* This will become an enum class in a future major release */ enum CRL_Code : uint32_t { UNSPECIFIED = 0, diff --git a/src/scripts/tls_suite_info.py b/src/scripts/tls_suite_info.py index 124a583e1..e19c24186 100755 --- a/src/scripts/tls_suite_info.py +++ b/src/scripts/tls_suite_info.py @@ -200,10 +200,10 @@ def main(args = None): if args is None: args = sys.argv - weak_crypto = ['EXPORT', 'RC2', 'IDEA', 'RC4', '_DES_', 'WITH_NULL'] + weak_crypto = ['EXPORT', 'RC2', 'IDEA', 'RC4', '_DES_', 'WITH_NULL', 'GOST'] static_dh = ['ECDH_ECDSA', 'ECDH_RSA', 'DH_DSS', 'DH_RSA'] # not supported protocol_goop = ['SCSV', 'KRB5'] - maybe_someday = ['RSA_PSK'] + maybe_someday = ['RSA_PSK', 'ECCPWD'] not_supported = weak_crypto + static_dh + protocol_goop + maybe_someday (options, args) = process_command_line(args) @@ -230,7 +230,7 @@ def main(args = None): if ns in name: should_use = False - if should_use: + if should_use and name.find('_WITH_') > 0: suites[code] = to_ciphersuite_info(code, name) sha1 = hashlib.sha1() @@ -320,11 +320,11 @@ const std::vector<Ciphersuite>& Ciphersuite::all_known_ciphersuites() for code in sorted(suites.keys()): info = suites[code] assert len(info) == 10 + suite_expr = 'Ciphersuite(0x%s, "%s", Auth_Method::%s, Kex_Algo::%s, "%s", %d, "%s", %d, KDF_Algo::%s, Nonce_Format::%s)' % ( code, info[0], info[2], info[3], info[4], info[5], info[6], info[7], info[8].replace('-','_'), info[9]) suite_info += " " + suite_expr + ",\n" - suite_info += """ }; |