• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
3  * Copyright 2005 Nokia. All rights reserved.
4  *
5  * Licensed under the OpenSSL license (the "License").  You may not use
6  * this file except in compliance with the License.  You can obtain a copy
7  * in the file LICENSE in the source distribution or at
8  * https://www.openssl.org/source/license.html
9  */
10 
11 #include <openssl/ssl.h>
12 
13 #include <limits.h>
14 #include <string.h>
15 
16 #include <utility>
17 
18 #include <openssl/bytestring.h>
19 #include <openssl/err.h>
20 #include <openssl/mem.h>
21 #include <openssl/x509.h>
22 
23 #include "../crypto/internal.h"
24 #include "internal.h"
25 
26 
27 BSSL_NAMESPACE_BEGIN
28 
29 // An SSL_SESSION is serialized as the following ASN.1 structure:
30 //
31 // SSLSession ::= SEQUENCE {
32 //     version                     INTEGER (1),  -- session structure version
33 //     sslVersion                  INTEGER,      -- protocol version number
34 //     cipher                      OCTET STRING, -- two bytes long
35 //     sessionID                   OCTET STRING,
36 //     secret                      OCTET STRING,
37 //     time                    [1] INTEGER, -- seconds since UNIX epoch
38 //     timeout                 [2] INTEGER, -- in seconds
39 //     peer                    [3] Certificate OPTIONAL,
40 //     sessionIDContext        [4] OCTET STRING OPTIONAL,
41 //     verifyResult            [5] INTEGER OPTIONAL,  -- one of X509_V_* codes
42 //     pskIdentity             [8] OCTET STRING OPTIONAL,
43 //     ticketLifetimeHint      [9] INTEGER OPTIONAL,       -- client-only
44 //     ticket                  [10] OCTET STRING OPTIONAL, -- client-only
45 //     peerSHA256              [13] OCTET STRING OPTIONAL,
46 //     originalHandshakeHash   [14] OCTET STRING OPTIONAL,
47 //     signedCertTimestampList [15] OCTET STRING OPTIONAL,
48 //                                  -- contents of SCT extension
49 //     ocspResponse            [16] OCTET STRING OPTIONAL,
50 //                                  -- stapled OCSP response from the server
51 //     extendedMasterSecret    [17] BOOLEAN OPTIONAL,
52 //     groupID                 [18] INTEGER OPTIONAL,
53 //     certChain               [19] SEQUENCE OF Certificate OPTIONAL,
54 //     ticketAgeAdd            [21] OCTET STRING OPTIONAL,
55 //     isServer                [22] BOOLEAN DEFAULT TRUE,
56 //     peerSignatureAlgorithm  [23] INTEGER OPTIONAL,
57 //     ticketMaxEarlyData      [24] INTEGER OPTIONAL,
58 //     authTimeout             [25] INTEGER OPTIONAL, -- defaults to timeout
59 //     earlyALPN               [26] OCTET STRING OPTIONAL,
60 //     isQuic                  [27] BOOLEAN OPTIONAL,
61 //     quicEarlyDataHash       [28] OCTET STRING OPTIONAL,
62 //     localALPS               [29] OCTET STRING OPTIONAL,
63 //     peerALPS                [30] OCTET STRING OPTIONAL,
64 //     -- Either both or none of localALPS and peerALPS must be present. If both
65 //     -- are present, earlyALPN must be present and non-empty.
66 // }
67 //
68 // Note: historically this serialization has included other optional
69 // fields. Their presence is currently treated as a parse error, except for
70 // hostName, which is ignored.
71 //
72 //     keyArg                  [0] IMPLICIT OCTET STRING OPTIONAL,
73 //     hostName                [6] OCTET STRING OPTIONAL,
74 //     pskIdentityHint         [7] OCTET STRING OPTIONAL,
75 //     compressionMethod       [11] OCTET STRING OPTIONAL,
76 //     srpUsername             [12] OCTET STRING OPTIONAL,
77 //     ticketFlags             [20] INTEGER OPTIONAL,
78 
79 static const unsigned kVersion = 1;
80 
81 static const CBS_ASN1_TAG kTimeTag =
82     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 1;
83 static const CBS_ASN1_TAG kTimeoutTag =
84     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 2;
85 static const CBS_ASN1_TAG kPeerTag =
86     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 3;
87 static const CBS_ASN1_TAG kSessionIDContextTag =
88     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 4;
89 static const CBS_ASN1_TAG kVerifyResultTag =
90     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 5;
91 static const CBS_ASN1_TAG kHostNameTag =
92     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 6;
93 static const CBS_ASN1_TAG kPSKIdentityTag =
94     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 8;
95 static const CBS_ASN1_TAG kTicketLifetimeHintTag =
96     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 9;
97 static const CBS_ASN1_TAG kTicketTag =
98     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 10;
99 static const CBS_ASN1_TAG kPeerSHA256Tag =
100     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 13;
101 static const CBS_ASN1_TAG kOriginalHandshakeHashTag =
102     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 14;
103 static const CBS_ASN1_TAG kSignedCertTimestampListTag =
104     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 15;
105 static const CBS_ASN1_TAG kOCSPResponseTag =
106     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 16;
107 static const CBS_ASN1_TAG kExtendedMasterSecretTag =
108     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 17;
109 static const CBS_ASN1_TAG kGroupIDTag =
110     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 18;
111 static const CBS_ASN1_TAG kCertChainTag =
112     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 19;
113 static const CBS_ASN1_TAG kTicketAgeAddTag =
114     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 21;
115 static const CBS_ASN1_TAG kIsServerTag =
116     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 22;
117 static const CBS_ASN1_TAG kPeerSignatureAlgorithmTag =
118     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 23;
119 static const CBS_ASN1_TAG kTicketMaxEarlyDataTag =
120     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 24;
121 static const CBS_ASN1_TAG kAuthTimeoutTag =
122     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 25;
123 static const CBS_ASN1_TAG kEarlyALPNTag =
124     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 26;
125 static const CBS_ASN1_TAG kIsQuicTag =
126     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 27;
127 static const CBS_ASN1_TAG kQuicEarlyDataContextTag =
128     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 28;
129 static const CBS_ASN1_TAG kLocalALPSTag =
130     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 29;
131 static const CBS_ASN1_TAG kPeerALPSTag =
132     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 30;
133 
SSL_SESSION_to_bytes_full(const SSL_SESSION * in,CBB * cbb,int for_ticket)134 static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, CBB *cbb,
135                                      int for_ticket) {
136   if (in == NULL || in->cipher == NULL) {
137     return 0;
138   }
139 
140   CBB session, child, child2;
141   if (!CBB_add_asn1(cbb, &session, CBS_ASN1_SEQUENCE) ||
142       !CBB_add_asn1_uint64(&session, kVersion) ||
143       !CBB_add_asn1_uint64(&session, in->ssl_version) ||
144       !CBB_add_asn1(&session, &child, CBS_ASN1_OCTETSTRING) ||
145       !CBB_add_u16(&child, (uint16_t)(in->cipher->id & 0xffff)) ||
146       // The session ID is irrelevant for a session ticket.
147       !CBB_add_asn1_octet_string(&session, in->session_id.data(),
148                                  for_ticket ? 0 : in->session_id.size()) ||
149       !CBB_add_asn1_octet_string(&session, in->secret.data(),
150                                  in->secret.size()) ||
151       !CBB_add_asn1(&session, &child, kTimeTag) ||
152       !CBB_add_asn1_uint64(&child, in->time) ||
153       !CBB_add_asn1(&session, &child, kTimeoutTag) ||
154       !CBB_add_asn1_uint64(&child, in->timeout)) {
155     return 0;
156   }
157 
158   // The peer certificate is only serialized if the SHA-256 isn't
159   // serialized instead.
160   if (sk_CRYPTO_BUFFER_num(in->certs.get()) > 0 && !in->peer_sha256_valid) {
161     const CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(in->certs.get(), 0);
162     if (!CBB_add_asn1(&session, &child, kPeerTag) ||
163         !CBB_add_bytes(&child, CRYPTO_BUFFER_data(buffer),
164                        CRYPTO_BUFFER_len(buffer))) {
165       return 0;
166     }
167   }
168 
169   // Although it is OPTIONAL and usually empty, OpenSSL has
170   // historically always encoded the sid_ctx.
171   if (!CBB_add_asn1(&session, &child, kSessionIDContextTag) ||
172       !CBB_add_asn1_octet_string(&child, in->sid_ctx.data(),
173                                  in->sid_ctx.size())) {
174     return 0;
175   }
176 
177   if (in->verify_result != X509_V_OK) {
178     if (!CBB_add_asn1(&session, &child, kVerifyResultTag) ||
179         !CBB_add_asn1_uint64(&child, in->verify_result)) {
180       return 0;
181     }
182   }
183 
184   if (in->psk_identity) {
185     if (!CBB_add_asn1(&session, &child, kPSKIdentityTag) ||
186         !CBB_add_asn1_octet_string(&child,
187                                    (const uint8_t *)in->psk_identity.get(),
188                                    strlen(in->psk_identity.get()))) {
189       return 0;
190     }
191   }
192 
193   if (in->ticket_lifetime_hint > 0) {
194     if (!CBB_add_asn1(&session, &child, kTicketLifetimeHintTag) ||
195         !CBB_add_asn1_uint64(&child, in->ticket_lifetime_hint)) {
196       return 0;
197     }
198   }
199 
200   if (!in->ticket.empty() && !for_ticket) {
201     if (!CBB_add_asn1(&session, &child, kTicketTag) ||
202         !CBB_add_asn1_octet_string(&child, in->ticket.data(),
203                                    in->ticket.size())) {
204       return 0;
205     }
206   }
207 
208   if (in->peer_sha256_valid) {
209     if (!CBB_add_asn1(&session, &child, kPeerSHA256Tag) ||
210         !CBB_add_asn1_octet_string(&child, in->peer_sha256,
211                                    sizeof(in->peer_sha256))) {
212       return 0;
213     }
214   }
215 
216   if (!in->original_handshake_hash.empty()) {
217     if (!CBB_add_asn1(&session, &child, kOriginalHandshakeHashTag) ||
218         !CBB_add_asn1_octet_string(&child, in->original_handshake_hash.data(),
219                                    in->original_handshake_hash.size())) {
220       return 0;
221     }
222   }
223 
224   if (in->signed_cert_timestamp_list != nullptr) {
225     if (!CBB_add_asn1(&session, &child, kSignedCertTimestampListTag) ||
226         !CBB_add_asn1_octet_string(
227             &child, CRYPTO_BUFFER_data(in->signed_cert_timestamp_list.get()),
228             CRYPTO_BUFFER_len(in->signed_cert_timestamp_list.get()))) {
229       return 0;
230     }
231   }
232 
233   if (in->ocsp_response != nullptr) {
234     if (!CBB_add_asn1(&session, &child, kOCSPResponseTag) ||
235         !CBB_add_asn1_octet_string(
236             &child, CRYPTO_BUFFER_data(in->ocsp_response.get()),
237             CRYPTO_BUFFER_len(in->ocsp_response.get()))) {
238       return 0;
239     }
240   }
241 
242   if (in->extended_master_secret) {
243     if (!CBB_add_asn1(&session, &child, kExtendedMasterSecretTag) ||
244         !CBB_add_asn1_bool(&child, true)) {
245       return 0;
246     }
247   }
248 
249   if (in->group_id > 0 &&                               //
250       (!CBB_add_asn1(&session, &child, kGroupIDTag) ||  //
251        !CBB_add_asn1_uint64(&child, in->group_id))) {
252     return 0;
253   }
254 
255   // The certificate chain is only serialized if the leaf's SHA-256 isn't
256   // serialized instead.
257   if (in->certs != NULL &&       //
258       !in->peer_sha256_valid &&  //
259       sk_CRYPTO_BUFFER_num(in->certs.get()) >= 2) {
260     if (!CBB_add_asn1(&session, &child, kCertChainTag)) {
261       return 0;
262     }
263     for (size_t i = 1; i < sk_CRYPTO_BUFFER_num(in->certs.get()); i++) {
264       const CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(in->certs.get(), i);
265       if (!CBB_add_bytes(&child, CRYPTO_BUFFER_data(buffer),
266                          CRYPTO_BUFFER_len(buffer))) {
267         return 0;
268       }
269     }
270   }
271 
272   if (in->ticket_age_add_valid) {
273     if (!CBB_add_asn1(&session, &child, kTicketAgeAddTag) ||
274         !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
275         !CBB_add_u32(&child2, in->ticket_age_add)) {
276       return 0;
277     }
278   }
279 
280   if (!in->is_server) {
281     if (!CBB_add_asn1(&session, &child, kIsServerTag) ||
282         !CBB_add_asn1_bool(&child, false)) {
283       return 0;
284     }
285   }
286 
287   if (in->peer_signature_algorithm != 0 &&
288       (!CBB_add_asn1(&session, &child, kPeerSignatureAlgorithmTag) ||
289        !CBB_add_asn1_uint64(&child, in->peer_signature_algorithm))) {
290     return 0;
291   }
292 
293   if (in->ticket_max_early_data != 0 &&
294       (!CBB_add_asn1(&session, &child, kTicketMaxEarlyDataTag) ||
295        !CBB_add_asn1_uint64(&child, in->ticket_max_early_data))) {
296     return 0;
297   }
298 
299   if (in->timeout != in->auth_timeout &&
300       (!CBB_add_asn1(&session, &child, kAuthTimeoutTag) ||
301        !CBB_add_asn1_uint64(&child, in->auth_timeout))) {
302     return 0;
303   }
304 
305   if (!in->early_alpn.empty()) {
306     if (!CBB_add_asn1(&session, &child, kEarlyALPNTag) ||
307         !CBB_add_asn1_octet_string(&child, in->early_alpn.data(),
308                                    in->early_alpn.size())) {
309       return 0;
310     }
311   }
312 
313   if (in->is_quic) {
314     if (!CBB_add_asn1(&session, &child, kIsQuicTag) ||
315         !CBB_add_asn1_bool(&child, true)) {
316       return 0;
317     }
318   }
319 
320   if (!in->quic_early_data_context.empty()) {
321     if (!CBB_add_asn1(&session, &child, kQuicEarlyDataContextTag) ||
322         !CBB_add_asn1_octet_string(&child, in->quic_early_data_context.data(),
323                                    in->quic_early_data_context.size())) {
324       return 0;
325     }
326   }
327 
328   if (in->has_application_settings) {
329     if (!CBB_add_asn1(&session, &child, kLocalALPSTag) ||
330         !CBB_add_asn1_octet_string(&child,
331                                    in->local_application_settings.data(),
332                                    in->local_application_settings.size()) ||
333         !CBB_add_asn1(&session, &child, kPeerALPSTag) ||
334         !CBB_add_asn1_octet_string(&child, in->peer_application_settings.data(),
335                                    in->peer_application_settings.size())) {
336       return 0;
337     }
338   }
339 
340   return CBB_flush(cbb);
341 }
342 
343 // SSL_SESSION_parse_string gets an optional ASN.1 OCTET STRING explicitly
344 // tagged with |tag| from |cbs| and saves it in |*out|. If the element was not
345 // found, it sets |*out| to NULL. It returns one on success, whether or not the
346 // element was found, and zero on decode error.
SSL_SESSION_parse_string(CBS * cbs,UniquePtr<char> * out,CBS_ASN1_TAG tag)347 static int SSL_SESSION_parse_string(CBS *cbs, UniquePtr<char> *out,
348                                     CBS_ASN1_TAG tag) {
349   CBS value;
350   int present;
351   if (!CBS_get_optional_asn1_octet_string(cbs, &value, &present, tag)) {
352     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
353     return 0;
354   }
355   if (present) {
356     if (CBS_contains_zero_byte(&value)) {
357       OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
358       return 0;
359     }
360     char *raw = nullptr;
361     if (!CBS_strdup(&value, &raw)) {
362       return 0;
363     }
364     out->reset(raw);
365   } else {
366     out->reset();
367   }
368   return 1;
369 }
370 
371 // SSL_SESSION_parse_octet_string gets an optional ASN.1 OCTET STRING explicitly
372 // tagged with |tag| from |cbs| and stows it in |*out|. It returns one on
373 // success, whether or not the element was found, and zero on decode error.
SSL_SESSION_parse_octet_string(CBS * cbs,Array<uint8_t> * out,CBS_ASN1_TAG tag)374 static bool SSL_SESSION_parse_octet_string(CBS *cbs, Array<uint8_t> *out,
375                                            CBS_ASN1_TAG tag) {
376   CBS value;
377   if (!CBS_get_optional_asn1_octet_string(cbs, &value, NULL, tag)) {
378     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
379     return false;
380   }
381   return out->CopyFrom(value);
382 }
383 
SSL_SESSION_parse_crypto_buffer(CBS * cbs,UniquePtr<CRYPTO_BUFFER> * out,CBS_ASN1_TAG tag,CRYPTO_BUFFER_POOL * pool)384 static int SSL_SESSION_parse_crypto_buffer(CBS *cbs,
385                                            UniquePtr<CRYPTO_BUFFER> *out,
386                                            CBS_ASN1_TAG tag,
387                                            CRYPTO_BUFFER_POOL *pool) {
388   if (!CBS_peek_asn1_tag(cbs, tag)) {
389     return 1;
390   }
391 
392   CBS child, value;
393   if (!CBS_get_asn1(cbs, &child, tag) ||
394       !CBS_get_asn1(&child, &value, CBS_ASN1_OCTETSTRING) ||
395       CBS_len(&child) != 0) {
396     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
397     return 0;
398   }
399   out->reset(CRYPTO_BUFFER_new_from_CBS(&value, pool));
400   if (*out == nullptr) {
401     return 0;
402   }
403   return 1;
404 }
405 
SSL_SESSION_parse_long(CBS * cbs,long * out,CBS_ASN1_TAG tag,long default_value)406 static int SSL_SESSION_parse_long(CBS *cbs, long *out, CBS_ASN1_TAG tag,
407                                   long default_value) {
408   uint64_t value;
409   if (!CBS_get_optional_asn1_uint64(cbs, &value, tag,
410                                     (uint64_t)default_value) ||
411       value > LONG_MAX) {
412     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
413     return 0;
414   }
415   *out = (long)value;
416   return 1;
417 }
418 
SSL_SESSION_parse_u32(CBS * cbs,uint32_t * out,CBS_ASN1_TAG tag,uint32_t default_value)419 static int SSL_SESSION_parse_u32(CBS *cbs, uint32_t *out, CBS_ASN1_TAG tag,
420                                  uint32_t default_value) {
421   uint64_t value;
422   if (!CBS_get_optional_asn1_uint64(cbs, &value, tag,
423                                     (uint64_t)default_value) ||
424       value > 0xffffffff) {
425     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
426     return 0;
427   }
428   *out = (uint32_t)value;
429   return 1;
430 }
431 
SSL_SESSION_parse_u16(CBS * cbs,uint16_t * out,CBS_ASN1_TAG tag,uint16_t default_value)432 static int SSL_SESSION_parse_u16(CBS *cbs, uint16_t *out, CBS_ASN1_TAG tag,
433                                  uint16_t default_value) {
434   uint64_t value;
435   if (!CBS_get_optional_asn1_uint64(cbs, &value, tag,
436                                     (uint64_t)default_value) ||
437       value > 0xffff) {
438     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
439     return 0;
440   }
441   *out = (uint16_t)value;
442   return 1;
443 }
444 
SSL_SESSION_parse(CBS * cbs,const SSL_X509_METHOD * x509_method,CRYPTO_BUFFER_POOL * pool)445 UniquePtr<SSL_SESSION> SSL_SESSION_parse(CBS *cbs,
446                                          const SSL_X509_METHOD *x509_method,
447                                          CRYPTO_BUFFER_POOL *pool) {
448   UniquePtr<SSL_SESSION> ret = ssl_session_new(x509_method);
449   if (!ret) {
450     return nullptr;
451   }
452 
453   CBS session;
454   uint64_t version, ssl_version;
455   uint16_t unused;
456   if (!CBS_get_asn1(cbs, &session, CBS_ASN1_SEQUENCE) ||  //
457       !CBS_get_asn1_uint64(&session, &version) ||         //
458       version != kVersion ||                              //
459       !CBS_get_asn1_uint64(&session, &ssl_version) ||     //
460       // Require sessions have versions valid in either TLS or DTLS. The session
461       // will not be used by the handshake if not applicable, but, for
462       // simplicity, never parse a session that does not pass
463       // |ssl_protocol_version_from_wire|.
464       ssl_version > UINT16_MAX ||  //
465       !ssl_protocol_version_from_wire(&unused, ssl_version)) {
466     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
467     return nullptr;
468   }
469   ret->ssl_version = ssl_version;
470 
471   CBS cipher;
472   uint16_t cipher_value;
473   if (!CBS_get_asn1(&session, &cipher, CBS_ASN1_OCTETSTRING) ||  //
474       !CBS_get_u16(&cipher, &cipher_value) ||                    //
475       CBS_len(&cipher) != 0) {
476     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
477     return nullptr;
478   }
479   ret->cipher = SSL_get_cipher_by_value(cipher_value);
480   if (ret->cipher == NULL) {
481     OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_CIPHER);
482     return nullptr;
483   }
484 
485   CBS session_id, secret, child;
486   uint64_t timeout;
487   if (!CBS_get_asn1(&session, &session_id, CBS_ASN1_OCTETSTRING) ||
488       !ret->session_id.TryCopyFrom(session_id) ||
489       !CBS_get_asn1(&session, &secret, CBS_ASN1_OCTETSTRING) ||
490       !ret->secret.TryCopyFrom(secret) ||
491       !CBS_get_asn1(&session, &child, kTimeTag) ||
492       !CBS_get_asn1_uint64(&child, &ret->time) ||
493       !CBS_get_asn1(&session, &child, kTimeoutTag) ||
494       !CBS_get_asn1_uint64(&child, &timeout) ||  //
495       timeout > UINT32_MAX) {
496     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
497     return nullptr;
498   }
499 
500   ret->timeout = (uint32_t)timeout;
501 
502   CBS peer;
503   int has_peer;
504   if (!CBS_get_optional_asn1(&session, &peer, &has_peer, kPeerTag) ||
505       (has_peer && CBS_len(&peer) == 0)) {
506     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
507     return nullptr;
508   }
509   // |peer| is processed with the certificate chain.
510 
511   CBS sid_ctx;
512   if (!CBS_get_optional_asn1_octet_string(
513           &session, &sid_ctx, /*out_present=*/nullptr, kSessionIDContextTag) ||
514       !ret->sid_ctx.TryCopyFrom(sid_ctx) ||
515       !SSL_SESSION_parse_long(&session, &ret->verify_result, kVerifyResultTag,
516                               X509_V_OK)) {
517     return nullptr;
518   }
519 
520   // Skip the historical hostName field.
521   CBS unused_hostname;
522   if (!CBS_get_optional_asn1(&session, &unused_hostname, nullptr,
523                              kHostNameTag)) {
524     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
525     return nullptr;
526   }
527 
528   if (!SSL_SESSION_parse_string(&session, &ret->psk_identity,
529                                 kPSKIdentityTag) ||
530       !SSL_SESSION_parse_u32(&session, &ret->ticket_lifetime_hint,
531                              kTicketLifetimeHintTag, 0) ||
532       !SSL_SESSION_parse_octet_string(&session, &ret->ticket, kTicketTag)) {
533     return nullptr;
534   }
535 
536   if (CBS_peek_asn1_tag(&session, kPeerSHA256Tag)) {
537     CBS peer_sha256;
538     if (!CBS_get_asn1(&session, &child, kPeerSHA256Tag) ||
539         !CBS_get_asn1(&child, &peer_sha256, CBS_ASN1_OCTETSTRING) ||
540         CBS_len(&peer_sha256) != sizeof(ret->peer_sha256) ||
541         CBS_len(&child) != 0) {
542       OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
543       return nullptr;
544     }
545     OPENSSL_memcpy(ret->peer_sha256, CBS_data(&peer_sha256),
546                    sizeof(ret->peer_sha256));
547     ret->peer_sha256_valid = true;
548   } else {
549     ret->peer_sha256_valid = false;
550   }
551 
552   CBS original_handshake_hash;
553   if (!CBS_get_optional_asn1_octet_string(&session, &original_handshake_hash,
554                                           /*out_present=*/nullptr,
555                                           kOriginalHandshakeHashTag) ||
556       !ret->original_handshake_hash.TryCopyFrom(original_handshake_hash) ||
557       !SSL_SESSION_parse_crypto_buffer(&session,
558                                        &ret->signed_cert_timestamp_list,
559                                        kSignedCertTimestampListTag, pool) ||
560       !SSL_SESSION_parse_crypto_buffer(&session, &ret->ocsp_response,
561                                        kOCSPResponseTag, pool)) {
562     return nullptr;
563   }
564 
565   int extended_master_secret;
566   if (!CBS_get_optional_asn1_bool(&session, &extended_master_secret,
567                                   kExtendedMasterSecretTag,
568                                   0 /* default to false */)) {
569     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
570     return nullptr;
571   }
572   ret->extended_master_secret = !!extended_master_secret;
573 
574   if (!SSL_SESSION_parse_u16(&session, &ret->group_id, kGroupIDTag, 0)) {
575     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
576     return nullptr;
577   }
578 
579   CBS cert_chain;
580   CBS_init(&cert_chain, NULL, 0);
581   int has_cert_chain;
582   if (!CBS_get_optional_asn1(&session, &cert_chain, &has_cert_chain,
583                              kCertChainTag) ||
584       (has_cert_chain && CBS_len(&cert_chain) == 0)) {
585     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
586     return nullptr;
587   }
588   if (has_cert_chain && !has_peer) {
589     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
590     return nullptr;
591   }
592   if (has_peer || has_cert_chain) {
593     ret->certs.reset(sk_CRYPTO_BUFFER_new_null());
594     if (ret->certs == nullptr) {
595       return nullptr;
596     }
597 
598     if (has_peer) {
599       UniquePtr<CRYPTO_BUFFER> buffer(CRYPTO_BUFFER_new_from_CBS(&peer, pool));
600       if (!buffer ||  //
601           !PushToStack(ret->certs.get(), std::move(buffer))) {
602         return nullptr;
603       }
604     }
605 
606     while (CBS_len(&cert_chain) > 0) {
607       CBS cert;
608       if (!CBS_get_any_asn1_element(&cert_chain, &cert, NULL, NULL) ||
609           CBS_len(&cert) == 0) {
610         OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
611         return nullptr;
612       }
613 
614       UniquePtr<CRYPTO_BUFFER> buffer(CRYPTO_BUFFER_new_from_CBS(&cert, pool));
615       if (buffer == nullptr ||
616           !PushToStack(ret->certs.get(), std::move(buffer))) {
617         return nullptr;
618       }
619     }
620   }
621 
622   CBS age_add;
623   int age_add_present;
624   if (!CBS_get_optional_asn1_octet_string(&session, &age_add, &age_add_present,
625                                           kTicketAgeAddTag) ||
626       (age_add_present &&                                //
627        !CBS_get_u32(&age_add, &ret->ticket_age_add)) ||  //
628       CBS_len(&age_add) != 0) {
629     return nullptr;
630   }
631   ret->ticket_age_add_valid = age_add_present != 0;
632 
633   int is_server;
634   if (!CBS_get_optional_asn1_bool(&session, &is_server, kIsServerTag,
635                                   1 /* default to true */)) {
636     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
637     return nullptr;
638   }
639   /* TODO: in time we can include |is_server| for servers too, then we can
640      enforce that client and server sessions are never mixed up. */
641 
642   ret->is_server = is_server;
643 
644   int is_quic;
645   if (!SSL_SESSION_parse_u16(&session, &ret->peer_signature_algorithm,
646                              kPeerSignatureAlgorithmTag, 0) ||
647       !SSL_SESSION_parse_u32(&session, &ret->ticket_max_early_data,
648                              kTicketMaxEarlyDataTag, 0) ||
649       !SSL_SESSION_parse_u32(&session, &ret->auth_timeout, kAuthTimeoutTag,
650                              ret->timeout) ||
651       !SSL_SESSION_parse_octet_string(&session, &ret->early_alpn,
652                                       kEarlyALPNTag) ||
653       !CBS_get_optional_asn1_bool(&session, &is_quic, kIsQuicTag,
654                                   /*default_value=*/false) ||
655       !SSL_SESSION_parse_octet_string(&session, &ret->quic_early_data_context,
656                                       kQuicEarlyDataContextTag)) {
657     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
658     return nullptr;
659   }
660 
661   CBS settings;
662   int has_local_alps, has_peer_alps;
663   if (!CBS_get_optional_asn1_octet_string(&session, &settings, &has_local_alps,
664                                           kLocalALPSTag) ||
665       !ret->local_application_settings.CopyFrom(settings) ||
666       !CBS_get_optional_asn1_octet_string(&session, &settings, &has_peer_alps,
667                                           kPeerALPSTag) ||
668       !ret->peer_application_settings.CopyFrom(settings) ||
669       CBS_len(&session) != 0) {
670     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
671     return nullptr;
672   }
673   ret->is_quic = is_quic;
674 
675   // The two ALPS values and ALPN must be consistent.
676   if (has_local_alps != has_peer_alps ||
677       (has_local_alps && ret->early_alpn.empty())) {
678     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
679     return nullptr;
680   }
681   ret->has_application_settings = has_local_alps;
682 
683   if (!x509_method->session_cache_objects(ret.get())) {
684     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
685     return nullptr;
686   }
687 
688   return ret;
689 }
690 
ssl_session_serialize(const SSL_SESSION * in,CBB * cbb)691 bool ssl_session_serialize(const SSL_SESSION *in, CBB *cbb) {
692   return SSL_SESSION_to_bytes_full(in, cbb, 0);
693 }
694 
695 BSSL_NAMESPACE_END
696 
697 using namespace bssl;
698 
SSL_SESSION_to_bytes(const SSL_SESSION * in,uint8_t ** out_data,size_t * out_len)699 int SSL_SESSION_to_bytes(const SSL_SESSION *in, uint8_t **out_data,
700                          size_t *out_len) {
701   if (in->not_resumable) {
702     // If the caller has an unresumable session, e.g. if |SSL_get_session| were
703     // called on a TLS 1.3 or False Started connection, serialize with a
704     // placeholder value so it is not accidentally deserialized into a resumable
705     // one.
706     static const char kNotResumableSession[] = "NOT RESUMABLE";
707 
708     *out_len = strlen(kNotResumableSession);
709     *out_data = (uint8_t *)OPENSSL_memdup(kNotResumableSession, *out_len);
710     if (*out_data == NULL) {
711       return 0;
712     }
713 
714     return 1;
715   }
716 
717   ScopedCBB cbb;
718   if (!CBB_init(cbb.get(), 256) ||
719       !SSL_SESSION_to_bytes_full(in, cbb.get(), 0) ||
720       !CBB_finish(cbb.get(), out_data, out_len)) {
721     return 0;
722   }
723 
724   return 1;
725 }
726 
SSL_SESSION_to_bytes_for_ticket(const SSL_SESSION * in,uint8_t ** out_data,size_t * out_len)727 int SSL_SESSION_to_bytes_for_ticket(const SSL_SESSION *in, uint8_t **out_data,
728                                     size_t *out_len) {
729   ScopedCBB cbb;
730   if (!CBB_init(cbb.get(), 256) ||
731       !SSL_SESSION_to_bytes_full(in, cbb.get(), 1) ||
732       !CBB_finish(cbb.get(), out_data, out_len)) {
733     return 0;
734   }
735 
736   return 1;
737 }
738 
i2d_SSL_SESSION(SSL_SESSION * in,uint8_t ** pp)739 int i2d_SSL_SESSION(SSL_SESSION *in, uint8_t **pp) {
740   uint8_t *out;
741   size_t len;
742 
743   if (!SSL_SESSION_to_bytes(in, &out, &len)) {
744     return -1;
745   }
746 
747   if (len > INT_MAX) {
748     OPENSSL_free(out);
749     OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
750     return -1;
751   }
752 
753   if (pp) {
754     OPENSSL_memcpy(*pp, out, len);
755     *pp += len;
756   }
757   OPENSSL_free(out);
758 
759   return len;
760 }
761 
SSL_SESSION_from_bytes(const uint8_t * in,size_t in_len,const SSL_CTX * ctx)762 SSL_SESSION *SSL_SESSION_from_bytes(const uint8_t *in, size_t in_len,
763                                     const SSL_CTX *ctx) {
764   CBS cbs;
765   CBS_init(&cbs, in, in_len);
766   UniquePtr<SSL_SESSION> ret =
767       SSL_SESSION_parse(&cbs, ctx->x509_method, ctx->pool);
768   if (!ret) {
769     return NULL;
770   }
771   if (CBS_len(&cbs) != 0) {
772     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
773     return NULL;
774   }
775   return ret.release();
776 }
777