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