/src/boringssl/ssl/handoff.cc
Line | Count | Source |
1 | | // Copyright 2018 The BoringSSL Authors |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // https://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | #include <openssl/ssl.h> |
16 | | |
17 | | #include <openssl/bytestring.h> |
18 | | #include <openssl/err.h> |
19 | | |
20 | | #include <algorithm> |
21 | | #include <optional> |
22 | | |
23 | | #include "../crypto/internal.h" |
24 | | #include "internal.h" |
25 | | |
26 | | |
27 | | BSSL_NAMESPACE_BEGIN |
28 | | |
29 | | static const CBS_ASN1_TAG kFeatureTagALPS = CBS_ASN1_CONTEXT_SPECIFIC | 0; |
30 | | |
31 | | // early_data_t represents the state of early data in a more compact way than |
32 | | // the 3 bits used by the implementation. |
33 | | enum early_data_t { |
34 | | early_data_not_offered = 0, |
35 | | early_data_accepted = 1, |
36 | | early_data_rejected_hrr = 2, |
37 | | early_data_skipped = 3, |
38 | | |
39 | | early_data_max_value = early_data_skipped, |
40 | | }; |
41 | | |
42 | | // serialize_features adds a description of features supported by this binary to |
43 | | // `out`. Returns true on success and false on error. |
44 | 0 | static bool serialize_features(CBB *out) { |
45 | 0 | CBB ciphers; |
46 | 0 | if (!CBB_add_asn1(out, &ciphers, CBS_ASN1_OCTETSTRING)) { |
47 | 0 | return false; |
48 | 0 | } |
49 | 0 | Span<const SSL_CIPHER> all_ciphers = AllCiphers(); |
50 | 0 | for (const SSL_CIPHER &cipher : all_ciphers) { |
51 | 0 | if (!CBB_add_u16(&ciphers, cipher.protocol_id)) { |
52 | 0 | return false; |
53 | 0 | } |
54 | 0 | } |
55 | 0 | CBB groups; |
56 | 0 | if (!CBB_add_asn1(out, &groups, CBS_ASN1_OCTETSTRING)) { |
57 | 0 | return false; |
58 | 0 | } |
59 | 0 | for (const NamedGroup &g : NamedGroups()) { |
60 | 0 | if (!CBB_add_u16(&groups, g.group_id)) { |
61 | 0 | return false; |
62 | 0 | } |
63 | 0 | } |
64 | | // ALPS is a draft protocol and may change over time. The features structure |
65 | | // contains a [0] IMPLICIT OCTET STRING OPTIONAL, containing a list of u16 |
66 | | // ALPS versions that the binary supports. For now we name them by codepoint. |
67 | | // Once ALPS is finalized and past the support horizon, this field can be |
68 | | // removed. |
69 | 0 | CBB alps; |
70 | 0 | if (!CBB_add_asn1(out, &alps, kFeatureTagALPS) || |
71 | 0 | !CBB_add_u16(&alps, TLSEXT_TYPE_application_settings_old) || |
72 | 0 | !CBB_add_u16(&alps, TLSEXT_TYPE_application_settings)) { |
73 | 0 | return false; |
74 | 0 | } |
75 | 0 | return CBB_flush(out); |
76 | 0 | } |
77 | | |
78 | | // apply_remote_features reads a list of supported features from `in` and |
79 | | // (possibly) reconfigures `ssl` to disallow the negotiation of features whose |
80 | | // support has not been indicated. (This prevents the hints from being generated |
81 | | // based on features that are not supported on the actual server.) |
82 | 0 | static bool apply_remote_features(SSLImpl *ssl, CBS *in) { |
83 | 0 | CBS ciphers; |
84 | 0 | if (!CBS_get_asn1(in, &ciphers, CBS_ASN1_OCTETSTRING)) { |
85 | 0 | return false; |
86 | 0 | } |
87 | 0 | bssl::UniquePtr<STACK_OF(SSL_CIPHER)> supported(sk_SSL_CIPHER_new_null()); |
88 | 0 | if (!supported) { |
89 | 0 | return false; |
90 | 0 | } |
91 | 0 | while (CBS_len(&ciphers)) { |
92 | 0 | uint16_t id; |
93 | 0 | if (!CBS_get_u16(&ciphers, &id)) { |
94 | 0 | return false; |
95 | 0 | } |
96 | 0 | const SSL_CIPHER *cipher = SSL_get_cipher_by_value(id); |
97 | 0 | if (!cipher) { |
98 | 0 | continue; |
99 | 0 | } |
100 | 0 | if (!sk_SSL_CIPHER_push(supported.get(), cipher)) { |
101 | 0 | return false; |
102 | 0 | } |
103 | 0 | } |
104 | 0 | const STACK_OF(SSL_CIPHER) *configured = |
105 | 0 | ssl->config->cipher_list ? ssl->config->cipher_list->ciphers() |
106 | 0 | : ssl->ctx->cipher_list->ciphers(); |
107 | 0 | bssl::UniquePtr<STACK_OF(SSL_CIPHER)> unsupported(sk_SSL_CIPHER_new_null()); |
108 | 0 | if (!unsupported) { |
109 | 0 | return false; |
110 | 0 | } |
111 | 0 | for (const SSL_CIPHER *configured_cipher : configured) { |
112 | 0 | if (sk_SSL_CIPHER_find(supported.get(), nullptr, configured_cipher)) { |
113 | 0 | continue; |
114 | 0 | } |
115 | 0 | if (!sk_SSL_CIPHER_push(unsupported.get(), configured_cipher)) { |
116 | 0 | return false; |
117 | 0 | } |
118 | 0 | } |
119 | 0 | if (sk_SSL_CIPHER_num(unsupported.get()) && !ssl->config->cipher_list) { |
120 | 0 | ssl->config->cipher_list = bssl::MakeUnique<SSLCipherPreferenceList>(); |
121 | 0 | if (!ssl->config->cipher_list || |
122 | 0 | !ssl->config->cipher_list->CopyFrom(*ssl->ctx->cipher_list)) { |
123 | 0 | return false; |
124 | 0 | } |
125 | 0 | } |
126 | 0 | for (const SSL_CIPHER *unsupported_cipher : unsupported.get()) { |
127 | 0 | ssl->config->cipher_list->Remove(unsupported_cipher); |
128 | 0 | } |
129 | 0 | if (sk_SSL_CIPHER_num(SSL_get_ciphers(ssl)) == 0) { |
130 | 0 | return false; |
131 | 0 | } |
132 | | |
133 | 0 | CBS groups; |
134 | 0 | if (!CBS_get_asn1(in, &groups, CBS_ASN1_OCTETSTRING)) { |
135 | 0 | return false; |
136 | 0 | } |
137 | 0 | Array<uint16_t> supported_groups; |
138 | 0 | if (!supported_groups.InitForOverwrite(CBS_len(&groups) / 2)) { |
139 | 0 | return false; |
140 | 0 | } |
141 | 0 | size_t idx = 0; |
142 | 0 | while (CBS_len(&groups)) { |
143 | 0 | uint16_t group; |
144 | 0 | if (!CBS_get_u16(&groups, &group)) { |
145 | 0 | return false; |
146 | 0 | } |
147 | 0 | supported_groups[idx++] = group; |
148 | 0 | } |
149 | 0 | Span<const uint16_t> configured_groups = |
150 | 0 | ssl->s3->hs->config->supported_group_list; |
151 | 0 | Span<const uint32_t> configured_groups_flags = |
152 | 0 | ssl->s3->hs->config->supported_group_list_flags; |
153 | 0 | Array<uint16_t> new_configured_groups; |
154 | | // Temporary scratch space to keep track of consecutive runs of groups of |
155 | | // equal preference, so they can be relabeled after filtering for groups |
156 | | // present in the remote features and copying to the new configuration. |
157 | 0 | Array<size_t> new_groups_preference_ranks; |
158 | 0 | Array<uint32_t> new_groups_flags; |
159 | 0 | if (!new_configured_groups.InitForOverwrite(configured_groups.size()) || |
160 | 0 | !new_groups_preference_ranks.Init(configured_groups.size()) || |
161 | 0 | !new_groups_flags.Init(configured_groups.size())) { |
162 | 0 | return false; |
163 | 0 | } |
164 | | // Populate temporary array containing "preference rank" of each group. |
165 | 0 | for (size_t i = 1; i < configured_groups.size(); ++i) { |
166 | 0 | new_groups_preference_ranks[i] = new_groups_preference_ranks[i - 1]; |
167 | 0 | if ((configured_groups_flags[i - 1] & |
168 | 0 | SSL_GROUP_FLAG_EQUAL_PREFERENCE_WITH_NEXT) == 0) { |
169 | 0 | ++new_groups_preference_ranks[i]; |
170 | 0 | } |
171 | 0 | } |
172 | 0 | idx = 0; |
173 | 0 | std::optional<size_t> last_rank; |
174 | 0 | for (size_t i = 0u; i < configured_groups.size(); ++i) { |
175 | 0 | uint16_t configured_group = configured_groups[i]; |
176 | 0 | if (std::find(supported_groups.begin(), supported_groups.end(), |
177 | 0 | configured_group) == supported_groups.end()) { |
178 | 0 | continue; |
179 | 0 | } |
180 | 0 | new_configured_groups[idx] = configured_group; |
181 | | // Set the "equal preference with next" flag on the previous group, if |
182 | | // appropriate. |
183 | 0 | if (last_rank.has_value() && new_groups_preference_ranks[i] == *last_rank) { |
184 | 0 | new_groups_flags[idx - 1] |= SSL_GROUP_FLAG_EQUAL_PREFERENCE_WITH_NEXT; |
185 | 0 | } |
186 | 0 | last_rank = new_groups_preference_ranks[i]; |
187 | 0 | ++idx; |
188 | 0 | } |
189 | 0 | if (idx == 0) { |
190 | 0 | return false; |
191 | 0 | } |
192 | 0 | new_configured_groups.Shrink(idx); |
193 | 0 | new_groups_flags.Shrink(idx); |
194 | 0 | ssl->config->supported_group_list = std::move(new_configured_groups); |
195 | 0 | ssl->config->supported_group_list_flags = std::move(new_groups_flags); |
196 | |
|
197 | 0 | CBS alps; |
198 | 0 | CBS_init(&alps, nullptr, 0); |
199 | 0 | if (!CBS_get_optional_asn1(in, &alps, /*out_present=*/nullptr, |
200 | 0 | kFeatureTagALPS)) { |
201 | 0 | return false; |
202 | 0 | } |
203 | 0 | bool supports_alps = false; |
204 | 0 | while (CBS_len(&alps) != 0) { |
205 | 0 | uint16_t id; |
206 | 0 | if (!CBS_get_u16(&alps, &id)) { |
207 | 0 | return false; |
208 | 0 | } |
209 | | // For now, we support two ALPS codepoints, so we need to extract both |
210 | | // codepoints, and then filter what the handshaker might try to send. |
211 | 0 | if ((id == TLSEXT_TYPE_application_settings && |
212 | 0 | ssl->config->alps_use_new_codepoint) || |
213 | 0 | (id == TLSEXT_TYPE_application_settings_old && |
214 | 0 | !ssl->config->alps_use_new_codepoint)) { |
215 | 0 | supports_alps = true; |
216 | 0 | break; |
217 | 0 | } |
218 | 0 | } |
219 | 0 | if (!supports_alps) { |
220 | 0 | ssl->config->alps_configs.clear(); |
221 | 0 | } |
222 | |
|
223 | 0 | return true; |
224 | 0 | } |
225 | | |
226 | | BSSL_NAMESPACE_END |
227 | | |
228 | | using namespace bssl; |
229 | | |
230 | 0 | int SSL_serialize_capabilities(const SSL *ssl, CBB *out) { |
231 | 0 | CBB seq; |
232 | 0 | if (!CBB_add_asn1(out, &seq, CBS_ASN1_SEQUENCE) || |
233 | 0 | !serialize_features(&seq) || // |
234 | 0 | !CBB_flush(out)) { |
235 | 0 | return 0; |
236 | 0 | } |
237 | | |
238 | 0 | return 1; |
239 | 0 | } |
240 | | |
241 | | int SSL_request_handshake_hints(SSL *ssl, const uint8_t *client_hello, |
242 | | size_t client_hello_len, |
243 | | const uint8_t *capabilities, |
244 | 0 | size_t capabilities_len) { |
245 | 0 | auto *ssl_impl = FromOpaque(ssl); |
246 | 0 | if (SSL_is_dtls(ssl_impl) || ssl_impl->s3->hs == nullptr) { |
247 | 0 | OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); |
248 | 0 | return 0; |
249 | 0 | } |
250 | | |
251 | 0 | CBS cbs, seq; |
252 | 0 | CBS_init(&cbs, capabilities, capabilities_len); |
253 | 0 | UniquePtr<SSL_HANDSHAKE_HINTS> pending_hints = |
254 | 0 | MakeUnique<SSL_HANDSHAKE_HINTS>(); |
255 | 0 | if (pending_hints == nullptr || |
256 | 0 | !CBS_get_asn1(&cbs, &seq, CBS_ASN1_SEQUENCE) || |
257 | 0 | !apply_remote_features(ssl_impl, &seq)) { |
258 | 0 | return 0; |
259 | 0 | } |
260 | | |
261 | 0 | SSL3_STATE *const s3 = ssl_impl->s3; |
262 | 0 | s3->v2_hello_done = true; |
263 | 0 | s3->has_message = true; |
264 | |
|
265 | 0 | Array<uint8_t> client_hello_msg; |
266 | 0 | ScopedCBB client_hello_cbb; |
267 | 0 | CBB client_hello_body; |
268 | 0 | if (!ssl_impl->method->init_message(ssl_impl, client_hello_cbb.get(), |
269 | 0 | &client_hello_body, |
270 | 0 | SSL3_MT_CLIENT_HELLO) || |
271 | 0 | !CBB_add_bytes(&client_hello_body, client_hello, client_hello_len) || |
272 | 0 | !ssl_impl->method->finish_message(ssl_impl, client_hello_cbb.get(), |
273 | 0 | &client_hello_msg)) { |
274 | 0 | return 0; |
275 | 0 | } |
276 | | |
277 | 0 | s3->hs_buf.reset(BUF_MEM_new()); |
278 | 0 | if (!s3->hs_buf || !BUF_MEM_append(s3->hs_buf.get(), client_hello_msg.data(), |
279 | 0 | client_hello_msg.size())) { |
280 | 0 | return 0; |
281 | 0 | } |
282 | | |
283 | 0 | s3->hs->pending_hints = std::move(pending_hints); |
284 | 0 | return 1; |
285 | 0 | } |
286 | | |
287 | | // `SSL_HANDSHAKE_HINTS` is serialized as the following ASN.1 structure. We use |
288 | | // implicit tagging to make it a little more compact. |
289 | | // |
290 | | // HandshakeHints ::= SEQUENCE { |
291 | | // serverRandomTLS13 [0] IMPLICIT OCTET STRING OPTIONAL, |
292 | | // keyShareHint [1] IMPLICIT KeyShareHint OPTIONAL, |
293 | | // signatureHint [2] IMPLICIT SignatureHint OPTIONAL, |
294 | | // -- At most one of decryptedPSKHint or ignorePSKHint may be present. It |
295 | | // -- corresponds to the first entry in pre_shared_keys. TLS 1.2 session |
296 | | // -- tickets use a separate hint, to ensure the caller does not apply the |
297 | | // -- hint to the wrong field. |
298 | | // decryptedPSKHint [3] IMPLICIT OCTET STRING OPTIONAL, |
299 | | // ignorePSKHint [4] IMPLICIT NULL OPTIONAL, |
300 | | // -- Due to a historical typo, compressCertificateHint's tag is primitive |
301 | | // -- instead of constructed. |
302 | | // compressCertificateHint [5 PRIMITIVE] IMPLICIT CompressCertificateHint |
303 | | // OPTIONAL, |
304 | | // -- TLS 1.2 and 1.3 use different server random hints because one contains |
305 | | // -- a timestamp while the other doesn't. If the hint was generated |
306 | | // -- assuming TLS 1.3 but we actually negotiate TLS 1.2, mixing the two |
307 | | // -- will break this. |
308 | | // serverRandomTLS12 [6] IMPLICIT OCTET STRING OPTIONAL, |
309 | | // -- Due to a historical typo, ecdheHint tag has universal class instead of |
310 | | // -- context-specific. |
311 | | // ecdheHint [UNIVERSAL 7] IMPLICIT ECDHEHint OPTIONAL |
312 | | // -- At most one of decryptedTicketHint or ignoreTicketHint may be present. |
313 | | // -- renewTicketHint requires decryptedTicketHint. |
314 | | // decryptedTicketHint [8] IMPLICIT OCTET STRING OPTIONAL, |
315 | | // renewTicketHint [9] IMPLICIT NULL OPTIONAL, |
316 | | // ignoreTicketHint [10] IMPLICIT NULL OPTIONAL, |
317 | | // -- Unlike a usual ASN.1 structure, trailing data is ignored. |
318 | | // } |
319 | | // |
320 | | // KeyShareHint ::= SEQUENCE { |
321 | | // groupId INTEGER, |
322 | | // ciphertext OCTET STRING, |
323 | | // secret OCTET STRING, |
324 | | // } |
325 | | // |
326 | | // SignatureHint ::= SEQUENCE { |
327 | | // algorithm INTEGER, |
328 | | // input OCTET STRING, |
329 | | // subjectPublicKeyInfo OCTET STRING, |
330 | | // signature OCTET STRING, |
331 | | // } |
332 | | // |
333 | | // CompressCertificateHint ::= SEQUENCE { |
334 | | // algorithm INTEGER, |
335 | | // input OCTET STRING, |
336 | | // compressed OCTET STRING, |
337 | | // } |
338 | | // |
339 | | // ECDHEHint ::= SEQUENCE { |
340 | | // groupId INTEGER, |
341 | | // publicKey OCTET STRING, |
342 | | // privateKey OCTET STRING, |
343 | | // } |
344 | | |
345 | | // HandshakeHints tags. |
346 | | static const CBS_ASN1_TAG kServerRandomTLS13Tag = CBS_ASN1_CONTEXT_SPECIFIC | 0; |
347 | | static const CBS_ASN1_TAG kKeyShareHintTag = |
348 | | CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 1; |
349 | | static const CBS_ASN1_TAG kSignatureHintTag = |
350 | | CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 2; |
351 | | static const CBS_ASN1_TAG kDecryptedPSKTag = CBS_ASN1_CONTEXT_SPECIFIC | 3; |
352 | | static const CBS_ASN1_TAG kIgnorePSKTag = CBS_ASN1_CONTEXT_SPECIFIC | 4; |
353 | | static const CBS_ASN1_TAG kCompressCertificateTag = |
354 | | CBS_ASN1_CONTEXT_SPECIFIC | 5; |
355 | | static const CBS_ASN1_TAG kServerRandomTLS12Tag = CBS_ASN1_CONTEXT_SPECIFIC | 6; |
356 | | static const CBS_ASN1_TAG kECDHEHintTag = CBS_ASN1_CONSTRUCTED | 7; |
357 | | static const CBS_ASN1_TAG kDecryptedTicketTag = CBS_ASN1_CONTEXT_SPECIFIC | 8; |
358 | | static const CBS_ASN1_TAG kRenewTicketTag = CBS_ASN1_CONTEXT_SPECIFIC | 9; |
359 | | static const CBS_ASN1_TAG kIgnoreTicketTag = CBS_ASN1_CONTEXT_SPECIFIC | 10; |
360 | | |
361 | 0 | int SSL_serialize_handshake_hints(const SSL *ssl, CBB *out) { |
362 | 0 | const auto *ssl_impl = FromOpaque(ssl); |
363 | 0 | const SSL_HANDSHAKE *hs = ssl_impl->s3->hs.get(); |
364 | 0 | if (!ssl_impl->server || hs == nullptr || hs->pending_hints == nullptr) { |
365 | 0 | OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); |
366 | 0 | return 0; |
367 | 0 | } |
368 | | |
369 | 0 | const SSL_HANDSHAKE_HINTS *const hints = hs->pending_hints.get(); |
370 | 0 | CBB seq, child; |
371 | 0 | if (!CBB_add_asn1(out, &seq, CBS_ASN1_SEQUENCE)) { |
372 | 0 | return 0; |
373 | 0 | } |
374 | | |
375 | 0 | if (!hints->server_random_tls13.empty()) { |
376 | 0 | if (!CBB_add_asn1_element(&seq, kServerRandomTLS13Tag, |
377 | 0 | hints->server_random_tls13.data(), |
378 | 0 | hints->server_random_tls13.size())) { |
379 | 0 | return 0; |
380 | 0 | } |
381 | 0 | } |
382 | | |
383 | 0 | if (hints->key_share_group_id != 0 && !hints->key_share_ciphertext.empty() && |
384 | 0 | !hints->key_share_secret.empty()) { |
385 | 0 | if (!CBB_add_asn1(&seq, &child, kKeyShareHintTag) || |
386 | 0 | !CBB_add_asn1_uint64(&child, hints->key_share_group_id) || |
387 | 0 | !CBB_add_asn1_octet_string(&child, hints->key_share_ciphertext.data(), |
388 | 0 | hints->key_share_ciphertext.size()) || |
389 | 0 | !CBB_add_asn1_octet_string(&child, hints->key_share_secret.data(), |
390 | 0 | hints->key_share_secret.size())) { |
391 | 0 | return 0; |
392 | 0 | } |
393 | 0 | } |
394 | | |
395 | 0 | if (hints->signature_algorithm != 0 && !hints->signature_input.empty() && |
396 | 0 | !hints->signature.empty()) { |
397 | 0 | if (!CBB_add_asn1(&seq, &child, kSignatureHintTag) || |
398 | 0 | !CBB_add_asn1_uint64(&child, hints->signature_algorithm) || |
399 | 0 | !CBB_add_asn1_octet_string(&child, hints->signature_input.data(), |
400 | 0 | hints->signature_input.size()) || |
401 | 0 | !CBB_add_asn1_octet_string(&child, hints->signature_spki.data(), |
402 | 0 | hints->signature_spki.size()) || |
403 | 0 | !CBB_add_asn1_octet_string(&child, hints->signature.data(), |
404 | 0 | hints->signature.size())) { |
405 | 0 | return 0; |
406 | 0 | } |
407 | 0 | } |
408 | | |
409 | 0 | if (!hints->decrypted_psk.empty()) { |
410 | 0 | if (!CBB_add_asn1_element(&seq, kDecryptedPSKTag, |
411 | 0 | hints->decrypted_psk.data(), |
412 | 0 | hints->decrypted_psk.size())) { |
413 | 0 | return 0; |
414 | 0 | } |
415 | 0 | } |
416 | | |
417 | 0 | if (hints->ignore_psk && // |
418 | 0 | !CBB_add_asn1(&seq, &child, kIgnorePSKTag)) { |
419 | 0 | return 0; |
420 | 0 | } |
421 | | |
422 | 0 | if (hints->cert_compression_alg_id != 0 && |
423 | 0 | !hints->cert_compression_input.empty() && |
424 | 0 | !hints->cert_compression_output.empty()) { |
425 | 0 | if (!CBB_add_asn1(&seq, &child, kCompressCertificateTag) || |
426 | 0 | !CBB_add_asn1_uint64(&child, hints->cert_compression_alg_id) || |
427 | 0 | !CBB_add_asn1_octet_string(&child, hints->cert_compression_input.data(), |
428 | 0 | hints->cert_compression_input.size()) || |
429 | 0 | !CBB_add_asn1_octet_string(&child, |
430 | 0 | hints->cert_compression_output.data(), |
431 | 0 | hints->cert_compression_output.size())) { |
432 | 0 | return 0; |
433 | 0 | } |
434 | 0 | } |
435 | | |
436 | 0 | if (!hints->server_random_tls12.empty()) { |
437 | 0 | if (!CBB_add_asn1_element(&seq, kServerRandomTLS12Tag, |
438 | 0 | hints->server_random_tls12.data(), |
439 | 0 | hints->server_random_tls12.size())) { |
440 | 0 | return 0; |
441 | 0 | } |
442 | 0 | } |
443 | | |
444 | 0 | if (hints->ecdhe_group_id != 0 && !hints->ecdhe_public_key.empty() && |
445 | 0 | !hints->ecdhe_private_key.empty()) { |
446 | 0 | if (!CBB_add_asn1(&seq, &child, kECDHEHintTag) || |
447 | 0 | !CBB_add_asn1_uint64(&child, hints->ecdhe_group_id) || |
448 | 0 | !CBB_add_asn1_octet_string(&child, hints->ecdhe_public_key.data(), |
449 | 0 | hints->ecdhe_public_key.size()) || |
450 | 0 | !CBB_add_asn1_octet_string(&child, hints->ecdhe_private_key.data(), |
451 | 0 | hints->ecdhe_private_key.size())) { |
452 | 0 | return 0; |
453 | 0 | } |
454 | 0 | } |
455 | | |
456 | | |
457 | 0 | if (!hints->decrypted_ticket.empty()) { |
458 | 0 | if (!CBB_add_asn1_element(&seq, kDecryptedTicketTag, |
459 | 0 | hints->decrypted_ticket.data(), |
460 | 0 | hints->decrypted_ticket.size())) { |
461 | 0 | return 0; |
462 | 0 | } |
463 | 0 | } |
464 | | |
465 | 0 | if (hints->renew_ticket && // |
466 | 0 | !CBB_add_asn1(&seq, &child, kRenewTicketTag)) { |
467 | 0 | return 0; |
468 | 0 | } |
469 | | |
470 | 0 | if (hints->ignore_ticket && // |
471 | 0 | !CBB_add_asn1(&seq, &child, kIgnoreTicketTag)) { |
472 | 0 | return 0; |
473 | 0 | } |
474 | | |
475 | 0 | return CBB_flush(out); |
476 | 0 | } |
477 | | |
478 | | static bool get_optional_implicit_null(CBS *cbs, bool *out_present, |
479 | 153k | CBS_ASN1_TAG tag) { |
480 | 153k | CBS value; |
481 | 153k | int present; |
482 | 153k | if (!CBS_get_optional_asn1(cbs, &value, &present, tag) || |
483 | 151k | (present && CBS_len(&value) != 0)) { |
484 | 3.16k | return false; |
485 | 3.16k | } |
486 | 150k | *out_present = present; |
487 | 150k | return true; |
488 | 153k | } |
489 | | |
490 | 78.5k | int SSL_set_handshake_hints(SSL *ssl, const uint8_t *hints, size_t hints_len) { |
491 | 78.5k | auto *ssl_impl = FromOpaque(ssl); |
492 | 78.5k | if (SSL_is_dtls(ssl_impl) || ssl_impl->s3->hs == nullptr) { |
493 | 1.10k | OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); |
494 | 1.10k | return 0; |
495 | 1.10k | } |
496 | | |
497 | 77.4k | UniquePtr<SSL_HANDSHAKE_HINTS> hints_obj = MakeUnique<SSL_HANDSHAKE_HINTS>(); |
498 | 77.4k | if (hints_obj == nullptr) { |
499 | 0 | return 0; |
500 | 0 | } |
501 | | |
502 | 77.4k | CBS cbs, seq, server_random_tls13, key_share, signature_hint, psk, |
503 | 77.4k | cert_compression, server_random_tls12, ecdhe, ticket; |
504 | 77.4k | int has_server_random_tls13, has_key_share, has_signature_hint, has_psk, |
505 | 77.4k | has_cert_compression, has_server_random_tls12, has_ecdhe, has_ticket; |
506 | 77.4k | CBS_init(&cbs, hints, hints_len); |
507 | 77.4k | if (!CBS_get_asn1(&cbs, &seq, CBS_ASN1_SEQUENCE) || |
508 | 58.3k | !CBS_get_optional_asn1(&seq, &server_random_tls13, |
509 | 58.3k | &has_server_random_tls13, kServerRandomTLS13Tag) || |
510 | 57.5k | !CBS_get_optional_asn1(&seq, &key_share, &has_key_share, |
511 | 57.5k | kKeyShareHintTag) || |
512 | 56.6k | !CBS_get_optional_asn1(&seq, &signature_hint, &has_signature_hint, |
513 | 56.6k | kSignatureHintTag) || |
514 | 55.6k | !CBS_get_optional_asn1(&seq, &psk, &has_psk, kDecryptedPSKTag) || |
515 | 54.7k | !get_optional_implicit_null(&seq, &hints_obj->ignore_psk, |
516 | 54.7k | kIgnorePSKTag) || |
517 | 53.4k | !CBS_get_optional_asn1(&seq, &cert_compression, &has_cert_compression, |
518 | 53.4k | kCompressCertificateTag) || |
519 | 52.5k | !CBS_get_optional_asn1(&seq, &server_random_tls12, |
520 | 52.5k | &has_server_random_tls12, kServerRandomTLS12Tag) || |
521 | 51.7k | !CBS_get_optional_asn1(&seq, &ecdhe, &has_ecdhe, kECDHEHintTag) || |
522 | 50.8k | !CBS_get_optional_asn1(&seq, &ticket, &has_ticket, kDecryptedTicketTag) || |
523 | 49.9k | !get_optional_implicit_null(&seq, &hints_obj->renew_ticket, |
524 | 49.9k | kRenewTicketTag) || |
525 | 49.1k | !get_optional_implicit_null(&seq, &hints_obj->ignore_ticket, |
526 | 49.1k | kIgnoreTicketTag)) { |
527 | 29.3k | OPENSSL_PUT_ERROR(SSL, SSL_R_COULD_NOT_PARSE_HINTS); |
528 | 29.3k | return 0; |
529 | 29.3k | } |
530 | | |
531 | 48.1k | if (has_server_random_tls13 && |
532 | 1.83k | !hints_obj->server_random_tls13.CopyFrom(server_random_tls13)) { |
533 | 0 | return 0; |
534 | 0 | } |
535 | | |
536 | 48.1k | if (has_key_share) { |
537 | 7.10k | uint64_t group_id; |
538 | 7.10k | CBS ciphertext, secret; |
539 | 7.10k | if (!CBS_get_asn1_uint64(&key_share, &group_id) || // |
540 | 5.20k | group_id == 0 || group_id > 0xffff || |
541 | 3.29k | !CBS_get_asn1(&key_share, &ciphertext, CBS_ASN1_OCTETSTRING) || |
542 | 2.22k | !hints_obj->key_share_ciphertext.CopyFrom(ciphertext) || |
543 | 2.22k | !CBS_get_asn1(&key_share, &secret, CBS_ASN1_OCTETSTRING) || |
544 | 5.99k | !hints_obj->key_share_secret.CopyFrom(secret)) { |
545 | 5.99k | OPENSSL_PUT_ERROR(SSL, SSL_R_COULD_NOT_PARSE_HINTS); |
546 | 5.99k | return 0; |
547 | 5.99k | } |
548 | 1.11k | hints_obj->key_share_group_id = static_cast<uint16_t>(group_id); |
549 | 1.11k | } |
550 | | |
551 | 42.1k | if (has_signature_hint) { |
552 | 9.15k | uint64_t sig_alg; |
553 | 9.15k | CBS input, spki, signature; |
554 | 9.15k | if (!CBS_get_asn1_uint64(&signature_hint, &sig_alg) || // |
555 | 7.00k | sig_alg == 0 || sig_alg > 0xffff || |
556 | 4.58k | !CBS_get_asn1(&signature_hint, &input, CBS_ASN1_OCTETSTRING) || |
557 | 3.40k | !hints_obj->signature_input.CopyFrom(input) || |
558 | 3.40k | !CBS_get_asn1(&signature_hint, &spki, CBS_ASN1_OCTETSTRING) || |
559 | 2.39k | !hints_obj->signature_spki.CopyFrom(spki) || |
560 | 2.39k | !CBS_get_asn1(&signature_hint, &signature, CBS_ASN1_OCTETSTRING) || |
561 | 7.69k | !hints_obj->signature.CopyFrom(signature)) { |
562 | 7.69k | OPENSSL_PUT_ERROR(SSL, SSL_R_COULD_NOT_PARSE_HINTS); |
563 | 7.69k | return 0; |
564 | 7.69k | } |
565 | 1.46k | hints_obj->signature_algorithm = static_cast<uint16_t>(sig_alg); |
566 | 1.46k | } |
567 | | |
568 | 34.4k | if (has_psk && !hints_obj->decrypted_psk.CopyFrom(psk)) { |
569 | 0 | return 0; |
570 | 0 | } |
571 | 34.4k | if (has_psk && hints_obj->ignore_psk) { |
572 | 1.40k | OPENSSL_PUT_ERROR(SSL, SSL_R_COULD_NOT_PARSE_HINTS); |
573 | 1.40k | return 0; |
574 | 1.40k | } |
575 | | |
576 | 33.0k | if (has_cert_compression) { |
577 | 11.6k | uint64_t alg; |
578 | 11.6k | CBS input, output; |
579 | 11.6k | if (!CBS_get_asn1_uint64(&cert_compression, &alg) || // |
580 | 8.28k | alg == 0 || alg > 0xffff || |
581 | 5.86k | !CBS_get_asn1(&cert_compression, &input, CBS_ASN1_OCTETSTRING) || |
582 | 4.53k | !hints_obj->cert_compression_input.CopyFrom(input) || |
583 | 4.53k | !CBS_get_asn1(&cert_compression, &output, CBS_ASN1_OCTETSTRING) || |
584 | 8.65k | !hints_obj->cert_compression_output.CopyFrom(output)) { |
585 | 8.65k | OPENSSL_PUT_ERROR(SSL, SSL_R_COULD_NOT_PARSE_HINTS); |
586 | 8.65k | return 0; |
587 | 8.65k | } |
588 | 2.98k | hints_obj->cert_compression_alg_id = static_cast<uint16_t>(alg); |
589 | 2.98k | } |
590 | | |
591 | 24.3k | if (has_server_random_tls12 && |
592 | 2.19k | !hints_obj->server_random_tls12.CopyFrom(server_random_tls12)) { |
593 | 0 | return 0; |
594 | 0 | } |
595 | | |
596 | 24.3k | if (has_ecdhe) { |
597 | 8.92k | uint64_t group_id; |
598 | 8.92k | CBS public_key, private_key; |
599 | 8.92k | if (!CBS_get_asn1_uint64(&ecdhe, &group_id) || // |
600 | 5.91k | group_id == 0 || group_id > 0xffff || |
601 | 4.01k | !CBS_get_asn1(&ecdhe, &public_key, CBS_ASN1_OCTETSTRING) || |
602 | 2.97k | !hints_obj->ecdhe_public_key.CopyFrom(public_key) || |
603 | 2.97k | !CBS_get_asn1(&ecdhe, &private_key, CBS_ASN1_OCTETSTRING) || |
604 | 6.82k | !hints_obj->ecdhe_private_key.CopyFrom(private_key)) { |
605 | 6.82k | OPENSSL_PUT_ERROR(SSL, SSL_R_COULD_NOT_PARSE_HINTS); |
606 | 6.82k | return 0; |
607 | 6.82k | } |
608 | 2.10k | hints_obj->ecdhe_group_id = static_cast<uint16_t>(group_id); |
609 | 2.10k | } |
610 | | |
611 | 17.5k | if (has_ticket && !hints_obj->decrypted_ticket.CopyFrom(ticket)) { |
612 | 0 | return 0; |
613 | 0 | } |
614 | 17.5k | if (has_ticket && hints_obj->ignore_ticket) { |
615 | 979 | OPENSSL_PUT_ERROR(SSL, SSL_R_COULD_NOT_PARSE_HINTS); |
616 | 979 | return 0; |
617 | 979 | } |
618 | 16.5k | if (!has_ticket && hints_obj->renew_ticket) { |
619 | 850 | OPENSSL_PUT_ERROR(SSL, SSL_R_COULD_NOT_PARSE_HINTS); |
620 | 850 | return 0; |
621 | 850 | } |
622 | | |
623 | 15.7k | ssl_impl->s3->hs->provided_hints = std::move(hints_obj); |
624 | 15.7k | return 1; |
625 | 16.5k | } |