Botan 3.12.0
Crypto and TLS for C&
msg_encrypted_extensions.cpp
Go to the documentation of this file.
1/*
2* TLS Hello Request and Client Hello Messages
3* (C) 2022 Jack Lloyd
4* 2022 René Meusel, Hannes Rantzsch - neXenio GmbH
5*
6* Botan is released under the Simplified BSD License (see license.txt)
7*/
8
9#include <botan/tls_messages_13.h>
10
11#include <botan/tls_callbacks.h>
12#include <botan/tls_exceptn.h>
13#include <botan/tls_policy.h>
14#include <botan/internal/stl_util.h>
15#include <botan/internal/tls_reader.h>
16
17namespace Botan::TLS {
18
20 const Policy& policy,
21 Callbacks& cb,
22 bool is_resumption,
23 bool requesting_client_auth) {
24 const auto& exts = client_hello.extensions();
25
26 // NOLINTBEGIN(*-owning-memory)
27
28 // RFC 8446 4.2.7
29 // As of TLS 1.3, servers are permitted to send the "supported_groups"
30 // extension to the client. Clients [...] MAY use the information
31 // learned from a successfully completed handshake to change what groups
32 // they use in their "key_share" extension in subsequent connections.
33 if(exts.has<Supported_Groups>()) {
34 m_extensions.add(new Supported_Groups(policy.key_exchange_groups()));
35 }
36
37 const auto record_size_limit = policy.record_size_limit();
38 const auto max_record_size = MAX_PLAINTEXT_SIZE + 1 /* encrypted content type byte */;
39 if(exts.has<Record_Size_Limit>()) {
40 // RFC 8449 4
41 // Endpoints SHOULD advertise the "record_size_limit" extension, even
42 // if they have no need to limit the size of records. [...] For
43 // servers, this allows clients to know that their limit will be
44 // respected.
45 m_extensions.add(new Record_Size_Limit(record_size_limit.value_or(max_record_size)));
46 } else if(record_size_limit.has_value() && record_size_limit.value() < max_record_size) {
47 // RFC 8449 4
48 // Endpoints SHOULD advertise the "record_size_limit" extension, even if
49 // they have no need to limit the size of records. For clients, this
50 // allows servers to advertise a limit at their discretion.
51 throw TLS_Exception(Alert::MissingExtension,
52 "Server cannot enforce record size limit without the client supporting it");
53 }
54
55 // RFC 7250 4.2
56 // If the TLS server wants to request a certificate from the client
57 // (via the certificate_request message), it MUST include the
58 // client_certificate_type extension in the server hello.
59 // [...]
60 // If the server does not send a certificate_request payload [...],
61 // then the client_certificate_type payload in the server hello MUST be
62 // omitted.
63 //
64 // Note: requesting_client_auth tracks whether the caller will actually
65 // emit a CertificateRequest. The server-side decision in
66 // Certificate_Request_13::maybe_create depends on both the policy flag
67 // *and* the credentials manager's CA list, so re-checking just the
68 // policy flag here would miss the trusted-CAs-only configuration.
69 if(auto* ch_client_cert_types = exts.get<Client_Certificate_Type>();
70 ch_client_cert_types != nullptr && requesting_client_auth) {
71 m_extensions.add(new Client_Certificate_Type(*ch_client_cert_types, policy));
72 }
73
74 // RFC 7250 4.2
75 // The server_certificate_type extension in the client hello indicates the
76 // types of certificates the client is able to process when provided by
77 // the server in a subsequent certificate payload. [...] With the
78 // server_certificate_type extension in the server hello, the TLS server
79 // indicates the certificate type carried in the Certificate payload.
80 if(auto* ch_server_cert_types = exts.get<Server_Certificate_Type>()) {
81 m_extensions.add(new Server_Certificate_Type(*ch_server_cert_types, policy));
82 }
83
84 // RFC 6066 3
85 // A server that receives a client hello containing the "server_name"
86 // extension [...] SHALL include an extension of type "server_name" in the
87 // (extended) server hello. The "extension_data" field of this extension
88 // SHALL be empty.
89 //
90 // When resuming a session, the server MUST NOT include a server_name
91 // extension in the server hello.
92 if(exts.has<Server_Name_Indicator>() && !is_resumption) {
93 m_extensions.add(new Server_Name_Indicator(""));
94 }
95
96 if(auto* alpn_ext = exts.get<Application_Layer_Protocol_Notification>()) {
97 const auto& offered = alpn_ext->protocols();
98 const auto next_protocol = cb.tls_server_choose_app_protocol(offered);
99 if(!next_protocol.empty()) {
100 // RFC 7301 3.2: if a protocol is selected, the server MUST select
101 // one of the protocols advertised by the client.
102 if(!value_exists(offered, next_protocol)) {
103 throw TLS_Exception(Alert::InternalError,
104 "Application chose an ALPN protocol that the client did not offer");
105 }
106 m_extensions.add(new Application_Layer_Protocol_Notification(next_protocol));
107 }
108 }
109
110 // NOLINTEND(*-owning-memory)
111
112 // TODO: Implement handling for (at least)
113 // * SRTP
114
116
117 // After the application's tls_modify_extensions callback runs, re-check the
118 // RFC-MUST invariants we just established above. The application can add or
119 // reorder extensions, but shouldn't remove ones required direct response to
120 // ClientHello extensions would put us out of spec.
121 if(exts.has<Server_Certificate_Type>() && !m_extensions.has<Server_Certificate_Type>()) {
122 throw TLS_Exception(
123 Alert::InternalError,
124 "Application tls_modify_extensions callback removed Server_Certificate_Type from EncryptedExtensions");
125 }
126
127 if(requesting_client_auth && exts.has<Client_Certificate_Type>() && !m_extensions.has<Client_Certificate_Type>()) {
128 throw TLS_Exception(
129 Alert::InternalError,
130 "Application tls_modify_extensions callback removed Client_Certificate_Type from EncryptedExtensions");
131 }
132}
133
134Encrypted_Extensions::Encrypted_Extensions(const std::vector<uint8_t>& buf) {
135 TLS_Data_Reader reader("encrypted extensions reader", buf);
136
137 // Encrypted Extensions contains a list of extensions. This list may legally
138 // be empty. However, in that case we should at least see a two-byte length
139 // field that reads 0x00 0x00.
140 if(buf.size() < 2) {
141 throw TLS_Exception(Alert::DecodeError, "Server sent an empty Encrypted Extensions message");
142 }
143
144 m_extensions.deserialize(reader, Connection_Side::Server, type());
145
146 // RFC 8446 4.2
147 // If an implementation receives an extension which it recognizes and
148 // which is not specified for the message in which it appears, it MUST
149 // abort the handshake with an "illegal_parameter" alert.
150 //
151 // Note that we cannot encounter any extensions that we don't recognize here,
152 // since only extensions we previously offered are allowed in EE.
153 const auto allowed_exts = std::set<Extension_Code>{
154 // Allowed extensions listed in RFC 8446 and implemented in Botan
156 // MAX_FRAGMENT_LENGTH
159 // HEARTBEAT
161 // RFC 7250
164 // EARLY_DATA
165
166 // Allowed extensions not listed in RFC 8446 but acceptable as Botan implements them
168 };
169 if(m_extensions.contains_implemented_extensions_other_than(allowed_exts)) {
170 throw TLS_Exception(Alert::IllegalParameter, "Encrypted Extensions contained an extension that is not allowed");
171 }
172
173 reader.assert_done();
174}
175
176std::vector<uint8_t> Encrypted_Extensions::serialize() const {
177 // RFC 8446 4.3.1: EncryptedExtensions carries Extension extensions<0..2^16-1>;
178 // an empty list still requires a 2-byte length-prefix on the wire.
179 // Extensions::serialize collapses empty to {} to suit other contexts, so
180 // emit the explicit length here. Mirrors the same fallback in
181 // New_Session_Ticket_13::serialize.
182 if(m_extensions.empty()) {
183 return {0x00, 0x00};
184 }
185 return m_extensions.serialize(Connection_Side::Server);
186}
187
188} // namespace Botan::TLS
virtual void tls_modify_extensions(Extensions &extn, Connection_Side which_side, Handshake_Type which_message)
virtual std::string tls_server_choose_app_protocol(const std::vector< std::string > &client_protos)
const Extensions & extensions() const
std::vector< uint8_t > serialize() const override
Handshake_Type type() const override
Encrypted_Extensions(const std::vector< uint8_t > &buf)
virtual std::vector< Group_Params > key_exchange_groups() const
virtual std::optional< uint16_t > record_size_limit() const
@ MAX_PLAINTEXT_SIZE
Definition tls_magic.h:31
bool value_exists(const std::vector< T > &vec, const V &val)
Definition stl_util.h:44