diff options
author | Jack Lloyd <[email protected]> | 2016-10-07 15:50:48 -0400 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2016-10-07 15:50:48 -0400 |
commit | 36220cebaae551f3e7c22e2abd8a8ce848e56892 (patch) | |
tree | 3b9aca25bf2437b7cde4f4df7e3bb876a139c264 /src/lib | |
parent | b2209d7ebe29bfe2ab5d25eb2be7c51d42ea2a46 (diff) | |
parent | c2d88a0c4e0d2b6aa461cf7c415eea23ff3994c2 (diff) |
Merge GH #645 TLS compressed points
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/pubkey/ecdh/ecdh.h | 11 | ||||
-rw-r--r-- | src/lib/tls/msg_client_hello.cpp | 16 | ||||
-rw-r--r-- | src/lib/tls/msg_client_kex.cpp | 5 | ||||
-rw-r--r-- | src/lib/tls/msg_server_hello.cpp | 8 | ||||
-rw-r--r-- | src/lib/tls/msg_server_kex.cpp | 5 | ||||
-rw-r--r-- | src/lib/tls/tls_extensions.cpp | 40 | ||||
-rw-r--r-- | src/lib/tls/tls_extensions.h | 32 | ||||
-rw-r--r-- | src/lib/tls/tls_messages.h | 18 | ||||
-rw-r--r-- | src/lib/tls/tls_policy.cpp | 5 | ||||
-rw-r--r-- | src/lib/tls/tls_policy.h | 8 |
10 files changed, 143 insertions, 5 deletions
diff --git a/src/lib/pubkey/ecdh/ecdh.h b/src/lib/pubkey/ecdh/ecdh.h index 2f892436c..bdd9ea047 100644 --- a/src/lib/pubkey/ecdh/ecdh.h +++ b/src/lib/pubkey/ecdh/ecdh.h @@ -55,6 +55,12 @@ class BOTAN_DLL ECDH_PublicKey : public virtual EC_PublicKey std::vector<byte> public_value() const { return unlock(EC2OSP(public_point(), PointGFp::UNCOMPRESSED)); } + /** + * @return public point value + */ + std::vector<byte> public_value(PointGFp::Compression_Type type) const + { return unlock(EC2OSP(public_point(), type)); } + protected: ECDH_PublicKey(); }; @@ -84,7 +90,10 @@ class BOTAN_DLL ECDH_PrivateKey : public ECDH_PublicKey, EC_PrivateKey(rng, domain, x) {} std::vector<byte> public_value() const override - { return ECDH_PublicKey::public_value(); } + { return ECDH_PublicKey::public_value(PointGFp::UNCOMPRESSED); } + + std::vector<byte> public_value(PointGFp::Compression_Type type) const + { return ECDH_PublicKey::public_value(type); } }; } diff --git a/src/lib/tls/msg_client_hello.cpp b/src/lib/tls/msg_client_hello.cpp index b493fd3ee..36335e7ce 100644 --- a/src/lib/tls/msg_client_hello.cpp +++ b/src/lib/tls/msg_client_hello.cpp @@ -98,8 +98,12 @@ Client_Hello::Client_Hello(Handshake_IO& io, if(reneg_info.empty() && !next_protocols.empty()) m_extensions.add(new Application_Layer_Protocol_Notification(next_protocols)); + if(m_version.supports_negotiable_signature_algorithms()) + m_extensions.add(new Signature_Algorithms(policy.allowed_signature_hashes(), + policy.allowed_signature_methods())); + if(m_version.is_datagram_protocol()) - m_extensions.add(new SRTP_Protection_Profiles(policy.srtp_profiles())); + m_extensions.add(new SRTP_Protection_Profiles(policy.srtp_profiles())); #if defined(BOTAN_HAS_SRP6) m_extensions.add(new SRP_Identifier(client_settings.srp_identifier())); @@ -112,6 +116,11 @@ Client_Hello::Client_Hello(Handshake_IO& io, m_extensions.add(new Supported_Elliptic_Curves(policy.allowed_ecc_curves())); + if(!policy.allowed_ecc_curves().empty() && policy.use_ecc_point_compression()) + { + m_extensions.add(new Supported_Point_Formats()); + } + if(m_version.supports_negotiable_signature_algorithms()) m_extensions.add(new Signature_Algorithms(policy.allowed_signature_hashes(), policy.allowed_signature_methods())); @@ -156,6 +165,11 @@ Client_Hello::Client_Hello(Handshake_IO& io, m_extensions.add(new Session_Ticket(session.session_ticket())); m_extensions.add(new Supported_Elliptic_Curves(policy.allowed_ecc_curves())); + if(!policy.allowed_ecc_curves().empty() && policy.use_ecc_point_compression()) + { + m_extensions.add(new Supported_Point_Formats()); + } + if(m_version.supports_negotiable_signature_algorithms()) m_extensions.add(new Signature_Algorithms(policy.allowed_signature_hashes(), policy.allowed_signature_methods())); diff --git a/src/lib/tls/msg_client_kex.cpp b/src/lib/tls/msg_client_kex.cpp index bc4d33d52..0eceadb3b 100644 --- a/src/lib/tls/msg_client_kex.cpp +++ b/src/lib/tls/msg_client_kex.cpp @@ -172,7 +172,10 @@ Client_Key_Exchange::Client_Key_Exchange(Handshake_IO& io, append_tls_length_value(m_pre_master, psk.bits_of(), 2); } - append_tls_length_value(m_key_material, priv_key.public_value(), 1); + // follow server's preference for point compression + append_tls_length_value(m_key_material, + priv_key.public_value(state.server_hello()->prefers_compressed_ec_points() ? + PointGFp::COMPRESSED : PointGFp::UNCOMPRESSED ), 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 ebe8fb085..4f95a5c9d 100644 --- a/src/lib/tls/msg_server_hello.cpp +++ b/src/lib/tls/msg_server_hello.cpp @@ -35,12 +35,18 @@ Server_Hello::Server_Hello(Handshake_IO& io, if(client_hello.supports_extended_master_secret()) m_extensions.add(new Extended_Master_Secret); + Ciphersuite c = Ciphersuite::by_id(m_ciphersuite); + if(client_hello.supports_encrypt_then_mac() && policy.negotiate_encrypt_then_mac()) { - Ciphersuite c = Ciphersuite::by_id(m_ciphersuite); if(c.cbc_ciphersuite()) m_extensions.add(new Encrypt_then_MAC); } + + if(c.ecc_ciphersuite() && policy.use_ecc_point_compression()) + { + m_extensions.add(new Supported_Point_Formats()); + } if(client_hello.secure_renegotiation()) m_extensions.add(new Renegotiation_Extension(reneg_info)); diff --git a/src/lib/tls/msg_server_kex.cpp b/src/lib/tls/msg_server_kex.cpp index 10581fe45..33b980ba9 100644 --- a/src/lib/tls/msg_server_kex.cpp +++ b/src/lib/tls/msg_server_kex.cpp @@ -85,7 +85,10 @@ Server_Key_Exchange::Server_Key_Exchange(Handshake_IO& io, m_params.push_back(get_byte(0, named_curve_id)); m_params.push_back(get_byte(1, named_curve_id)); - append_tls_length_value(m_params, ecdh->public_value(), 1); + // follow client's preference for point compression + append_tls_length_value(m_params, + ecdh->public_value(state.client_hello()->prefers_compressed_ec_points() ? + PointGFp::COMPRESSED : PointGFp::UNCOMPRESSED), 1); m_kex_key.reset(ecdh.release()); } diff --git a/src/lib/tls/tls_extensions.cpp b/src/lib/tls/tls_extensions.cpp index e38e4ccdc..df265d915 100644 --- a/src/lib/tls/tls_extensions.cpp +++ b/src/lib/tls/tls_extensions.cpp @@ -33,6 +33,9 @@ Extension* make_extension(TLS_Data_Reader& reader, case TLSEXT_USABLE_ELLIPTIC_CURVES: return new Supported_Elliptic_Curves(reader, size); + case TLSEXT_EC_POINT_FORMATS: + return new Supported_Point_Formats(reader, size); + case TLSEXT_SAFE_RENEGOTIATION: return new Renegotiation_Extension(reader, size); @@ -353,6 +356,43 @@ Supported_Elliptic_Curves::Supported_Elliptic_Curves(TLS_Data_Reader& reader, } } +std::vector<byte> Supported_Point_Formats::serialize() const + { + // if we send this extension, we prefer compressed points, + // otherwise we don't send it (which is equal to supporting only uncompressed) + // if this extension is sent, it MUST include uncompressed (RFC 4492, section 5.1) + return std::vector<byte>{2, ANSIX962_COMPRESSED_PRIME, UNCOMPRESSED}; + } + +Supported_Point_Formats::Supported_Point_Formats(TLS_Data_Reader& reader, + u16bit extension_size) + { + byte len = reader.get_byte(); + + if(len + 1 != extension_size) + throw Decoding_Error("Inconsistent length field in supported point formats list"); + + for(size_t i = 0; i != len; ++i) + { + byte format = reader.get_byte(); + + if(format == UNCOMPRESSED) + { + m_prefers_compressed = false; + reader.discard_next(len-i-1); + return; + } + else if(format == ANSIX962_COMPRESSED_PRIME) + { + m_prefers_compressed = true; + reader.discard_next(len-i-1); + return; + } + + // ignore ANSIX962_COMPRESSED_CHAR2, we don't support these curves + } + } + std::string Signature_Algorithms::hash_algo_name(byte code) { switch(code) diff --git a/src/lib/tls/tls_extensions.h b/src/lib/tls/tls_extensions.h index c270bf23a..d69e40a60 100644 --- a/src/lib/tls/tls_extensions.h +++ b/src/lib/tls/tls_extensions.h @@ -258,6 +258,38 @@ class Supported_Elliptic_Curves final : public Extension }; /** +* Supported Point Formats Extension (RFC 4492) +*/ +class Supported_Point_Formats final : public Extension + { + public: + enum ECPointFormat : byte { + UNCOMPRESSED = 0, + ANSIX962_COMPRESSED_PRIME = 1, + ANSIX962_COMPRESSED_CHAR2 = 2, // don't support these curves + }; + + static Handshake_Extension_Type static_type() + { return TLSEXT_EC_POINT_FORMATS; } + + Handshake_Extension_Type type() const override { return static_type(); } + + std::vector<byte> serialize() const override; + + explicit Supported_Point_Formats() : m_prefers_compressed(true) {} + + Supported_Point_Formats(TLS_Data_Reader& reader, + u16bit extension_size); + + bool empty() const override { return false; } + + bool prefers_compressed() { return m_prefers_compressed; } + + private: + bool m_prefers_compressed = false; + }; + +/** * Signature Algorithms Extension for TLS 1.2 (RFC 5246) */ class Signature_Algorithms final : public Extension diff --git a/src/lib/tls/tls_messages.h b/src/lib/tls/tls_messages.h index 698dbc99f..25228c865 100644 --- a/src/lib/tls/tls_messages.h +++ b/src/lib/tls/tls_messages.h @@ -121,6 +121,15 @@ class BOTAN_DLL Client_Hello final : public Handshake_Message return std::vector<std::string>(); } + bool prefers_compressed_ec_points() const + { + if(Supported_Point_Formats* ecc_formats = m_extensions.get<Supported_Point_Formats>()) + { + return ecc_formats->prefers_compressed(); + } + return false; + } + std::string sni_hostname() const { if(Server_Name_Indicator* sni = m_extensions.get<Server_Name_Indicator>()) @@ -328,6 +337,15 @@ class BOTAN_DLL Server_Hello final : public Handshake_Message std::set<Handshake_Extension_Type> extension_types() const { return m_extensions.extension_types(); } + bool prefers_compressed_ec_points() const + { + if(auto ecc_formats = m_extensions.get<Supported_Point_Formats>()) + { + return ecc_formats->prefers_compressed(); + } + return false; + } + Server_Hello(Handshake_IO& io, Handshake_Hash& hash, const Policy& policy, diff --git a/src/lib/tls/tls_policy.cpp b/src/lib/tls/tls_policy.cpp index 592d4f572..9646aa320 100644 --- a/src/lib/tls/tls_policy.cpp +++ b/src/lib/tls/tls_policy.cpp @@ -104,6 +104,11 @@ bool Policy::allowed_ecc_curve(const std::string& curve) const return value_exists(allowed_ecc_curves(), curve); } +bool Policy::use_ecc_point_compression() const + { + return false; + } + /* * Choose an ECC curve to use */ diff --git a/src/lib/tls/tls_policy.h b/src/lib/tls/tls_policy.h index 76e80ddde..47ac51685 100644 --- a/src/lib/tls/tls_policy.h +++ b/src/lib/tls/tls_policy.h @@ -67,6 +67,11 @@ class BOTAN_DLL Policy bool allowed_ecc_curve(const std::string& curve) const; /** + * Request that ECC curve points are sent compressed + */ + virtual bool use_ecc_point_compression() const; + + /** * Returns a list of compression algorithms we are willing to use, * in order of preference. Allowed values any value of * Compression_Method. @@ -348,6 +353,9 @@ class BOTAN_DLL Text_Policy : public Policy std::vector<std::string> allowed_ecc_curves() const override { return get_list("ecc_curves", Policy::allowed_ecc_curves()); } + bool use_ecc_point_compression() const override + { return get_bool("use_ecc_point_compression", Policy::use_ecc_point_compression()); } + bool allow_tls10() const override { return get_bool("allow_tls10", Policy::allow_tls10()); } |