xref: /dflybsd-src/crypto/libressl/ssl/ssl_asn1.c (revision 72c3367655e64985522b7a48ddfab613e869dc68)
1*72c33676SMaxim Ag /* $OpenBSD: ssl_asn1.c,v 1.57 2018/08/27 16:42:48 jsing Exp $ */
2*72c33676SMaxim Ag /*
3*72c33676SMaxim Ag  * Copyright (c) 2016 Joel Sing <jsing@openbsd.org>
4f5b1c8a1SJohn Marino  *
5*72c33676SMaxim Ag  * Permission to use, copy, modify, and distribute this software for any
6*72c33676SMaxim Ag  * purpose with or without fee is hereby granted, provided that the above
7*72c33676SMaxim Ag  * copyright notice and this permission notice appear in all copies.
8f5b1c8a1SJohn Marino  *
9*72c33676SMaxim Ag  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10*72c33676SMaxim Ag  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11*72c33676SMaxim Ag  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12*72c33676SMaxim Ag  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13*72c33676SMaxim Ag  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14*72c33676SMaxim Ag  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15*72c33676SMaxim Ag  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16f5b1c8a1SJohn Marino  */
17f5b1c8a1SJohn Marino 
18*72c33676SMaxim Ag #include <limits.h>
19*72c33676SMaxim Ag 
20*72c33676SMaxim Ag #include <openssl/ssl.h>
21*72c33676SMaxim Ag #include <openssl/x509.h>
22f5b1c8a1SJohn Marino 
23f5b1c8a1SJohn Marino #include "ssl_locl.h"
24f5b1c8a1SJohn Marino 
25*72c33676SMaxim Ag #include "bytestring.h"
26f5b1c8a1SJohn Marino 
27*72c33676SMaxim Ag #define SSLASN1_TAG	(CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC)
28*72c33676SMaxim Ag #define SSLASN1_TIME_TAG		(SSLASN1_TAG | 1)
29*72c33676SMaxim Ag #define SSLASN1_TIMEOUT_TAG		(SSLASN1_TAG | 2)
30*72c33676SMaxim Ag #define SSLASN1_PEER_CERT_TAG		(SSLASN1_TAG | 3)
31*72c33676SMaxim Ag #define SSLASN1_SESSION_ID_CTX_TAG	(SSLASN1_TAG | 4)
32*72c33676SMaxim Ag #define SSLASN1_VERIFY_RESULT_TAG	(SSLASN1_TAG | 5)
33*72c33676SMaxim Ag #define SSLASN1_HOSTNAME_TAG		(SSLASN1_TAG | 6)
34*72c33676SMaxim Ag #define SSLASN1_LIFETIME_TAG		(SSLASN1_TAG | 9)
35*72c33676SMaxim Ag #define SSLASN1_TICKET_TAG		(SSLASN1_TAG | 10)
36f5b1c8a1SJohn Marino 
37*72c33676SMaxim Ag static uint64_t
38*72c33676SMaxim Ag time_max(void)
39*72c33676SMaxim Ag {
40*72c33676SMaxim Ag 	if (sizeof(time_t) == sizeof(int32_t))
41*72c33676SMaxim Ag 		return INT32_MAX;
42*72c33676SMaxim Ag 	if (sizeof(time_t) == sizeof(int64_t))
43*72c33676SMaxim Ag 		return INT64_MAX;
44*72c33676SMaxim Ag 	return 0;
45*72c33676SMaxim Ag }
46*72c33676SMaxim Ag 
47*72c33676SMaxim Ag static int
48*72c33676SMaxim Ag SSL_SESSION_encode(SSL_SESSION *s, unsigned char **out, size_t *out_len,
49*72c33676SMaxim Ag     int ticket_encoding)
50*72c33676SMaxim Ag {
51*72c33676SMaxim Ag 	CBB cbb, session, cipher_suite, session_id, master_key, time, timeout;
52*72c33676SMaxim Ag 	CBB peer_cert, sidctx, verify_result, hostname, lifetime, ticket, value;
53*72c33676SMaxim Ag 	unsigned char *peer_cert_bytes = NULL;
54*72c33676SMaxim Ag 	int len, rv = 0;
55*72c33676SMaxim Ag 	uint16_t cid;
56*72c33676SMaxim Ag 
57*72c33676SMaxim Ag 	if (!CBB_init(&cbb, 0))
58*72c33676SMaxim Ag 		goto err;
59*72c33676SMaxim Ag 
60*72c33676SMaxim Ag 	if (!CBB_add_asn1(&cbb, &session, CBS_ASN1_SEQUENCE))
61*72c33676SMaxim Ag 		goto err;
62*72c33676SMaxim Ag 
63*72c33676SMaxim Ag 	/* Session ASN1 version. */
64*72c33676SMaxim Ag 	if (!CBB_add_asn1_uint64(&session, SSL_SESSION_ASN1_VERSION))
65*72c33676SMaxim Ag 		goto err;
66*72c33676SMaxim Ag 
67*72c33676SMaxim Ag 	/* TLS/SSL protocol version. */
68*72c33676SMaxim Ag 	if (s->ssl_version < 0)
69*72c33676SMaxim Ag 		goto err;
70*72c33676SMaxim Ag 	if (!CBB_add_asn1_uint64(&session, s->ssl_version))
71*72c33676SMaxim Ag 		goto err;
72*72c33676SMaxim Ag 
73*72c33676SMaxim Ag 	/* Cipher suite ID. */
74*72c33676SMaxim Ag 	/* XXX - require cipher to be non-NULL or always/only use cipher_id. */
75*72c33676SMaxim Ag 	cid = (uint16_t)(s->cipher_id & 0xffff);
76*72c33676SMaxim Ag 	if (s->cipher != NULL)
77*72c33676SMaxim Ag 		cid = ssl3_cipher_get_value(s->cipher);
78*72c33676SMaxim Ag 	if (!CBB_add_asn1(&session, &cipher_suite, CBS_ASN1_OCTETSTRING))
79*72c33676SMaxim Ag 		goto err;
80*72c33676SMaxim Ag 	if (!CBB_add_u16(&cipher_suite, cid))
81*72c33676SMaxim Ag 		goto err;
82*72c33676SMaxim Ag 
83*72c33676SMaxim Ag 	/* Session ID - zero length for a ticket. */
84*72c33676SMaxim Ag 	if (!CBB_add_asn1(&session, &session_id, CBS_ASN1_OCTETSTRING))
85*72c33676SMaxim Ag 		goto err;
86*72c33676SMaxim Ag 	if (!CBB_add_bytes(&session_id, s->session_id,
87*72c33676SMaxim Ag 	    ticket_encoding ? 0 : s->session_id_length))
88*72c33676SMaxim Ag 		goto err;
89*72c33676SMaxim Ag 
90*72c33676SMaxim Ag 	/* Master key. */
91*72c33676SMaxim Ag 	if (!CBB_add_asn1(&session, &master_key, CBS_ASN1_OCTETSTRING))
92*72c33676SMaxim Ag 		goto err;
93*72c33676SMaxim Ag 	if (!CBB_add_bytes(&master_key, s->master_key, s->master_key_length))
94*72c33676SMaxim Ag 		goto err;
95*72c33676SMaxim Ag 
96*72c33676SMaxim Ag 	/* Time [1]. */
97*72c33676SMaxim Ag 	if (s->time != 0) {
98*72c33676SMaxim Ag 		if (s->time < 0)
99*72c33676SMaxim Ag 			goto err;
100*72c33676SMaxim Ag 		if (!CBB_add_asn1(&session, &time, SSLASN1_TIME_TAG))
101*72c33676SMaxim Ag 			goto err;
102*72c33676SMaxim Ag 		if (!CBB_add_asn1_uint64(&time, s->time))
103*72c33676SMaxim Ag 			goto err;
104*72c33676SMaxim Ag 	}
105*72c33676SMaxim Ag 
106*72c33676SMaxim Ag 	/* Timeout [2]. */
107*72c33676SMaxim Ag 	if (s->timeout != 0) {
108*72c33676SMaxim Ag 		if (s->timeout < 0)
109*72c33676SMaxim Ag 			goto err;
110*72c33676SMaxim Ag 		if (!CBB_add_asn1(&session, &timeout, SSLASN1_TIMEOUT_TAG))
111*72c33676SMaxim Ag 			goto err;
112*72c33676SMaxim Ag 		if (!CBB_add_asn1_uint64(&timeout, s->timeout))
113*72c33676SMaxim Ag 			goto err;
114*72c33676SMaxim Ag 	}
115*72c33676SMaxim Ag 
116*72c33676SMaxim Ag 	/* Peer certificate [3]. */
117*72c33676SMaxim Ag 	if (s->peer != NULL) {
118*72c33676SMaxim Ag 		if ((len = i2d_X509(s->peer, &peer_cert_bytes)) <= 0)
119*72c33676SMaxim Ag 			goto err;
120*72c33676SMaxim Ag 		if (!CBB_add_asn1(&session, &peer_cert, SSLASN1_PEER_CERT_TAG))
121*72c33676SMaxim Ag 			goto err;
122*72c33676SMaxim Ag 		if (!CBB_add_bytes(&peer_cert, peer_cert_bytes, len))
123*72c33676SMaxim Ag 			goto err;
124*72c33676SMaxim Ag 	}
125*72c33676SMaxim Ag 
126*72c33676SMaxim Ag 	/* Session ID context [4]. */
127*72c33676SMaxim Ag 	/* XXX - Actually handle this as optional? */
128*72c33676SMaxim Ag 	if (!CBB_add_asn1(&session, &sidctx, SSLASN1_SESSION_ID_CTX_TAG))
129*72c33676SMaxim Ag 		goto err;
130*72c33676SMaxim Ag 	if (!CBB_add_asn1(&sidctx, &value, CBS_ASN1_OCTETSTRING))
131*72c33676SMaxim Ag 		goto err;
132*72c33676SMaxim Ag 	if (!CBB_add_bytes(&value, s->sid_ctx, s->sid_ctx_length))
133*72c33676SMaxim Ag 		goto err;
134*72c33676SMaxim Ag 
135*72c33676SMaxim Ag 	/* Verify result [5]. */
136*72c33676SMaxim Ag 	if (s->verify_result != X509_V_OK) {
137*72c33676SMaxim Ag 		if (s->verify_result < 0)
138*72c33676SMaxim Ag 			goto err;
139*72c33676SMaxim Ag 		if (!CBB_add_asn1(&session, &verify_result,
140*72c33676SMaxim Ag 		    SSLASN1_VERIFY_RESULT_TAG))
141*72c33676SMaxim Ag 			goto err;
142*72c33676SMaxim Ag 		if (!CBB_add_asn1_uint64(&verify_result, s->verify_result))
143*72c33676SMaxim Ag 			goto err;
144*72c33676SMaxim Ag 	}
145*72c33676SMaxim Ag 
146*72c33676SMaxim Ag 	/* Hostname [6]. */
147*72c33676SMaxim Ag 	if (s->tlsext_hostname != NULL) {
148*72c33676SMaxim Ag 		if (!CBB_add_asn1(&session, &hostname, SSLASN1_HOSTNAME_TAG))
149*72c33676SMaxim Ag 			goto err;
150*72c33676SMaxim Ag 		if (!CBB_add_asn1(&hostname, &value, CBS_ASN1_OCTETSTRING))
151*72c33676SMaxim Ag 			goto err;
152*72c33676SMaxim Ag 		if (!CBB_add_bytes(&value, (const uint8_t *)s->tlsext_hostname,
153*72c33676SMaxim Ag 		    strlen(s->tlsext_hostname)))
154*72c33676SMaxim Ag 			goto err;
155*72c33676SMaxim Ag 	}
156*72c33676SMaxim Ag 
157*72c33676SMaxim Ag 	/* PSK identity hint [7]. */
158*72c33676SMaxim Ag 	/* PSK identity [8]. */
159*72c33676SMaxim Ag 
160*72c33676SMaxim Ag 	/* Ticket lifetime hint [9]. */
161*72c33676SMaxim Ag 	if (s->tlsext_tick_lifetime_hint > 0) {
162*72c33676SMaxim Ag 		if (!CBB_add_asn1(&session, &lifetime, SSLASN1_LIFETIME_TAG))
163*72c33676SMaxim Ag 			goto err;
164*72c33676SMaxim Ag 		if (!CBB_add_asn1_uint64(&lifetime,
165*72c33676SMaxim Ag 		    s->tlsext_tick_lifetime_hint))
166*72c33676SMaxim Ag 			goto err;
167*72c33676SMaxim Ag 	}
168*72c33676SMaxim Ag 
169*72c33676SMaxim Ag 	/* Ticket [10]. */
170*72c33676SMaxim Ag 	if (s->tlsext_tick != NULL) {
171*72c33676SMaxim Ag 		if (!CBB_add_asn1(&session, &ticket, SSLASN1_TICKET_TAG))
172*72c33676SMaxim Ag 			goto err;
173*72c33676SMaxim Ag 		if (!CBB_add_asn1(&ticket, &value, CBS_ASN1_OCTETSTRING))
174*72c33676SMaxim Ag 			goto err;
175*72c33676SMaxim Ag 		if (!CBB_add_bytes(&value, s->tlsext_tick, s->tlsext_ticklen))
176*72c33676SMaxim Ag 			goto err;
177*72c33676SMaxim Ag 	}
178*72c33676SMaxim Ag 
179*72c33676SMaxim Ag 	/* Compression method [11]. */
180*72c33676SMaxim Ag 	/* SRP username [12]. */
181*72c33676SMaxim Ag 
182*72c33676SMaxim Ag 	if (!CBB_finish(&cbb, out, out_len))
183*72c33676SMaxim Ag 		goto err;
184*72c33676SMaxim Ag 
185*72c33676SMaxim Ag 	rv = 1;
186*72c33676SMaxim Ag 
187*72c33676SMaxim Ag  err:
188*72c33676SMaxim Ag 	CBB_cleanup(&cbb);
189*72c33676SMaxim Ag 	free(peer_cert_bytes);
190*72c33676SMaxim Ag 
191*72c33676SMaxim Ag 	return rv;
192*72c33676SMaxim Ag }
193f5b1c8a1SJohn Marino 
194f5b1c8a1SJohn Marino int
195*72c33676SMaxim Ag SSL_SESSION_ticket(SSL_SESSION *ss, unsigned char **out, size_t *out_len)
196f5b1c8a1SJohn Marino {
197*72c33676SMaxim Ag 	if (ss == NULL)
198*72c33676SMaxim Ag 		return 0;
199f5b1c8a1SJohn Marino 
200*72c33676SMaxim Ag 	if (ss->cipher == NULL && ss->cipher_id == 0)
201*72c33676SMaxim Ag 		return 0;
202f5b1c8a1SJohn Marino 
203*72c33676SMaxim Ag 	return SSL_SESSION_encode(ss, out, out_len, 1);
204f5b1c8a1SJohn Marino }
205f5b1c8a1SJohn Marino 
206*72c33676SMaxim Ag int
207*72c33676SMaxim Ag i2d_SSL_SESSION(SSL_SESSION *ss, unsigned char **pp)
208*72c33676SMaxim Ag {
209*72c33676SMaxim Ag 	unsigned char *data = NULL;
210*72c33676SMaxim Ag 	size_t data_len = 0;
211*72c33676SMaxim Ag 	int rv = -1;
212*72c33676SMaxim Ag 
213*72c33676SMaxim Ag 	if (ss == NULL)
214*72c33676SMaxim Ag 		return 0;
215*72c33676SMaxim Ag 
216*72c33676SMaxim Ag 	if (ss->cipher == NULL && ss->cipher_id == 0)
217*72c33676SMaxim Ag 		return 0;
218*72c33676SMaxim Ag 
219*72c33676SMaxim Ag 	if (!SSL_SESSION_encode(ss, &data, &data_len, 0))
220*72c33676SMaxim Ag 		goto err;
221*72c33676SMaxim Ag 
222*72c33676SMaxim Ag 	if (data_len > INT_MAX)
223*72c33676SMaxim Ag 		goto err;
224*72c33676SMaxim Ag 
225*72c33676SMaxim Ag 	if (pp != NULL) {
226*72c33676SMaxim Ag 		if (*pp == NULL) {
227*72c33676SMaxim Ag 			*pp = data;
228*72c33676SMaxim Ag 			data = NULL;
229*72c33676SMaxim Ag 		} else {
230*72c33676SMaxim Ag 			memcpy(*pp, data, data_len);
231*72c33676SMaxim Ag 			*pp += data_len;
232*72c33676SMaxim Ag 		}
233f5b1c8a1SJohn Marino 	}
234f5b1c8a1SJohn Marino 
235*72c33676SMaxim Ag 	rv = (int)data_len;
236f5b1c8a1SJohn Marino 
237*72c33676SMaxim Ag  err:
238*72c33676SMaxim Ag 	freezero(data, data_len);
239f5b1c8a1SJohn Marino 
240*72c33676SMaxim Ag 	return rv;
241f5b1c8a1SJohn Marino }
242f5b1c8a1SJohn Marino 
243f5b1c8a1SJohn Marino SSL_SESSION *
244f5b1c8a1SJohn Marino d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp, long length)
245f5b1c8a1SJohn Marino {
246*72c33676SMaxim Ag 	CBS cbs, session, cipher_suite, session_id, master_key, peer_cert;
247*72c33676SMaxim Ag 	CBS hostname, ticket;
248*72c33676SMaxim Ag 	uint64_t version, tls_version, stime, timeout, verify_result, lifetime;
249*72c33676SMaxim Ag 	const unsigned char *peer_cert_bytes;
250*72c33676SMaxim Ag 	uint16_t cipher_value;
251*72c33676SMaxim Ag 	SSL_SESSION *s = NULL;
252*72c33676SMaxim Ag 	size_t data_len;
253*72c33676SMaxim Ag 	int present;
254f5b1c8a1SJohn Marino 
255f5b1c8a1SJohn Marino 	if (a != NULL)
256*72c33676SMaxim Ag 		s = *a;
257f5b1c8a1SJohn Marino 
258*72c33676SMaxim Ag 	if (s == NULL) {
259*72c33676SMaxim Ag 		if ((s = SSL_SESSION_new()) == NULL) {
260*72c33676SMaxim Ag 			SSLerrorx(ERR_R_MALLOC_FAILURE);
261*72c33676SMaxim Ag 			return (NULL);
262*72c33676SMaxim Ag 		}
263*72c33676SMaxim Ag 	}
264*72c33676SMaxim Ag 
265*72c33676SMaxim Ag 	CBS_init(&cbs, *pp, length);
266*72c33676SMaxim Ag 
267*72c33676SMaxim Ag 	if (!CBS_get_asn1(&cbs, &session, CBS_ASN1_SEQUENCE))
268*72c33676SMaxim Ag 		goto err;
269*72c33676SMaxim Ag 
270*72c33676SMaxim Ag 	/* Session ASN1 version. */
271*72c33676SMaxim Ag 	if (!CBS_get_asn1_uint64(&session, &version))
272*72c33676SMaxim Ag 		goto err;
273*72c33676SMaxim Ag 	if (version != SSL_SESSION_ASN1_VERSION)
274*72c33676SMaxim Ag 		goto err;
275*72c33676SMaxim Ag 
276*72c33676SMaxim Ag 	/* TLS/SSL Protocol Version. */
277*72c33676SMaxim Ag 	if (!CBS_get_asn1_uint64(&session, &tls_version))
278*72c33676SMaxim Ag 		goto err;
279*72c33676SMaxim Ag 	if (tls_version > INT_MAX)
280*72c33676SMaxim Ag 		goto err;
281*72c33676SMaxim Ag 	s->ssl_version = (int)tls_version;
282*72c33676SMaxim Ag 
283*72c33676SMaxim Ag 	/* Cipher suite. */
284*72c33676SMaxim Ag 	if (!CBS_get_asn1(&session, &cipher_suite, CBS_ASN1_OCTETSTRING))
285*72c33676SMaxim Ag 		goto err;
286*72c33676SMaxim Ag 	if (!CBS_get_u16(&cipher_suite, &cipher_value))
287*72c33676SMaxim Ag 		goto err;
288*72c33676SMaxim Ag 	if (CBS_len(&cipher_suite) != 0)
289*72c33676SMaxim Ag 		goto err;
290*72c33676SMaxim Ag 
291*72c33676SMaxim Ag 	/* XXX - populate cipher instead? */
292*72c33676SMaxim Ag 	s->cipher = NULL;
293*72c33676SMaxim Ag 	s->cipher_id = SSL3_CK_ID | cipher_value;
294*72c33676SMaxim Ag 
295*72c33676SMaxim Ag 	/* Session ID. */
296*72c33676SMaxim Ag 	if (!CBS_get_asn1(&session, &session_id, CBS_ASN1_OCTETSTRING))
297*72c33676SMaxim Ag 		goto err;
298*72c33676SMaxim Ag 	if (!CBS_write_bytes(&session_id, s->session_id, sizeof(s->session_id),
299*72c33676SMaxim Ag 	    &data_len))
300*72c33676SMaxim Ag 		goto err;
301*72c33676SMaxim Ag 	if (data_len > UINT_MAX)
302*72c33676SMaxim Ag 		goto err;
303*72c33676SMaxim Ag 	s->session_id_length = (unsigned int)data_len;
304*72c33676SMaxim Ag 
305*72c33676SMaxim Ag 	/* Master key. */
306*72c33676SMaxim Ag 	if (!CBS_get_asn1(&session, &master_key, CBS_ASN1_OCTETSTRING))
307*72c33676SMaxim Ag 		goto err;
308*72c33676SMaxim Ag 	if (!CBS_write_bytes(&master_key, s->master_key, sizeof(s->master_key),
309*72c33676SMaxim Ag 	    &data_len))
310*72c33676SMaxim Ag 		goto err;
311*72c33676SMaxim Ag 	if (data_len > INT_MAX)
312*72c33676SMaxim Ag 		goto err;
313*72c33676SMaxim Ag 	s->master_key_length = (int)data_len;
314*72c33676SMaxim Ag 
315*72c33676SMaxim Ag 	/* Time [1]. */
316*72c33676SMaxim Ag 	s->time = time(NULL);
317*72c33676SMaxim Ag 	if (!CBS_get_optional_asn1_uint64(&session, &stime, SSLASN1_TIME_TAG,
318*72c33676SMaxim Ag 	    0))
319*72c33676SMaxim Ag 		goto err;
320*72c33676SMaxim Ag 	if (stime > time_max())
321*72c33676SMaxim Ag 		goto err;
322*72c33676SMaxim Ag 	if (stime != 0)
323*72c33676SMaxim Ag 		s->time = (time_t)stime;
324*72c33676SMaxim Ag 
325*72c33676SMaxim Ag 	/* Timeout [2]. */
326*72c33676SMaxim Ag 	s->timeout = 3;
327*72c33676SMaxim Ag 	if (!CBS_get_optional_asn1_uint64(&session, &timeout,
328*72c33676SMaxim Ag 	    SSLASN1_TIMEOUT_TAG, 0))
329*72c33676SMaxim Ag 		goto err;
330*72c33676SMaxim Ag 	if (timeout > LONG_MAX)
331*72c33676SMaxim Ag 		goto err;
332*72c33676SMaxim Ag 	if (timeout != 0)
333*72c33676SMaxim Ag 		s->timeout = (long)timeout;
334*72c33676SMaxim Ag 
335*72c33676SMaxim Ag 	/* Peer certificate [3]. */
336*72c33676SMaxim Ag 	X509_free(s->peer);
337*72c33676SMaxim Ag 	s->peer = NULL;
338*72c33676SMaxim Ag 	if (!CBS_get_optional_asn1(&session, &peer_cert, &present,
339*72c33676SMaxim Ag 	    SSLASN1_PEER_CERT_TAG))
340*72c33676SMaxim Ag 		goto err;
341*72c33676SMaxim Ag 	if (present) {
342*72c33676SMaxim Ag 		data_len = CBS_len(&peer_cert);
343*72c33676SMaxim Ag 		if (data_len > LONG_MAX)
344*72c33676SMaxim Ag 			goto err;
345*72c33676SMaxim Ag 		peer_cert_bytes = CBS_data(&peer_cert);
346*72c33676SMaxim Ag 		if (d2i_X509(&s->peer, &peer_cert_bytes,
347*72c33676SMaxim Ag 		    (long)data_len) == NULL)
348*72c33676SMaxim Ag 			goto err;
349*72c33676SMaxim Ag 	}
350*72c33676SMaxim Ag 
351*72c33676SMaxim Ag 	/* Session ID context [4]. */
352*72c33676SMaxim Ag 	s->sid_ctx_length = 0;
353*72c33676SMaxim Ag 	if (!CBS_get_optional_asn1_octet_string(&session, &session_id, &present,
354*72c33676SMaxim Ag 	    SSLASN1_SESSION_ID_CTX_TAG))
355*72c33676SMaxim Ag 		goto err;
356*72c33676SMaxim Ag 	if (present) {
357*72c33676SMaxim Ag 		if (!CBS_write_bytes(&session_id, (uint8_t *)&s->sid_ctx,
358*72c33676SMaxim Ag 		    sizeof(s->sid_ctx), &data_len))
359*72c33676SMaxim Ag 			goto err;
360*72c33676SMaxim Ag 		if (data_len > UINT_MAX)
361*72c33676SMaxim Ag 			goto err;
362*72c33676SMaxim Ag 		s->sid_ctx_length = (unsigned int)data_len;
363*72c33676SMaxim Ag 	}
364*72c33676SMaxim Ag 
365*72c33676SMaxim Ag 	/* Verify result [5]. */
366*72c33676SMaxim Ag 	s->verify_result = X509_V_OK;
367*72c33676SMaxim Ag 	if (!CBS_get_optional_asn1_uint64(&session, &verify_result,
368*72c33676SMaxim Ag 	    SSLASN1_VERIFY_RESULT_TAG, X509_V_OK))
369*72c33676SMaxim Ag 		goto err;
370*72c33676SMaxim Ag 	if (verify_result > LONG_MAX)
371*72c33676SMaxim Ag 		goto err;
372*72c33676SMaxim Ag 	s->verify_result = (long)verify_result;
373*72c33676SMaxim Ag 
374*72c33676SMaxim Ag 	/* Hostname [6]. */
375*72c33676SMaxim Ag 	free(s->tlsext_hostname);
376*72c33676SMaxim Ag 	s->tlsext_hostname = NULL;
377*72c33676SMaxim Ag 	if (!CBS_get_optional_asn1_octet_string(&session, &hostname, &present,
378*72c33676SMaxim Ag 	    SSLASN1_HOSTNAME_TAG))
379*72c33676SMaxim Ag 		goto err;
380*72c33676SMaxim Ag 	if (present) {
381*72c33676SMaxim Ag 		if (CBS_contains_zero_byte(&hostname))
382*72c33676SMaxim Ag 			goto err;
383*72c33676SMaxim Ag 		if (!CBS_strdup(&hostname, &s->tlsext_hostname))
384*72c33676SMaxim Ag 			goto err;
385*72c33676SMaxim Ag 	}
386*72c33676SMaxim Ag 
387*72c33676SMaxim Ag 	/* PSK identity hint [7]. */
388*72c33676SMaxim Ag 	/* PSK identity [8]. */
389*72c33676SMaxim Ag 
390*72c33676SMaxim Ag 	/* Ticket lifetime [9]. */
391*72c33676SMaxim Ag 	s->tlsext_tick_lifetime_hint = 0;
392*72c33676SMaxim Ag 	/* XXX - tlsext_ticklen is not yet set... */
393*72c33676SMaxim Ag 	if (s->tlsext_ticklen > 0 && s->session_id_length > 0)
394*72c33676SMaxim Ag 		s->tlsext_tick_lifetime_hint = -1;
395*72c33676SMaxim Ag 	if (!CBS_get_optional_asn1_uint64(&session, &lifetime,
396*72c33676SMaxim Ag 	    SSLASN1_LIFETIME_TAG, 0))
397*72c33676SMaxim Ag 		goto err;
398*72c33676SMaxim Ag 	if (lifetime > LONG_MAX)
399*72c33676SMaxim Ag 		goto err;
400*72c33676SMaxim Ag 	if (lifetime > 0)
401*72c33676SMaxim Ag 		s->tlsext_tick_lifetime_hint = (long)lifetime;
402*72c33676SMaxim Ag 
403*72c33676SMaxim Ag 	/* Ticket [10]. */
404*72c33676SMaxim Ag 	free(s->tlsext_tick);
405*72c33676SMaxim Ag 	s->tlsext_tick = NULL;
406*72c33676SMaxim Ag 	if (!CBS_get_optional_asn1_octet_string(&session, &ticket, &present,
407*72c33676SMaxim Ag 	    SSLASN1_TICKET_TAG))
408*72c33676SMaxim Ag 		goto err;
409*72c33676SMaxim Ag 	if (present) {
410*72c33676SMaxim Ag 		if (!CBS_stow(&ticket, &s->tlsext_tick, &s->tlsext_ticklen))
411*72c33676SMaxim Ag 			goto err;
412*72c33676SMaxim Ag 	}
413*72c33676SMaxim Ag 
414*72c33676SMaxim Ag 	/* Compression method [11]. */
415*72c33676SMaxim Ag 	/* SRP username [12]. */
416*72c33676SMaxim Ag 
417*72c33676SMaxim Ag 	*pp = CBS_data(&cbs);
418*72c33676SMaxim Ag 
419*72c33676SMaxim Ag 	if (a != NULL)
420*72c33676SMaxim Ag 		*a = s;
421*72c33676SMaxim Ag 
422*72c33676SMaxim Ag 	return (s);
423f5b1c8a1SJohn Marino 
424f5b1c8a1SJohn Marino err:
425*72c33676SMaxim Ag 	ERR_asprintf_error_data("offset=%d", (int)(CBS_data(&cbs) - *pp));
426*72c33676SMaxim Ag 
427*72c33676SMaxim Ag 	if (s != NULL && (a == NULL || *a != s))
428*72c33676SMaxim Ag 		SSL_SESSION_free(s);
429f5b1c8a1SJohn Marino 
430f5b1c8a1SJohn Marino 	return (NULL);
431f5b1c8a1SJohn Marino }
432