1 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
2 | * All rights reserved. |
3 | * |
4 | * This package is an SSL implementation written |
5 | * by Eric Young (eay@cryptsoft.com). |
6 | * The implementation was written so as to conform with Netscapes SSL. |
7 | * |
8 | * This library is free for commercial and non-commercial use as long as |
9 | * the following conditions are aheared to. The following conditions |
10 | * apply to all code found in this distribution, be it the RC4, RSA, |
11 | * lhash, DES, etc., code; not just the SSL code. The SSL documentation |
12 | * included with this distribution is covered by the same copyright terms |
13 | * except that the holder is Tim Hudson (tjh@cryptsoft.com). |
14 | * |
15 | * Copyright remains Eric Young's, and as such any Copyright notices in |
16 | * the code are not to be removed. |
17 | * If this package is used in a product, Eric Young should be given attribution |
18 | * as the author of the parts of the library used. |
19 | * This can be in the form of a textual message at program startup or |
20 | * in documentation (online or textual) provided with the package. |
21 | * |
22 | * Redistribution and use in source and binary forms, with or without |
23 | * modification, are permitted provided that the following conditions |
24 | * are met: |
25 | * 1. Redistributions of source code must retain the copyright |
26 | * notice, this list of conditions and the following disclaimer. |
27 | * 2. Redistributions in binary form must reproduce the above copyright |
28 | * notice, this list of conditions and the following disclaimer in the |
29 | * documentation and/or other materials provided with the distribution. |
30 | * 3. All advertising materials mentioning features or use of this software |
31 | * must display the following acknowledgement: |
32 | * "This product includes cryptographic software written by |
33 | * Eric Young (eay@cryptsoft.com)" |
34 | * The word 'cryptographic' can be left out if the rouines from the library |
35 | * being used are not cryptographic related :-). |
36 | * 4. If you include any Windows specific code (or a derivative thereof) from |
37 | * the apps directory (application code) you must include an acknowledgement: |
38 | * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
39 | * |
40 | * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
41 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
42 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
43 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
44 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
45 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
46 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
47 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
48 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
49 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
50 | * SUCH DAMAGE. |
51 | * |
52 | * The licence and distribution terms for any publically available version or |
53 | * derivative of this code cannot be changed. i.e. this code cannot simply be |
54 | * copied and put under another distribution licence |
55 | * [including the GNU Public Licence.] |
56 | */ |
57 | /* ==================================================================== |
58 | * Copyright 2005 Nokia. All rights reserved. |
59 | * |
60 | * The portions of the attached software ("Contribution") is developed by |
61 | * Nokia Corporation and is licensed pursuant to the OpenSSL open source |
62 | * license. |
63 | * |
64 | * The Contribution, originally written by Mika Kousa and Pasi Eronen of |
65 | * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites |
66 | * support (see RFC 4279) to OpenSSL. |
67 | * |
68 | * No patent licenses or other rights except those expressly stated in |
69 | * the OpenSSL open source license shall be deemed granted or received |
70 | * expressly, by implication, estoppel, or otherwise. |
71 | * |
72 | * No assurances are provided by Nokia that the Contribution does not |
73 | * infringe the patent or other intellectual property rights of any third |
74 | * party or that the license provides you with all the necessary rights |
75 | * to make use of the Contribution. |
76 | * |
77 | * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN |
78 | * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA |
79 | * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY |
80 | * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR |
81 | * OTHERWISE. */ |
82 | |
83 | #include <openssl/ssl.h> |
84 | |
85 | #include <limits.h> |
86 | #include <string.h> |
87 | |
88 | #include <utility> |
89 | |
90 | #include <openssl/buf.h> |
91 | #include <openssl/bytestring.h> |
92 | #include <openssl/err.h> |
93 | #include <openssl/mem.h> |
94 | #include <openssl/x509.h> |
95 | |
96 | #include "../crypto/internal.h" |
97 | #include "internal.h" |
98 | |
99 | |
100 | BSSL_NAMESPACE_BEGIN |
101 | |
102 | // An SSL_SESSION is serialized as the following ASN.1 structure: |
103 | // |
104 | // SSLSession ::= SEQUENCE { |
105 | // version INTEGER (1), -- session structure version |
106 | // sslVersion INTEGER, -- protocol version number |
107 | // cipher OCTET STRING, -- two bytes long |
108 | // sessionID OCTET STRING, |
109 | // masterKey OCTET STRING, |
110 | // time [1] INTEGER, -- seconds since UNIX epoch |
111 | // timeout [2] INTEGER, -- in seconds |
112 | // peer [3] Certificate OPTIONAL, |
113 | // sessionIDContext [4] OCTET STRING OPTIONAL, |
114 | // verifyResult [5] INTEGER OPTIONAL, -- one of X509_V_* codes |
115 | // pskIdentity [8] OCTET STRING OPTIONAL, |
116 | // ticketLifetimeHint [9] INTEGER OPTIONAL, -- client-only |
117 | // ticket [10] OCTET STRING OPTIONAL, -- client-only |
118 | // peerSHA256 [13] OCTET STRING OPTIONAL, |
119 | // originalHandshakeHash [14] OCTET STRING OPTIONAL, |
120 | // signedCertTimestampList [15] OCTET STRING OPTIONAL, |
121 | // -- contents of SCT extension |
122 | // ocspResponse [16] OCTET STRING OPTIONAL, |
123 | // -- stapled OCSP response from the server |
124 | // extendedMasterSecret [17] BOOLEAN OPTIONAL, |
125 | // groupID [18] INTEGER OPTIONAL, |
126 | // certChain [19] SEQUENCE OF Certificate OPTIONAL, |
127 | // ticketAgeAdd [21] OCTET STRING OPTIONAL, |
128 | // isServer [22] BOOLEAN DEFAULT TRUE, |
129 | // peerSignatureAlgorithm [23] INTEGER OPTIONAL, |
130 | // ticketMaxEarlyData [24] INTEGER OPTIONAL, |
131 | // authTimeout [25] INTEGER OPTIONAL, -- defaults to timeout |
132 | // earlyALPN [26] OCTET STRING OPTIONAL, |
133 | // } |
134 | // |
135 | // Note: historically this serialization has included other optional |
136 | // fields. Their presence is currently treated as a parse error, except for |
137 | // hostName, which is ignored. |
138 | // |
139 | // keyArg [0] IMPLICIT OCTET STRING OPTIONAL, |
140 | // hostName [6] OCTET STRING OPTIONAL, |
141 | // pskIdentityHint [7] OCTET STRING OPTIONAL, |
142 | // compressionMethod [11] OCTET STRING OPTIONAL, |
143 | // srpUsername [12] OCTET STRING OPTIONAL, |
144 | // ticketFlags [20] INTEGER OPTIONAL, |
145 | |
146 | static const unsigned kVersion = 1; |
147 | |
148 | static const unsigned kTimeTag = |
149 | CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 1; |
150 | static const unsigned kTimeoutTag = |
151 | CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 2; |
152 | static const unsigned kPeerTag = |
153 | CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 3; |
154 | static const unsigned kSessionIDContextTag = |
155 | CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 4; |
156 | static const unsigned kVerifyResultTag = |
157 | CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 5; |
158 | static const unsigned kHostNameTag = |
159 | CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 6; |
160 | static const unsigned kPSKIdentityTag = |
161 | CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 8; |
162 | static const unsigned kTicketLifetimeHintTag = |
163 | CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 9; |
164 | static const unsigned kTicketTag = |
165 | CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 10; |
166 | static const unsigned kPeerSHA256Tag = |
167 | CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 13; |
168 | static const unsigned kOriginalHandshakeHashTag = |
169 | CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 14; |
170 | static const unsigned kSignedCertTimestampListTag = |
171 | CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 15; |
172 | static const unsigned kOCSPResponseTag = |
173 | CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 16; |
174 | static const unsigned kExtendedMasterSecretTag = |
175 | CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 17; |
176 | static const unsigned kGroupIDTag = |
177 | CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 18; |
178 | static const unsigned kCertChainTag = |
179 | CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 19; |
180 | static const unsigned kTicketAgeAddTag = |
181 | CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 21; |
182 | static const unsigned kIsServerTag = |
183 | CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 22; |
184 | static const unsigned kPeerSignatureAlgorithmTag = |
185 | CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 23; |
186 | static const unsigned kTicketMaxEarlyDataTag = |
187 | CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 24; |
188 | static const unsigned kAuthTimeoutTag = |
189 | CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 25; |
190 | static const unsigned kEarlyALPNTag = |
191 | CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 26; |
192 | |
193 | static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, CBB *cbb, |
194 | int for_ticket) { |
195 | if (in == NULL || in->cipher == NULL) { |
196 | return 0; |
197 | } |
198 | |
199 | CBB session, child, child2; |
200 | if (!CBB_add_asn1(cbb, &session, CBS_ASN1_SEQUENCE) || |
201 | !CBB_add_asn1_uint64(&session, kVersion) || |
202 | !CBB_add_asn1_uint64(&session, in->ssl_version) || |
203 | !CBB_add_asn1(&session, &child, CBS_ASN1_OCTETSTRING) || |
204 | !CBB_add_u16(&child, (uint16_t)(in->cipher->id & 0xffff)) || |
205 | // The session ID is irrelevant for a session ticket. |
206 | !CBB_add_asn1_octet_string(&session, in->session_id, |
207 | for_ticket ? 0 : in->session_id_length) || |
208 | !CBB_add_asn1_octet_string(&session, in->master_key, |
209 | in->master_key_length) || |
210 | !CBB_add_asn1(&session, &child, kTimeTag) || |
211 | !CBB_add_asn1_uint64(&child, in->time) || |
212 | !CBB_add_asn1(&session, &child, kTimeoutTag) || |
213 | !CBB_add_asn1_uint64(&child, in->timeout)) { |
214 | OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); |
215 | return 0; |
216 | } |
217 | |
218 | // The peer certificate is only serialized if the SHA-256 isn't |
219 | // serialized instead. |
220 | if (sk_CRYPTO_BUFFER_num(in->certs.get()) > 0 && !in->peer_sha256_valid) { |
221 | const CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(in->certs.get(), 0); |
222 | if (!CBB_add_asn1(&session, &child, kPeerTag) || |
223 | !CBB_add_bytes(&child, CRYPTO_BUFFER_data(buffer), |
224 | CRYPTO_BUFFER_len(buffer))) { |
225 | OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); |
226 | return 0; |
227 | } |
228 | } |
229 | |
230 | // Although it is OPTIONAL and usually empty, OpenSSL has |
231 | // historically always encoded the sid_ctx. |
232 | if (!CBB_add_asn1(&session, &child, kSessionIDContextTag) || |
233 | !CBB_add_asn1_octet_string(&child, in->sid_ctx, in->sid_ctx_length)) { |
234 | OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); |
235 | return 0; |
236 | } |
237 | |
238 | if (in->verify_result != X509_V_OK) { |
239 | if (!CBB_add_asn1(&session, &child, kVerifyResultTag) || |
240 | !CBB_add_asn1_uint64(&child, in->verify_result)) { |
241 | OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); |
242 | return 0; |
243 | } |
244 | } |
245 | |
246 | if (in->psk_identity) { |
247 | if (!CBB_add_asn1(&session, &child, kPSKIdentityTag) || |
248 | !CBB_add_asn1_octet_string(&child, |
249 | (const uint8_t *)in->psk_identity.get(), |
250 | strlen(in->psk_identity.get()))) { |
251 | OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); |
252 | return 0; |
253 | } |
254 | } |
255 | |
256 | if (in->ticket_lifetime_hint > 0) { |
257 | if (!CBB_add_asn1(&session, &child, kTicketLifetimeHintTag) || |
258 | !CBB_add_asn1_uint64(&child, in->ticket_lifetime_hint)) { |
259 | OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); |
260 | return 0; |
261 | } |
262 | } |
263 | |
264 | if (!in->ticket.empty() && !for_ticket) { |
265 | if (!CBB_add_asn1(&session, &child, kTicketTag) || |
266 | !CBB_add_asn1_octet_string(&child, in->ticket.data(), |
267 | in->ticket.size())) { |
268 | OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); |
269 | return 0; |
270 | } |
271 | } |
272 | |
273 | if (in->peer_sha256_valid) { |
274 | if (!CBB_add_asn1(&session, &child, kPeerSHA256Tag) || |
275 | !CBB_add_asn1_octet_string(&child, in->peer_sha256, |
276 | sizeof(in->peer_sha256))) { |
277 | OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); |
278 | return 0; |
279 | } |
280 | } |
281 | |
282 | if (in->original_handshake_hash_len > 0) { |
283 | if (!CBB_add_asn1(&session, &child, kOriginalHandshakeHashTag) || |
284 | !CBB_add_asn1_octet_string(&child, in->original_handshake_hash, |
285 | in->original_handshake_hash_len)) { |
286 | OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); |
287 | return 0; |
288 | } |
289 | } |
290 | |
291 | if (in->signed_cert_timestamp_list != nullptr) { |
292 | if (!CBB_add_asn1(&session, &child, kSignedCertTimestampListTag) || |
293 | !CBB_add_asn1_octet_string( |
294 | &child, CRYPTO_BUFFER_data(in->signed_cert_timestamp_list.get()), |
295 | CRYPTO_BUFFER_len(in->signed_cert_timestamp_list.get()))) { |
296 | OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); |
297 | return 0; |
298 | } |
299 | } |
300 | |
301 | if (in->ocsp_response != nullptr) { |
302 | if (!CBB_add_asn1(&session, &child, kOCSPResponseTag) || |
303 | !CBB_add_asn1_octet_string( |
304 | &child, CRYPTO_BUFFER_data(in->ocsp_response.get()), |
305 | CRYPTO_BUFFER_len(in->ocsp_response.get()))) { |
306 | OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); |
307 | return 0; |
308 | } |
309 | } |
310 | |
311 | if (in->extended_master_secret) { |
312 | if (!CBB_add_asn1(&session, &child, kExtendedMasterSecretTag) || |
313 | !CBB_add_asn1_bool(&child, true)) { |
314 | OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); |
315 | return 0; |
316 | } |
317 | } |
318 | |
319 | if (in->group_id > 0 && |
320 | (!CBB_add_asn1(&session, &child, kGroupIDTag) || |
321 | !CBB_add_asn1_uint64(&child, in->group_id))) { |
322 | OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); |
323 | return 0; |
324 | } |
325 | |
326 | // The certificate chain is only serialized if the leaf's SHA-256 isn't |
327 | // serialized instead. |
328 | if (in->certs != NULL && |
329 | !in->peer_sha256_valid && |
330 | sk_CRYPTO_BUFFER_num(in->certs.get()) >= 2) { |
331 | if (!CBB_add_asn1(&session, &child, kCertChainTag)) { |
332 | OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); |
333 | return 0; |
334 | } |
335 | for (size_t i = 1; i < sk_CRYPTO_BUFFER_num(in->certs.get()); i++) { |
336 | const CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(in->certs.get(), i); |
337 | if (!CBB_add_bytes(&child, CRYPTO_BUFFER_data(buffer), |
338 | CRYPTO_BUFFER_len(buffer))) { |
339 | OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); |
340 | return 0; |
341 | } |
342 | } |
343 | } |
344 | |
345 | if (in->ticket_age_add_valid) { |
346 | if (!CBB_add_asn1(&session, &child, kTicketAgeAddTag) || |
347 | !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) || |
348 | !CBB_add_u32(&child2, in->ticket_age_add)) { |
349 | OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); |
350 | return 0; |
351 | } |
352 | } |
353 | |
354 | if (!in->is_server) { |
355 | if (!CBB_add_asn1(&session, &child, kIsServerTag) || |
356 | !CBB_add_asn1_bool(&child, false)) { |
357 | OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); |
358 | return 0; |
359 | } |
360 | } |
361 | |
362 | if (in->peer_signature_algorithm != 0 && |
363 | (!CBB_add_asn1(&session, &child, kPeerSignatureAlgorithmTag) || |
364 | !CBB_add_asn1_uint64(&child, in->peer_signature_algorithm))) { |
365 | OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); |
366 | return 0; |
367 | } |
368 | |
369 | if (in->ticket_max_early_data != 0 && |
370 | (!CBB_add_asn1(&session, &child, kTicketMaxEarlyDataTag) || |
371 | !CBB_add_asn1_uint64(&child, in->ticket_max_early_data))) { |
372 | OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); |
373 | return 0; |
374 | } |
375 | |
376 | if (in->timeout != in->auth_timeout && |
377 | (!CBB_add_asn1(&session, &child, kAuthTimeoutTag) || |
378 | !CBB_add_asn1_uint64(&child, in->auth_timeout))) { |
379 | OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); |
380 | return 0; |
381 | } |
382 | |
383 | if (!in->early_alpn.empty()) { |
384 | if (!CBB_add_asn1(&session, &child, kEarlyALPNTag) || |
385 | !CBB_add_asn1_octet_string(&child, in->early_alpn.data(), |
386 | in->early_alpn.size())) { |
387 | OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); |
388 | return 0; |
389 | } |
390 | } |
391 | |
392 | return CBB_flush(cbb); |
393 | } |
394 | |
395 | // SSL_SESSION_parse_string gets an optional ASN.1 OCTET STRING explicitly |
396 | // tagged with |tag| from |cbs| and saves it in |*out|. If the element was not |
397 | // found, it sets |*out| to NULL. It returns one on success, whether or not the |
398 | // element was found, and zero on decode error. |
399 | static int SSL_SESSION_parse_string(CBS *cbs, UniquePtr<char> *out, unsigned tag) { |
400 | CBS value; |
401 | int present; |
402 | if (!CBS_get_optional_asn1_octet_string(cbs, &value, &present, tag)) { |
403 | OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); |
404 | return 0; |
405 | } |
406 | if (present) { |
407 | if (CBS_contains_zero_byte(&value)) { |
408 | OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); |
409 | return 0; |
410 | } |
411 | char *raw = nullptr; |
412 | if (!CBS_strdup(&value, &raw)) { |
413 | OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); |
414 | return 0; |
415 | } |
416 | out->reset(raw); |
417 | } else { |
418 | out->reset(); |
419 | } |
420 | return 1; |
421 | } |
422 | |
423 | // SSL_SESSION_parse_octet_string gets an optional ASN.1 OCTET STRING explicitly |
424 | // tagged with |tag| from |cbs| and stows it in |*out|. It returns one on |
425 | // success, whether or not the element was found, and zero on decode error. |
426 | static bool SSL_SESSION_parse_octet_string(CBS *cbs, Array<uint8_t> *out, |
427 | unsigned tag) { |
428 | CBS value; |
429 | if (!CBS_get_optional_asn1_octet_string(cbs, &value, NULL, tag)) { |
430 | OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); |
431 | return false; |
432 | } |
433 | return out->CopyFrom(value); |
434 | } |
435 | |
436 | static int SSL_SESSION_parse_crypto_buffer(CBS *cbs, |
437 | UniquePtr<CRYPTO_BUFFER> *out, |
438 | unsigned tag, |
439 | CRYPTO_BUFFER_POOL *pool) { |
440 | if (!CBS_peek_asn1_tag(cbs, tag)) { |
441 | return 1; |
442 | } |
443 | |
444 | CBS child, value; |
445 | if (!CBS_get_asn1(cbs, &child, tag) || |
446 | !CBS_get_asn1(&child, &value, CBS_ASN1_OCTETSTRING) || |
447 | CBS_len(&child) != 0) { |
448 | OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); |
449 | return 0; |
450 | } |
451 | out->reset(CRYPTO_BUFFER_new_from_CBS(&value, pool)); |
452 | if (*out == nullptr) { |
453 | OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); |
454 | return 0; |
455 | } |
456 | return 1; |
457 | } |
458 | |
459 | // SSL_SESSION_parse_bounded_octet_string parses an optional ASN.1 OCTET STRING |
460 | // explicitly tagged with |tag| of size at most |max_out|. |
461 | static int SSL_SESSION_parse_bounded_octet_string( |
462 | CBS *cbs, uint8_t *out, uint8_t *out_len, uint8_t max_out, unsigned tag) { |
463 | CBS value; |
464 | if (!CBS_get_optional_asn1_octet_string(cbs, &value, NULL, tag) || |
465 | CBS_len(&value) > max_out) { |
466 | OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); |
467 | return 0; |
468 | } |
469 | OPENSSL_memcpy(out, CBS_data(&value), CBS_len(&value)); |
470 | *out_len = (uint8_t)CBS_len(&value); |
471 | return 1; |
472 | } |
473 | |
474 | static int SSL_SESSION_parse_long(CBS *cbs, long *out, unsigned tag, |
475 | long default_value) { |
476 | uint64_t value; |
477 | if (!CBS_get_optional_asn1_uint64(cbs, &value, tag, |
478 | (uint64_t)default_value) || |
479 | value > LONG_MAX) { |
480 | OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); |
481 | return 0; |
482 | } |
483 | *out = (long)value; |
484 | return 1; |
485 | } |
486 | |
487 | static int SSL_SESSION_parse_u32(CBS *cbs, uint32_t *out, unsigned tag, |
488 | uint32_t default_value) { |
489 | uint64_t value; |
490 | if (!CBS_get_optional_asn1_uint64(cbs, &value, tag, |
491 | (uint64_t)default_value) || |
492 | value > 0xffffffff) { |
493 | OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); |
494 | return 0; |
495 | } |
496 | *out = (uint32_t)value; |
497 | return 1; |
498 | } |
499 | |
500 | static int SSL_SESSION_parse_u16(CBS *cbs, uint16_t *out, unsigned tag, |
501 | uint16_t default_value) { |
502 | uint64_t value; |
503 | if (!CBS_get_optional_asn1_uint64(cbs, &value, tag, |
504 | (uint64_t)default_value) || |
505 | value > 0xffff) { |
506 | OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); |
507 | return 0; |
508 | } |
509 | *out = (uint16_t)value; |
510 | return 1; |
511 | } |
512 | |
513 | UniquePtr<SSL_SESSION> SSL_SESSION_parse(CBS *cbs, |
514 | const SSL_X509_METHOD *x509_method, |
515 | CRYPTO_BUFFER_POOL *pool) { |
516 | UniquePtr<SSL_SESSION> ret = ssl_session_new(x509_method); |
517 | if (!ret) { |
518 | return nullptr; |
519 | } |
520 | |
521 | CBS session; |
522 | uint64_t version, ssl_version; |
523 | uint16_t unused; |
524 | if (!CBS_get_asn1(cbs, &session, CBS_ASN1_SEQUENCE) || |
525 | !CBS_get_asn1_uint64(&session, &version) || |
526 | version != kVersion || |
527 | !CBS_get_asn1_uint64(&session, &ssl_version) || |
528 | // Require sessions have versions valid in either TLS or DTLS. The session |
529 | // will not be used by the handshake if not applicable, but, for |
530 | // simplicity, never parse a session that does not pass |
531 | // |ssl_protocol_version_from_wire|. |
532 | ssl_version > UINT16_MAX || |
533 | !ssl_protocol_version_from_wire(&unused, ssl_version)) { |
534 | OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); |
535 | return nullptr; |
536 | } |
537 | ret->ssl_version = ssl_version; |
538 | |
539 | CBS cipher; |
540 | uint16_t cipher_value; |
541 | if (!CBS_get_asn1(&session, &cipher, CBS_ASN1_OCTETSTRING) || |
542 | !CBS_get_u16(&cipher, &cipher_value) || |
543 | CBS_len(&cipher) != 0) { |
544 | OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); |
545 | return nullptr; |
546 | } |
547 | ret->cipher = SSL_get_cipher_by_value(cipher_value); |
548 | if (ret->cipher == NULL) { |
549 | OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_CIPHER); |
550 | return nullptr; |
551 | } |
552 | |
553 | CBS session_id, master_key; |
554 | if (!CBS_get_asn1(&session, &session_id, CBS_ASN1_OCTETSTRING) || |
555 | CBS_len(&session_id) > SSL3_MAX_SSL_SESSION_ID_LENGTH || |
556 | !CBS_get_asn1(&session, &master_key, CBS_ASN1_OCTETSTRING) || |
557 | CBS_len(&master_key) > SSL_MAX_MASTER_KEY_LENGTH) { |
558 | OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); |
559 | return nullptr; |
560 | } |
561 | OPENSSL_memcpy(ret->session_id, CBS_data(&session_id), CBS_len(&session_id)); |
562 | ret->session_id_length = CBS_len(&session_id); |
563 | OPENSSL_memcpy(ret->master_key, CBS_data(&master_key), CBS_len(&master_key)); |
564 | ret->master_key_length = CBS_len(&master_key); |
565 | |
566 | CBS child; |
567 | uint64_t timeout; |
568 | if (!CBS_get_asn1(&session, &child, kTimeTag) || |
569 | !CBS_get_asn1_uint64(&child, &ret->time) || |
570 | !CBS_get_asn1(&session, &child, kTimeoutTag) || |
571 | !CBS_get_asn1_uint64(&child, &timeout) || |
572 | timeout > UINT32_MAX) { |
573 | OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); |
574 | return nullptr; |
575 | } |
576 | |
577 | ret->timeout = (uint32_t)timeout; |
578 | |
579 | CBS peer; |
580 | int has_peer; |
581 | if (!CBS_get_optional_asn1(&session, &peer, &has_peer, kPeerTag) || |
582 | (has_peer && CBS_len(&peer) == 0)) { |
583 | OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); |
584 | return nullptr; |
585 | } |
586 | // |peer| is processed with the certificate chain. |
587 | |
588 | if (!SSL_SESSION_parse_bounded_octet_string( |
589 | &session, ret->sid_ctx, &ret->sid_ctx_length, sizeof(ret->sid_ctx), |
590 | kSessionIDContextTag) || |
591 | !SSL_SESSION_parse_long(&session, &ret->verify_result, kVerifyResultTag, |
592 | X509_V_OK)) { |
593 | return nullptr; |
594 | } |
595 | |
596 | // Skip the historical hostName field. |
597 | CBS unused_hostname; |
598 | if (!CBS_get_optional_asn1(&session, &unused_hostname, nullptr, |
599 | kHostNameTag)) { |
600 | OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); |
601 | return nullptr; |
602 | } |
603 | |
604 | if (!SSL_SESSION_parse_string(&session, &ret->psk_identity, |
605 | kPSKIdentityTag) || |
606 | !SSL_SESSION_parse_u32(&session, &ret->ticket_lifetime_hint, |
607 | kTicketLifetimeHintTag, 0) || |
608 | !SSL_SESSION_parse_octet_string(&session, &ret->ticket, kTicketTag)) { |
609 | return nullptr; |
610 | } |
611 | |
612 | if (CBS_peek_asn1_tag(&session, kPeerSHA256Tag)) { |
613 | CBS peer_sha256; |
614 | if (!CBS_get_asn1(&session, &child, kPeerSHA256Tag) || |
615 | !CBS_get_asn1(&child, &peer_sha256, CBS_ASN1_OCTETSTRING) || |
616 | CBS_len(&peer_sha256) != sizeof(ret->peer_sha256) || |
617 | CBS_len(&child) != 0) { |
618 | OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); |
619 | return nullptr; |
620 | } |
621 | OPENSSL_memcpy(ret->peer_sha256, CBS_data(&peer_sha256), |
622 | sizeof(ret->peer_sha256)); |
623 | ret->peer_sha256_valid = 1; |
624 | } else { |
625 | ret->peer_sha256_valid = 0; |
626 | } |
627 | |
628 | if (!SSL_SESSION_parse_bounded_octet_string( |
629 | &session, ret->original_handshake_hash, |
630 | &ret->original_handshake_hash_len, |
631 | sizeof(ret->original_handshake_hash), kOriginalHandshakeHashTag) || |
632 | !SSL_SESSION_parse_crypto_buffer(&session, |
633 | &ret->signed_cert_timestamp_list, |
634 | kSignedCertTimestampListTag, pool) || |
635 | !SSL_SESSION_parse_crypto_buffer(&session, &ret->ocsp_response, |
636 | kOCSPResponseTag, pool)) { |
637 | return nullptr; |
638 | } |
639 | |
640 | int extended_master_secret; |
641 | if (!CBS_get_optional_asn1_bool(&session, &extended_master_secret, |
642 | kExtendedMasterSecretTag, |
643 | 0 /* default to false */)) { |
644 | OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); |
645 | return nullptr; |
646 | } |
647 | ret->extended_master_secret = !!extended_master_secret; |
648 | |
649 | if (!SSL_SESSION_parse_u16(&session, &ret->group_id, kGroupIDTag, 0)) { |
650 | OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); |
651 | return nullptr; |
652 | } |
653 | |
654 | CBS cert_chain; |
655 | CBS_init(&cert_chain, NULL, 0); |
656 | int has_cert_chain; |
657 | if (!CBS_get_optional_asn1(&session, &cert_chain, &has_cert_chain, |
658 | kCertChainTag) || |
659 | (has_cert_chain && CBS_len(&cert_chain) == 0)) { |
660 | OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); |
661 | return nullptr; |
662 | } |
663 | if (has_cert_chain && !has_peer) { |
664 | OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); |
665 | return nullptr; |
666 | } |
667 | if (has_peer || has_cert_chain) { |
668 | ret->certs.reset(sk_CRYPTO_BUFFER_new_null()); |
669 | if (ret->certs == nullptr) { |
670 | OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); |
671 | return nullptr; |
672 | } |
673 | |
674 | if (has_peer) { |
675 | UniquePtr<CRYPTO_BUFFER> buffer(CRYPTO_BUFFER_new_from_CBS(&peer, pool)); |
676 | if (!buffer || |
677 | !PushToStack(ret->certs.get(), std::move(buffer))) { |
678 | OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); |
679 | return nullptr; |
680 | } |
681 | } |
682 | |
683 | while (CBS_len(&cert_chain) > 0) { |
684 | CBS cert; |
685 | if (!CBS_get_any_asn1_element(&cert_chain, &cert, NULL, NULL) || |
686 | CBS_len(&cert) == 0) { |
687 | OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); |
688 | return nullptr; |
689 | } |
690 | |
691 | UniquePtr<CRYPTO_BUFFER> buffer(CRYPTO_BUFFER_new_from_CBS(&cert, pool)); |
692 | if (buffer == nullptr || |
693 | !PushToStack(ret->certs.get(), std::move(buffer))) { |
694 | OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); |
695 | return nullptr; |
696 | } |
697 | } |
698 | } |
699 | |
700 | CBS age_add; |
701 | int age_add_present; |
702 | if (!CBS_get_optional_asn1_octet_string(&session, &age_add, &age_add_present, |
703 | kTicketAgeAddTag) || |
704 | (age_add_present && |
705 | !CBS_get_u32(&age_add, &ret->ticket_age_add)) || |
706 | CBS_len(&age_add) != 0) { |
707 | return nullptr; |
708 | } |
709 | ret->ticket_age_add_valid = age_add_present != 0; |
710 | |
711 | int is_server; |
712 | if (!CBS_get_optional_asn1_bool(&session, &is_server, kIsServerTag, |
713 | 1 /* default to true */)) { |
714 | OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); |
715 | return nullptr; |
716 | } |
717 | /* TODO: in time we can include |is_server| for servers too, then we can |
718 | enforce that client and server sessions are never mixed up. */ |
719 | |
720 | ret->is_server = is_server; |
721 | |
722 | if (!SSL_SESSION_parse_u16(&session, &ret->peer_signature_algorithm, |
723 | kPeerSignatureAlgorithmTag, 0) || |
724 | !SSL_SESSION_parse_u32(&session, &ret->ticket_max_early_data, |
725 | kTicketMaxEarlyDataTag, 0) || |
726 | !SSL_SESSION_parse_u32(&session, &ret->auth_timeout, kAuthTimeoutTag, |
727 | ret->timeout) || |
728 | !SSL_SESSION_parse_octet_string(&session, &ret->early_alpn, |
729 | kEarlyALPNTag) || |
730 | CBS_len(&session) != 0) { |
731 | OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); |
732 | return nullptr; |
733 | } |
734 | |
735 | if (!x509_method->session_cache_objects(ret.get())) { |
736 | OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); |
737 | return nullptr; |
738 | } |
739 | |
740 | return ret; |
741 | } |
742 | |
743 | int ssl_session_serialize(const SSL_SESSION *in, CBB *cbb) { |
744 | return SSL_SESSION_to_bytes_full(in, cbb, 0); |
745 | } |
746 | |
747 | BSSL_NAMESPACE_END |
748 | |
749 | using namespace bssl; |
750 | |
751 | int SSL_SESSION_to_bytes(const SSL_SESSION *in, uint8_t **out_data, |
752 | size_t *out_len) { |
753 | if (in->not_resumable) { |
754 | // If the caller has an unresumable session, e.g. if |SSL_get_session| were |
755 | // called on a TLS 1.3 or False Started connection, serialize with a |
756 | // placeholder value so it is not accidentally deserialized into a resumable |
757 | // one. |
758 | static const char kNotResumableSession[] = "NOT RESUMABLE" ; |
759 | |
760 | *out_len = strlen(kNotResumableSession); |
761 | *out_data = (uint8_t *)BUF_memdup(kNotResumableSession, *out_len); |
762 | if (*out_data == NULL) { |
763 | return 0; |
764 | } |
765 | |
766 | return 1; |
767 | } |
768 | |
769 | ScopedCBB cbb; |
770 | if (!CBB_init(cbb.get(), 256) || |
771 | !SSL_SESSION_to_bytes_full(in, cbb.get(), 0) || |
772 | !CBB_finish(cbb.get(), out_data, out_len)) { |
773 | return 0; |
774 | } |
775 | |
776 | return 1; |
777 | } |
778 | |
779 | int SSL_SESSION_to_bytes_for_ticket(const SSL_SESSION *in, uint8_t **out_data, |
780 | size_t *out_len) { |
781 | ScopedCBB cbb; |
782 | if (!CBB_init(cbb.get(), 256) || |
783 | !SSL_SESSION_to_bytes_full(in, cbb.get(), 1) || |
784 | !CBB_finish(cbb.get(), out_data, out_len)) { |
785 | return 0; |
786 | } |
787 | |
788 | return 1; |
789 | } |
790 | |
791 | int i2d_SSL_SESSION(SSL_SESSION *in, uint8_t **pp) { |
792 | uint8_t *out; |
793 | size_t len; |
794 | |
795 | if (!SSL_SESSION_to_bytes(in, &out, &len)) { |
796 | return -1; |
797 | } |
798 | |
799 | if (len > INT_MAX) { |
800 | OPENSSL_free(out); |
801 | OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); |
802 | return -1; |
803 | } |
804 | |
805 | if (pp) { |
806 | OPENSSL_memcpy(*pp, out, len); |
807 | *pp += len; |
808 | } |
809 | OPENSSL_free(out); |
810 | |
811 | return len; |
812 | } |
813 | |
814 | SSL_SESSION *SSL_SESSION_from_bytes(const uint8_t *in, size_t in_len, |
815 | const SSL_CTX *ctx) { |
816 | CBS cbs; |
817 | CBS_init(&cbs, in, in_len); |
818 | UniquePtr<SSL_SESSION> ret = |
819 | SSL_SESSION_parse(&cbs, ctx->x509_method, ctx->pool); |
820 | if (!ret) { |
821 | return NULL; |
822 | } |
823 | if (CBS_len(&cbs) != 0) { |
824 | OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); |
825 | return NULL; |
826 | } |
827 | return ret.release(); |
828 | } |
829 | |