xref: /dflybsd-src/crypto/libressl/ssl/ssl_asn1.c (revision f5b1c8a1e6dbe9333aed363dba27c2ff58be6174)
1*f5b1c8a1SJohn Marino /* $OpenBSD: ssl_asn1.c,v 1.40 2014/12/14 15:30:50 jsing Exp $ */
2*f5b1c8a1SJohn Marino /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3*f5b1c8a1SJohn Marino  * All rights reserved.
4*f5b1c8a1SJohn Marino  *
5*f5b1c8a1SJohn Marino  * This package is an SSL implementation written
6*f5b1c8a1SJohn Marino  * by Eric Young (eay@cryptsoft.com).
7*f5b1c8a1SJohn Marino  * The implementation was written so as to conform with Netscapes SSL.
8*f5b1c8a1SJohn Marino  *
9*f5b1c8a1SJohn Marino  * This library is free for commercial and non-commercial use as long as
10*f5b1c8a1SJohn Marino  * the following conditions are aheared to.  The following conditions
11*f5b1c8a1SJohn Marino  * apply to all code found in this distribution, be it the RC4, RSA,
12*f5b1c8a1SJohn Marino  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13*f5b1c8a1SJohn Marino  * included with this distribution is covered by the same copyright terms
14*f5b1c8a1SJohn Marino  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15*f5b1c8a1SJohn Marino  *
16*f5b1c8a1SJohn Marino  * Copyright remains Eric Young's, and as such any Copyright notices in
17*f5b1c8a1SJohn Marino  * the code are not to be removed.
18*f5b1c8a1SJohn Marino  * If this package is used in a product, Eric Young should be given attribution
19*f5b1c8a1SJohn Marino  * as the author of the parts of the library used.
20*f5b1c8a1SJohn Marino  * This can be in the form of a textual message at program startup or
21*f5b1c8a1SJohn Marino  * in documentation (online or textual) provided with the package.
22*f5b1c8a1SJohn Marino  *
23*f5b1c8a1SJohn Marino  * Redistribution and use in source and binary forms, with or without
24*f5b1c8a1SJohn Marino  * modification, are permitted provided that the following conditions
25*f5b1c8a1SJohn Marino  * are met:
26*f5b1c8a1SJohn Marino  * 1. Redistributions of source code must retain the copyright
27*f5b1c8a1SJohn Marino  *    notice, this list of conditions and the following disclaimer.
28*f5b1c8a1SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
29*f5b1c8a1SJohn Marino  *    notice, this list of conditions and the following disclaimer in the
30*f5b1c8a1SJohn Marino  *    documentation and/or other materials provided with the distribution.
31*f5b1c8a1SJohn Marino  * 3. All advertising materials mentioning features or use of this software
32*f5b1c8a1SJohn Marino  *    must display the following acknowledgement:
33*f5b1c8a1SJohn Marino  *    "This product includes cryptographic software written by
34*f5b1c8a1SJohn Marino  *     Eric Young (eay@cryptsoft.com)"
35*f5b1c8a1SJohn Marino  *    The word 'cryptographic' can be left out if the rouines from the library
36*f5b1c8a1SJohn Marino  *    being used are not cryptographic related :-).
37*f5b1c8a1SJohn Marino  * 4. If you include any Windows specific code (or a derivative thereof) from
38*f5b1c8a1SJohn Marino  *    the apps directory (application code) you must include an acknowledgement:
39*f5b1c8a1SJohn Marino  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40*f5b1c8a1SJohn Marino  *
41*f5b1c8a1SJohn Marino  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42*f5b1c8a1SJohn Marino  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43*f5b1c8a1SJohn Marino  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44*f5b1c8a1SJohn Marino  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45*f5b1c8a1SJohn Marino  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46*f5b1c8a1SJohn Marino  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47*f5b1c8a1SJohn Marino  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48*f5b1c8a1SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49*f5b1c8a1SJohn Marino  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50*f5b1c8a1SJohn Marino  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51*f5b1c8a1SJohn Marino  * SUCH DAMAGE.
52*f5b1c8a1SJohn Marino  *
53*f5b1c8a1SJohn Marino  * The licence and distribution terms for any publically available version or
54*f5b1c8a1SJohn Marino  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55*f5b1c8a1SJohn Marino  * copied and put under another distribution licence
56*f5b1c8a1SJohn Marino  * [including the GNU Public Licence.]
57*f5b1c8a1SJohn Marino  */
58*f5b1c8a1SJohn Marino 
59*f5b1c8a1SJohn Marino #include <stdio.h>
60*f5b1c8a1SJohn Marino #include <stdlib.h>
61*f5b1c8a1SJohn Marino 
62*f5b1c8a1SJohn Marino #include "ssl_locl.h"
63*f5b1c8a1SJohn Marino 
64*f5b1c8a1SJohn Marino #include <openssl/objects.h>
65*f5b1c8a1SJohn Marino #include <openssl/x509.h>
66*f5b1c8a1SJohn Marino 
67*f5b1c8a1SJohn Marino /* XXX - these are here to avoid including asn1_mac.h */
68*f5b1c8a1SJohn Marino int asn1_GetSequence(ASN1_const_CTX *c, long *length);
69*f5b1c8a1SJohn Marino void asn1_add_error(const unsigned char *address, int offset);
70*f5b1c8a1SJohn Marino 
71*f5b1c8a1SJohn Marino typedef struct ssl_session_asn1_st {
72*f5b1c8a1SJohn Marino 	ASN1_INTEGER version;
73*f5b1c8a1SJohn Marino 	ASN1_INTEGER ssl_version;
74*f5b1c8a1SJohn Marino 	ASN1_OCTET_STRING cipher;
75*f5b1c8a1SJohn Marino 	ASN1_OCTET_STRING master_key;
76*f5b1c8a1SJohn Marino 	ASN1_OCTET_STRING session_id;
77*f5b1c8a1SJohn Marino 	ASN1_OCTET_STRING session_id_context;
78*f5b1c8a1SJohn Marino 	ASN1_INTEGER time;
79*f5b1c8a1SJohn Marino 	ASN1_INTEGER timeout;
80*f5b1c8a1SJohn Marino 	ASN1_INTEGER verify_result;
81*f5b1c8a1SJohn Marino 	ASN1_OCTET_STRING tlsext_hostname;
82*f5b1c8a1SJohn Marino 	ASN1_INTEGER tlsext_tick_lifetime;
83*f5b1c8a1SJohn Marino 	ASN1_OCTET_STRING tlsext_tick;
84*f5b1c8a1SJohn Marino } SSL_SESSION_ASN1;
85*f5b1c8a1SJohn Marino 
86*f5b1c8a1SJohn Marino int
87*f5b1c8a1SJohn Marino i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
88*f5b1c8a1SJohn Marino {
89*f5b1c8a1SJohn Marino #define LSIZE2 (sizeof(long)*2)
90*f5b1c8a1SJohn Marino 	int v1 = 0, v2 = 0, v3 = 0, v4 = 0, v5 = 0, v6 = 0, v9 = 0, v10 = 0;
91*f5b1c8a1SJohn Marino 	unsigned char buf[4], ibuf1[LSIZE2], ibuf2[LSIZE2];
92*f5b1c8a1SJohn Marino 	unsigned char ibuf3[LSIZE2], ibuf4[LSIZE2], ibuf5[LSIZE2];
93*f5b1c8a1SJohn Marino 	unsigned char ibuf6[LSIZE2];
94*f5b1c8a1SJohn Marino 	SSL_SESSION_ASN1 a;
95*f5b1c8a1SJohn Marino 	unsigned char *p;
96*f5b1c8a1SJohn Marino 	int len = 0, ret;
97*f5b1c8a1SJohn Marino 	long l;
98*f5b1c8a1SJohn Marino 
99*f5b1c8a1SJohn Marino 	if ((in == NULL) || ((in->cipher == NULL) && (in->cipher_id == 0)))
100*f5b1c8a1SJohn Marino 		return (0);
101*f5b1c8a1SJohn Marino 
102*f5b1c8a1SJohn Marino 	/*
103*f5b1c8a1SJohn Marino 	 * Note that I cheat in the following 2 assignments.
104*f5b1c8a1SJohn Marino 	 * I know that if the ASN1_INTEGER passed to ASN1_INTEGER_set
105*f5b1c8a1SJohn Marino 	 * is > sizeof(long)+1, the buffer will not be re-malloc()ed.
106*f5b1c8a1SJohn Marino 	 * This is a bit evil but makes things simple, no dynamic allocation
107*f5b1c8a1SJohn Marino 	 * to clean up :-)
108*f5b1c8a1SJohn Marino 	 */
109*f5b1c8a1SJohn Marino 	a.version.length = LSIZE2;
110*f5b1c8a1SJohn Marino 	a.version.type = V_ASN1_INTEGER;
111*f5b1c8a1SJohn Marino 	a.version.data = ibuf1;
112*f5b1c8a1SJohn Marino 	ASN1_INTEGER_set(&(a.version), SSL_SESSION_ASN1_VERSION);
113*f5b1c8a1SJohn Marino 	len += i2d_ASN1_INTEGER(&(a.version), NULL);
114*f5b1c8a1SJohn Marino 
115*f5b1c8a1SJohn Marino 	a.ssl_version.length = LSIZE2;
116*f5b1c8a1SJohn Marino 	a.ssl_version.type = V_ASN1_INTEGER;
117*f5b1c8a1SJohn Marino 	a.ssl_version.data = ibuf2;
118*f5b1c8a1SJohn Marino 	ASN1_INTEGER_set(&(a.ssl_version), in->ssl_version);
119*f5b1c8a1SJohn Marino 	len += i2d_ASN1_INTEGER(&(a.ssl_version), NULL);
120*f5b1c8a1SJohn Marino 
121*f5b1c8a1SJohn Marino 	a.cipher.length = 2;
122*f5b1c8a1SJohn Marino 	a.cipher.type = V_ASN1_OCTET_STRING;
123*f5b1c8a1SJohn Marino 	l = (in->cipher == NULL) ? in->cipher_id : in->cipher->id;
124*f5b1c8a1SJohn Marino 	buf[0] = ((unsigned char)(l >> 8L)) & 0xff;
125*f5b1c8a1SJohn Marino 	buf[1] = ((unsigned char)(l)) & 0xff;
126*f5b1c8a1SJohn Marino 	a.cipher.data = buf;
127*f5b1c8a1SJohn Marino 	len += i2d_ASN1_OCTET_STRING(&(a.cipher), NULL);
128*f5b1c8a1SJohn Marino 
129*f5b1c8a1SJohn Marino 	a.master_key.length = in->master_key_length;
130*f5b1c8a1SJohn Marino 	a.master_key.type = V_ASN1_OCTET_STRING;
131*f5b1c8a1SJohn Marino 	a.master_key.data = in->master_key;
132*f5b1c8a1SJohn Marino 	len += i2d_ASN1_OCTET_STRING(&(a.master_key), NULL);
133*f5b1c8a1SJohn Marino 
134*f5b1c8a1SJohn Marino 	a.session_id.length = in->session_id_length;
135*f5b1c8a1SJohn Marino 	a.session_id.type = V_ASN1_OCTET_STRING;
136*f5b1c8a1SJohn Marino 	a.session_id.data = in->session_id;
137*f5b1c8a1SJohn Marino 	len += i2d_ASN1_OCTET_STRING(&(a.session_id), NULL);
138*f5b1c8a1SJohn Marino 
139*f5b1c8a1SJohn Marino 	if (in->time != 0L) {
140*f5b1c8a1SJohn Marino 		a.time.length = LSIZE2;
141*f5b1c8a1SJohn Marino 		a.time.type = V_ASN1_INTEGER;
142*f5b1c8a1SJohn Marino 		a.time.data = ibuf3;
143*f5b1c8a1SJohn Marino 		ASN1_INTEGER_set(&(a.time), in->time);	/* XXX 2038 */
144*f5b1c8a1SJohn Marino 		v1 = i2d_ASN1_INTEGER(&(a.time), NULL);
145*f5b1c8a1SJohn Marino 		len += ASN1_object_size(1, v1, 1);
146*f5b1c8a1SJohn Marino 	}
147*f5b1c8a1SJohn Marino 
148*f5b1c8a1SJohn Marino 	if (in->timeout != 0L) {
149*f5b1c8a1SJohn Marino 		a.timeout.length = LSIZE2;
150*f5b1c8a1SJohn Marino 		a.timeout.type = V_ASN1_INTEGER;
151*f5b1c8a1SJohn Marino 		a.timeout.data = ibuf4;
152*f5b1c8a1SJohn Marino 		ASN1_INTEGER_set(&(a.timeout), in->timeout);
153*f5b1c8a1SJohn Marino 		v2 = i2d_ASN1_INTEGER(&(a.timeout), NULL);
154*f5b1c8a1SJohn Marino 		len += ASN1_object_size(1, v2, 2);
155*f5b1c8a1SJohn Marino 	}
156*f5b1c8a1SJohn Marino 
157*f5b1c8a1SJohn Marino 	if (in->peer != NULL) {
158*f5b1c8a1SJohn Marino 		v3 = i2d_X509(in->peer, NULL);
159*f5b1c8a1SJohn Marino 		len += ASN1_object_size(1, v3, 3);
160*f5b1c8a1SJohn Marino 	}
161*f5b1c8a1SJohn Marino 
162*f5b1c8a1SJohn Marino 	a.session_id_context.length = in->sid_ctx_length;
163*f5b1c8a1SJohn Marino 	a.session_id_context.type = V_ASN1_OCTET_STRING;
164*f5b1c8a1SJohn Marino 	a.session_id_context.data = in->sid_ctx;
165*f5b1c8a1SJohn Marino 	v4 = i2d_ASN1_OCTET_STRING(&(a.session_id_context), NULL);
166*f5b1c8a1SJohn Marino 	len += ASN1_object_size(1, v4, 4);
167*f5b1c8a1SJohn Marino 
168*f5b1c8a1SJohn Marino 	if (in->verify_result != X509_V_OK) {
169*f5b1c8a1SJohn Marino 		a.verify_result.length = LSIZE2;
170*f5b1c8a1SJohn Marino 		a.verify_result.type = V_ASN1_INTEGER;
171*f5b1c8a1SJohn Marino 		a.verify_result.data = ibuf5;
172*f5b1c8a1SJohn Marino 		ASN1_INTEGER_set(&a.verify_result, in->verify_result);
173*f5b1c8a1SJohn Marino 		v5 = i2d_ASN1_INTEGER(&(a.verify_result), NULL);
174*f5b1c8a1SJohn Marino 		len += ASN1_object_size(1, v5, 5);
175*f5b1c8a1SJohn Marino 	}
176*f5b1c8a1SJohn Marino 
177*f5b1c8a1SJohn Marino 	if (in->tlsext_hostname) {
178*f5b1c8a1SJohn Marino 		a.tlsext_hostname.length = strlen(in->tlsext_hostname);
179*f5b1c8a1SJohn Marino 		a.tlsext_hostname.type = V_ASN1_OCTET_STRING;
180*f5b1c8a1SJohn Marino 		a.tlsext_hostname.data = (unsigned char *)in->tlsext_hostname;
181*f5b1c8a1SJohn Marino 		v6 = i2d_ASN1_OCTET_STRING(&(a.tlsext_hostname), NULL);
182*f5b1c8a1SJohn Marino 		len += ASN1_object_size(1, v6, 6);
183*f5b1c8a1SJohn Marino 	}
184*f5b1c8a1SJohn Marino 
185*f5b1c8a1SJohn Marino 	/* 7 - PSK identity hint. */
186*f5b1c8a1SJohn Marino 	/* 8 - PSK identity. */
187*f5b1c8a1SJohn Marino 
188*f5b1c8a1SJohn Marino 	if (in->tlsext_tick_lifetime_hint > 0) {
189*f5b1c8a1SJohn Marino 		a.tlsext_tick_lifetime.length = LSIZE2;
190*f5b1c8a1SJohn Marino 		a.tlsext_tick_lifetime.type = V_ASN1_INTEGER;
191*f5b1c8a1SJohn Marino 		a.tlsext_tick_lifetime.data = ibuf6;
192*f5b1c8a1SJohn Marino 		ASN1_INTEGER_set(&a.tlsext_tick_lifetime,
193*f5b1c8a1SJohn Marino 		    in->tlsext_tick_lifetime_hint);
194*f5b1c8a1SJohn Marino 		v9 = i2d_ASN1_INTEGER(&(a.tlsext_tick_lifetime), NULL);
195*f5b1c8a1SJohn Marino 		len += ASN1_object_size(1, v9, 9);
196*f5b1c8a1SJohn Marino 	}
197*f5b1c8a1SJohn Marino 
198*f5b1c8a1SJohn Marino 	if (in->tlsext_tick) {
199*f5b1c8a1SJohn Marino 		a.tlsext_tick.length = in->tlsext_ticklen;
200*f5b1c8a1SJohn Marino 		a.tlsext_tick.type = V_ASN1_OCTET_STRING;
201*f5b1c8a1SJohn Marino 		a.tlsext_tick.data = (unsigned char *)in->tlsext_tick;
202*f5b1c8a1SJohn Marino 		v10 = i2d_ASN1_OCTET_STRING(&(a.tlsext_tick), NULL);
203*f5b1c8a1SJohn Marino 		len += ASN1_object_size(1, v10, 10);
204*f5b1c8a1SJohn Marino 	}
205*f5b1c8a1SJohn Marino 
206*f5b1c8a1SJohn Marino 	/* 11 - Compression method. */
207*f5b1c8a1SJohn Marino 	/* 12 - SRP username. */
208*f5b1c8a1SJohn Marino 
209*f5b1c8a1SJohn Marino 	/* If given a NULL pointer, return the length only. */
210*f5b1c8a1SJohn Marino 	ret = (ASN1_object_size(1, len, V_ASN1_SEQUENCE));
211*f5b1c8a1SJohn Marino 	if (pp == NULL)
212*f5b1c8a1SJohn Marino 		return (ret);
213*f5b1c8a1SJohn Marino 
214*f5b1c8a1SJohn Marino 	/* Burp out the ASN1. */
215*f5b1c8a1SJohn Marino 	p = *pp;
216*f5b1c8a1SJohn Marino 	ASN1_put_object(&p, 1, len, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL);
217*f5b1c8a1SJohn Marino 	i2d_ASN1_INTEGER(&(a.version), &p);
218*f5b1c8a1SJohn Marino 	i2d_ASN1_INTEGER(&(a.ssl_version), &p);
219*f5b1c8a1SJohn Marino 	i2d_ASN1_OCTET_STRING(&(a.cipher), &p);
220*f5b1c8a1SJohn Marino 	i2d_ASN1_OCTET_STRING(&(a.session_id), &p);
221*f5b1c8a1SJohn Marino 	i2d_ASN1_OCTET_STRING(&(a.master_key), &p);
222*f5b1c8a1SJohn Marino 	if (in->time != 0L) {
223*f5b1c8a1SJohn Marino 		ASN1_put_object(&p, 1, v1, 1, V_ASN1_CONTEXT_SPECIFIC);
224*f5b1c8a1SJohn Marino 		i2d_ASN1_INTEGER(&(a.time), &p);
225*f5b1c8a1SJohn Marino 	}
226*f5b1c8a1SJohn Marino 	if (in->timeout != 0L) {
227*f5b1c8a1SJohn Marino 		ASN1_put_object(&p, 1, v2, 2, V_ASN1_CONTEXT_SPECIFIC);
228*f5b1c8a1SJohn Marino 		i2d_ASN1_INTEGER(&(a.timeout), &p);
229*f5b1c8a1SJohn Marino 	}
230*f5b1c8a1SJohn Marino 	if (in->peer != NULL) {
231*f5b1c8a1SJohn Marino 		ASN1_put_object(&p, 1, v3, 3, V_ASN1_CONTEXT_SPECIFIC);
232*f5b1c8a1SJohn Marino 		i2d_X509(in->peer, &p);
233*f5b1c8a1SJohn Marino 	}
234*f5b1c8a1SJohn Marino 	ASN1_put_object(&p, 1, v4, 4, V_ASN1_CONTEXT_SPECIFIC);
235*f5b1c8a1SJohn Marino 	i2d_ASN1_OCTET_STRING(&(a.session_id_context), &p);
236*f5b1c8a1SJohn Marino 	if (in->verify_result != X509_V_OK) {
237*f5b1c8a1SJohn Marino 		ASN1_put_object(&p, 1, v5, 5, V_ASN1_CONTEXT_SPECIFIC);
238*f5b1c8a1SJohn Marino 		i2d_ASN1_INTEGER(&(a.verify_result), &p);
239*f5b1c8a1SJohn Marino 	}
240*f5b1c8a1SJohn Marino 	if (in->tlsext_hostname) {
241*f5b1c8a1SJohn Marino 		ASN1_put_object(&p, 1, v6, 6, V_ASN1_CONTEXT_SPECIFIC);
242*f5b1c8a1SJohn Marino 		i2d_ASN1_OCTET_STRING(&(a.tlsext_hostname), &p);
243*f5b1c8a1SJohn Marino 	}
244*f5b1c8a1SJohn Marino 	/* 7 - PSK identity hint. */
245*f5b1c8a1SJohn Marino 	/* 8 - PSK identity. */
246*f5b1c8a1SJohn Marino 	if (in->tlsext_tick_lifetime_hint > 0) {
247*f5b1c8a1SJohn Marino 		ASN1_put_object(&p, 1, v9, 9, V_ASN1_CONTEXT_SPECIFIC);
248*f5b1c8a1SJohn Marino 		i2d_ASN1_INTEGER(&(a.tlsext_tick_lifetime), &p);
249*f5b1c8a1SJohn Marino 	}
250*f5b1c8a1SJohn Marino 	if (in->tlsext_tick) {
251*f5b1c8a1SJohn Marino 		ASN1_put_object(&p, 1, v10, 10, V_ASN1_CONTEXT_SPECIFIC);
252*f5b1c8a1SJohn Marino 		i2d_ASN1_OCTET_STRING(&(a.tlsext_tick), &p);
253*f5b1c8a1SJohn Marino 	}
254*f5b1c8a1SJohn Marino 	/* 11 - Compression method. */
255*f5b1c8a1SJohn Marino 	/* 12 - SRP username. */
256*f5b1c8a1SJohn Marino 
257*f5b1c8a1SJohn Marino 	*pp = p;
258*f5b1c8a1SJohn Marino 	return (ret);
259*f5b1c8a1SJohn Marino }
260*f5b1c8a1SJohn Marino 
261*f5b1c8a1SJohn Marino SSL_SESSION *
262*f5b1c8a1SJohn Marino d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp, long length)
263*f5b1c8a1SJohn Marino {
264*f5b1c8a1SJohn Marino 	SSL_SESSION *ret = NULL;
265*f5b1c8a1SJohn Marino 	ASN1_const_CTX c;
266*f5b1c8a1SJohn Marino 	ASN1_INTEGER ai, *aip;
267*f5b1c8a1SJohn Marino 	ASN1_OCTET_STRING os, *osp;
268*f5b1c8a1SJohn Marino 	int ssl_version = 0, i;
269*f5b1c8a1SJohn Marino 	int Tinf, Ttag, Tclass;
270*f5b1c8a1SJohn Marino 	long Tlen;
271*f5b1c8a1SJohn Marino 	long id;
272*f5b1c8a1SJohn Marino 
273*f5b1c8a1SJohn Marino 	c.pp = pp;
274*f5b1c8a1SJohn Marino 	c.p = *pp;
275*f5b1c8a1SJohn Marino 	c.q = *pp;
276*f5b1c8a1SJohn Marino 	c.max = (length == 0) ? 0 : (c.p + length);
277*f5b1c8a1SJohn Marino 	c.slen = length;
278*f5b1c8a1SJohn Marino 
279*f5b1c8a1SJohn Marino 	if (a == NULL || *a == NULL) {
280*f5b1c8a1SJohn Marino 		if ((ret = SSL_SESSION_new()) == NULL) {
281*f5b1c8a1SJohn Marino 			SSLerr(SSL_F_D2I_SSL_SESSION, ERR_R_NESTED_ASN1_ERROR);
282*f5b1c8a1SJohn Marino 			goto err;
283*f5b1c8a1SJohn Marino 		}
284*f5b1c8a1SJohn Marino 	} else
285*f5b1c8a1SJohn Marino 		ret = *a;
286*f5b1c8a1SJohn Marino 
287*f5b1c8a1SJohn Marino 	aip = &ai;
288*f5b1c8a1SJohn Marino 	osp = &os;
289*f5b1c8a1SJohn Marino 
290*f5b1c8a1SJohn Marino 	if (!asn1_GetSequence(&c, &length)) {
291*f5b1c8a1SJohn Marino 		SSLerr(SSL_F_D2I_SSL_SESSION, ERR_R_NESTED_ASN1_ERROR);
292*f5b1c8a1SJohn Marino 		goto err;
293*f5b1c8a1SJohn Marino 	}
294*f5b1c8a1SJohn Marino 
295*f5b1c8a1SJohn Marino 	ai.data = NULL;
296*f5b1c8a1SJohn Marino 	ai.length = 0;
297*f5b1c8a1SJohn Marino 	c.q = c.p;
298*f5b1c8a1SJohn Marino 	if (d2i_ASN1_INTEGER(&aip, &c.p, c.slen) == NULL) {
299*f5b1c8a1SJohn Marino 		SSLerr(SSL_F_D2I_SSL_SESSION, ERR_R_NESTED_ASN1_ERROR);
300*f5b1c8a1SJohn Marino 		goto err;
301*f5b1c8a1SJohn Marino 	}
302*f5b1c8a1SJohn Marino 	c.slen -= (c.p - c.q);
303*f5b1c8a1SJohn Marino 
304*f5b1c8a1SJohn Marino 	if (ai.data != NULL) {
305*f5b1c8a1SJohn Marino 		free(ai.data);
306*f5b1c8a1SJohn Marino 		ai.data = NULL;
307*f5b1c8a1SJohn Marino 		ai.length = 0;
308*f5b1c8a1SJohn Marino 	}
309*f5b1c8a1SJohn Marino 
310*f5b1c8a1SJohn Marino 	/* we don't care about the version right now :-) */
311*f5b1c8a1SJohn Marino 	c.q = c.p;
312*f5b1c8a1SJohn Marino 	if (d2i_ASN1_INTEGER(&aip, &c.p, c.slen) == NULL) {
313*f5b1c8a1SJohn Marino 		SSLerr(SSL_F_D2I_SSL_SESSION, ERR_R_NESTED_ASN1_ERROR);
314*f5b1c8a1SJohn Marino 		goto err;
315*f5b1c8a1SJohn Marino 	}
316*f5b1c8a1SJohn Marino 	c.slen -= (c.p - c.q);
317*f5b1c8a1SJohn Marino 	ssl_version = (int)ASN1_INTEGER_get(aip);
318*f5b1c8a1SJohn Marino 	ret->ssl_version = ssl_version;
319*f5b1c8a1SJohn Marino 	if (ai.data != NULL) {
320*f5b1c8a1SJohn Marino 		free(ai.data);
321*f5b1c8a1SJohn Marino 		ai.data = NULL;
322*f5b1c8a1SJohn Marino 		ai.length = 0;
323*f5b1c8a1SJohn Marino 	}
324*f5b1c8a1SJohn Marino 
325*f5b1c8a1SJohn Marino 	os.data = NULL;
326*f5b1c8a1SJohn Marino 	os.length = 0;
327*f5b1c8a1SJohn Marino 	c.q = c.p;
328*f5b1c8a1SJohn Marino 	if (d2i_ASN1_OCTET_STRING(&osp, &c.p, c.slen) == NULL) {
329*f5b1c8a1SJohn Marino 		SSLerr(SSL_F_D2I_SSL_SESSION, ERR_R_NESTED_ASN1_ERROR);
330*f5b1c8a1SJohn Marino 		goto err;
331*f5b1c8a1SJohn Marino 	}
332*f5b1c8a1SJohn Marino 	c.slen -= (c.p - c.q);
333*f5b1c8a1SJohn Marino 	if ((ssl_version >> 8) >= SSL3_VERSION_MAJOR) {
334*f5b1c8a1SJohn Marino 		if (os.length != 2) {
335*f5b1c8a1SJohn Marino 			SSLerr(SSL_F_D2I_SSL_SESSION,
336*f5b1c8a1SJohn Marino 			    SSL_R_CIPHER_CODE_WRONG_LENGTH);
337*f5b1c8a1SJohn Marino 			goto err;
338*f5b1c8a1SJohn Marino 		}
339*f5b1c8a1SJohn Marino 		id = 0x03000000L | ((unsigned long)os.data[0]<<8L) |
340*f5b1c8a1SJohn Marino 		    (unsigned long)os.data[1];
341*f5b1c8a1SJohn Marino 	} else {
342*f5b1c8a1SJohn Marino 		SSLerr(SSL_F_D2I_SSL_SESSION, SSL_R_UNKNOWN_SSL_VERSION);
343*f5b1c8a1SJohn Marino 		goto err;
344*f5b1c8a1SJohn Marino 	}
345*f5b1c8a1SJohn Marino 
346*f5b1c8a1SJohn Marino 	ret->cipher = NULL;
347*f5b1c8a1SJohn Marino 	ret->cipher_id = id;
348*f5b1c8a1SJohn Marino 
349*f5b1c8a1SJohn Marino 	c.q = c.p;
350*f5b1c8a1SJohn Marino 	if (d2i_ASN1_OCTET_STRING(&osp, &c.p, c.slen) == NULL) {
351*f5b1c8a1SJohn Marino 		SSLerr(SSL_F_D2I_SSL_SESSION, ERR_R_NESTED_ASN1_ERROR);
352*f5b1c8a1SJohn Marino 		goto err;
353*f5b1c8a1SJohn Marino 	}
354*f5b1c8a1SJohn Marino 	c.slen -= (c.p - c.q);
355*f5b1c8a1SJohn Marino 
356*f5b1c8a1SJohn Marino 	i = SSL3_MAX_SSL_SESSION_ID_LENGTH;
357*f5b1c8a1SJohn Marino 	if (os.length > i)
358*f5b1c8a1SJohn Marino 		os.length = i;
359*f5b1c8a1SJohn Marino 	if (os.length > (int)sizeof(ret->session_id)) /* can't happen */
360*f5b1c8a1SJohn Marino 		os.length = sizeof(ret->session_id);
361*f5b1c8a1SJohn Marino 
362*f5b1c8a1SJohn Marino 	ret->session_id_length = os.length;
363*f5b1c8a1SJohn Marino 	OPENSSL_assert(os.length <= (int)sizeof(ret->session_id));
364*f5b1c8a1SJohn Marino 	memcpy(ret->session_id, os.data, os.length);
365*f5b1c8a1SJohn Marino 
366*f5b1c8a1SJohn Marino 	c.q = c.p;
367*f5b1c8a1SJohn Marino 	if (d2i_ASN1_OCTET_STRING(&osp, &c.p, c.slen) == NULL) {
368*f5b1c8a1SJohn Marino 		SSLerr(SSL_F_D2I_SSL_SESSION, ERR_R_NESTED_ASN1_ERROR);
369*f5b1c8a1SJohn Marino 		goto err;
370*f5b1c8a1SJohn Marino 	}
371*f5b1c8a1SJohn Marino 	c.slen -= (c.p - c.q);
372*f5b1c8a1SJohn Marino 	if (os.length > SSL_MAX_MASTER_KEY_LENGTH)
373*f5b1c8a1SJohn Marino 		ret->master_key_length = SSL_MAX_MASTER_KEY_LENGTH;
374*f5b1c8a1SJohn Marino 	else
375*f5b1c8a1SJohn Marino 		ret->master_key_length = os.length;
376*f5b1c8a1SJohn Marino 	memcpy(ret->master_key, os.data, ret->master_key_length);
377*f5b1c8a1SJohn Marino 
378*f5b1c8a1SJohn Marino 	os.length = 0;
379*f5b1c8a1SJohn Marino 
380*f5b1c8a1SJohn Marino 	/* 1 - Time (INTEGER). */
381*f5b1c8a1SJohn Marino 	/* XXX 2038 */
382*f5b1c8a1SJohn Marino 	ai.length = 0;
383*f5b1c8a1SJohn Marino 	if (c.slen != 0L &&
384*f5b1c8a1SJohn Marino 	    *c.p == (V_ASN1_CONSTRUCTED | V_ASN1_CONTEXT_SPECIFIC | 1)) {
385*f5b1c8a1SJohn Marino 		c.q = c.p;
386*f5b1c8a1SJohn Marino 		Tinf = ASN1_get_object(&c.p, &Tlen, &Ttag, &Tclass, c.slen);
387*f5b1c8a1SJohn Marino 		if (Tinf & 0x80) {
388*f5b1c8a1SJohn Marino 			SSLerr(SSL_F_D2I_SSL_SESSION,
389*f5b1c8a1SJohn Marino 			    ERR_R_BAD_ASN1_OBJECT_HEADER);
390*f5b1c8a1SJohn Marino 			goto err;
391*f5b1c8a1SJohn Marino 		}
392*f5b1c8a1SJohn Marino 		if (Tinf == (V_ASN1_CONSTRUCTED + 1))
393*f5b1c8a1SJohn Marino 			Tlen = c.slen - (c.p - c.q) - 2;
394*f5b1c8a1SJohn Marino 		if (d2i_ASN1_INTEGER(&aip, &c.p, Tlen) == NULL) {
395*f5b1c8a1SJohn Marino 			SSLerr(SSL_F_D2I_SSL_SESSION, ERR_R_NESTED_ASN1_ERROR);
396*f5b1c8a1SJohn Marino 			goto err;
397*f5b1c8a1SJohn Marino 		}
398*f5b1c8a1SJohn Marino 		if (Tinf == (V_ASN1_CONSTRUCTED + 1)) {
399*f5b1c8a1SJohn Marino 			Tlen = c.slen - (c.p - c.q);
400*f5b1c8a1SJohn Marino 			if(!ASN1_const_check_infinite_end(&c.p, Tlen)) {
401*f5b1c8a1SJohn Marino 				SSLerr(SSL_F_D2I_SSL_SESSION,
402*f5b1c8a1SJohn Marino 				    ERR_R_MISSING_ASN1_EOS);
403*f5b1c8a1SJohn Marino 				goto err;
404*f5b1c8a1SJohn Marino 			}
405*f5b1c8a1SJohn Marino 		}
406*f5b1c8a1SJohn Marino 		c.slen -= (c.p - c.q);
407*f5b1c8a1SJohn Marino 	}
408*f5b1c8a1SJohn Marino 	if (ai.data != NULL) {
409*f5b1c8a1SJohn Marino 		ret->time = ASN1_INTEGER_get(aip);
410*f5b1c8a1SJohn Marino 		free(ai.data);
411*f5b1c8a1SJohn Marino 		ai.data = NULL;
412*f5b1c8a1SJohn Marino 		ai.length = 0;
413*f5b1c8a1SJohn Marino 	} else
414*f5b1c8a1SJohn Marino 		ret->time = time(NULL);
415*f5b1c8a1SJohn Marino 
416*f5b1c8a1SJohn Marino 	/* 2 - Timeout (INTEGER). */
417*f5b1c8a1SJohn Marino 	ai.length = 0;
418*f5b1c8a1SJohn Marino 	if (c.slen != 0L &&
419*f5b1c8a1SJohn Marino 	    *c.p == (V_ASN1_CONSTRUCTED | V_ASN1_CONTEXT_SPECIFIC | 2)) {
420*f5b1c8a1SJohn Marino 		c.q = c.p;
421*f5b1c8a1SJohn Marino 		Tinf = ASN1_get_object(&c.p, &Tlen, &Ttag, &Tclass, c.slen);
422*f5b1c8a1SJohn Marino 		if (Tinf & 0x80) {
423*f5b1c8a1SJohn Marino 			SSLerr(SSL_F_D2I_SSL_SESSION,
424*f5b1c8a1SJohn Marino 			    ERR_R_BAD_ASN1_OBJECT_HEADER);
425*f5b1c8a1SJohn Marino 			goto err;
426*f5b1c8a1SJohn Marino 		}
427*f5b1c8a1SJohn Marino 		if (Tinf == (V_ASN1_CONSTRUCTED + 1))
428*f5b1c8a1SJohn Marino 			Tlen = c.slen - (c.p - c.q) - 2;
429*f5b1c8a1SJohn Marino 		if (d2i_ASN1_INTEGER(&aip, &c.p, Tlen) == NULL) {
430*f5b1c8a1SJohn Marino 			SSLerr(SSL_F_D2I_SSL_SESSION, ERR_R_NESTED_ASN1_ERROR);
431*f5b1c8a1SJohn Marino 			goto err;
432*f5b1c8a1SJohn Marino 		}
433*f5b1c8a1SJohn Marino 		if (Tinf == (V_ASN1_CONSTRUCTED + 1)) {
434*f5b1c8a1SJohn Marino 			Tlen = c.slen - (c.p - c.q);
435*f5b1c8a1SJohn Marino 			if(!ASN1_const_check_infinite_end(&c.p, Tlen)) {
436*f5b1c8a1SJohn Marino 				SSLerr(SSL_F_D2I_SSL_SESSION,
437*f5b1c8a1SJohn Marino 				    ERR_R_MISSING_ASN1_EOS);
438*f5b1c8a1SJohn Marino 				goto err;
439*f5b1c8a1SJohn Marino 			}
440*f5b1c8a1SJohn Marino 		}
441*f5b1c8a1SJohn Marino 		c.slen -= (c.p - c.q);
442*f5b1c8a1SJohn Marino 	}
443*f5b1c8a1SJohn Marino 	if (ai.data != NULL) {
444*f5b1c8a1SJohn Marino 		ret->timeout = ASN1_INTEGER_get(aip);
445*f5b1c8a1SJohn Marino 		free(ai.data);
446*f5b1c8a1SJohn Marino 		ai.data = NULL;
447*f5b1c8a1SJohn Marino 		ai.length = 0;
448*f5b1c8a1SJohn Marino 	} else
449*f5b1c8a1SJohn Marino 		ret->timeout = 3;
450*f5b1c8a1SJohn Marino 
451*f5b1c8a1SJohn Marino 	/* 3 - Peer (X509). */
452*f5b1c8a1SJohn Marino 	X509_free(ret->peer);
453*f5b1c8a1SJohn Marino 	ret->peer = NULL;
454*f5b1c8a1SJohn Marino 
455*f5b1c8a1SJohn Marino 	if (c.slen != 0L &&
456*f5b1c8a1SJohn Marino 	    *c.p == (V_ASN1_CONSTRUCTED | V_ASN1_CONTEXT_SPECIFIC | 3)) {
457*f5b1c8a1SJohn Marino 		c.q = c.p;
458*f5b1c8a1SJohn Marino 		Tinf = ASN1_get_object(&c.p, &Tlen, &Ttag, &Tclass, c.slen);
459*f5b1c8a1SJohn Marino 		if (Tinf & 0x80) {
460*f5b1c8a1SJohn Marino 			SSLerr(SSL_F_D2I_SSL_SESSION,
461*f5b1c8a1SJohn Marino 			    ERR_R_BAD_ASN1_OBJECT_HEADER);
462*f5b1c8a1SJohn Marino 			goto err;
463*f5b1c8a1SJohn Marino 		}
464*f5b1c8a1SJohn Marino 		if (Tinf == (V_ASN1_CONSTRUCTED + 1))
465*f5b1c8a1SJohn Marino 			Tlen = c.slen - (c.p - c.q) - 2;
466*f5b1c8a1SJohn Marino 		if (d2i_X509(&ret->peer, &c.p, Tlen) == NULL) {
467*f5b1c8a1SJohn Marino 			SSLerr(SSL_F_D2I_SSL_SESSION, ERR_R_NESTED_ASN1_ERROR);
468*f5b1c8a1SJohn Marino 			goto err;
469*f5b1c8a1SJohn Marino 		}
470*f5b1c8a1SJohn Marino 		if (Tinf == (V_ASN1_CONSTRUCTED + 1)) {
471*f5b1c8a1SJohn Marino 			Tlen = c.slen - (c.p - c.q);
472*f5b1c8a1SJohn Marino 			if(!ASN1_const_check_infinite_end(&c.p, Tlen)) {
473*f5b1c8a1SJohn Marino 				SSLerr(SSL_F_D2I_SSL_SESSION,
474*f5b1c8a1SJohn Marino 				    ERR_R_MISSING_ASN1_EOS);
475*f5b1c8a1SJohn Marino 				goto err;
476*f5b1c8a1SJohn Marino 			}
477*f5b1c8a1SJohn Marino 		}
478*f5b1c8a1SJohn Marino 		c.slen -= (c.p - c.q);
479*f5b1c8a1SJohn Marino 	}
480*f5b1c8a1SJohn Marino 
481*f5b1c8a1SJohn Marino 	/* 4 - Session ID (OCTET STRING). */
482*f5b1c8a1SJohn Marino 	os.length = 0;
483*f5b1c8a1SJohn Marino 	free(os.data);
484*f5b1c8a1SJohn Marino 	os.data = NULL;
485*f5b1c8a1SJohn Marino 	if (c.slen != 0L &&
486*f5b1c8a1SJohn Marino 	    *c.p == (V_ASN1_CONSTRUCTED | V_ASN1_CONTEXT_SPECIFIC | 4)) {
487*f5b1c8a1SJohn Marino 		c.q = c.p;
488*f5b1c8a1SJohn Marino 		Tinf = ASN1_get_object(&c.p, &Tlen, &Ttag, &Tclass, c.slen);
489*f5b1c8a1SJohn Marino 		if (Tinf & 0x80) {
490*f5b1c8a1SJohn Marino 			SSLerr(SSL_F_D2I_SSL_SESSION,
491*f5b1c8a1SJohn Marino 			    ERR_R_BAD_ASN1_OBJECT_HEADER);
492*f5b1c8a1SJohn Marino 			goto err;
493*f5b1c8a1SJohn Marino 		}
494*f5b1c8a1SJohn Marino 		if (Tinf == (V_ASN1_CONSTRUCTED + 1))
495*f5b1c8a1SJohn Marino 			Tlen = c.slen - (c.p - c.q) - 2;
496*f5b1c8a1SJohn Marino 		if (d2i_ASN1_OCTET_STRING(&osp, &c.p, Tlen) == NULL) {
497*f5b1c8a1SJohn Marino 			SSLerr(SSL_F_D2I_SSL_SESSION, ERR_R_NESTED_ASN1_ERROR);
498*f5b1c8a1SJohn Marino 			goto err;
499*f5b1c8a1SJohn Marino 		}
500*f5b1c8a1SJohn Marino 		if (Tinf == (V_ASN1_CONSTRUCTED + 1)) {
501*f5b1c8a1SJohn Marino 			Tlen = c.slen - (c.p - c.q);
502*f5b1c8a1SJohn Marino 			if(!ASN1_const_check_infinite_end(&c.p, Tlen)) {
503*f5b1c8a1SJohn Marino 				SSLerr(SSL_F_D2I_SSL_SESSION,
504*f5b1c8a1SJohn Marino 				    ERR_R_MISSING_ASN1_EOS);
505*f5b1c8a1SJohn Marino 				goto err;
506*f5b1c8a1SJohn Marino 			}
507*f5b1c8a1SJohn Marino 		}
508*f5b1c8a1SJohn Marino 		c.slen -= (c.p - c.q);
509*f5b1c8a1SJohn Marino 	}
510*f5b1c8a1SJohn Marino 	if (os.data != NULL) {
511*f5b1c8a1SJohn Marino 		if (os.length > SSL_MAX_SID_CTX_LENGTH) {
512*f5b1c8a1SJohn Marino 			SSLerr(SSL_F_D2I_SSL_SESSION, SSL_R_BAD_LENGTH);
513*f5b1c8a1SJohn Marino 			goto err;
514*f5b1c8a1SJohn Marino 		} else {
515*f5b1c8a1SJohn Marino 			ret->sid_ctx_length = os.length;
516*f5b1c8a1SJohn Marino 			memcpy(ret->sid_ctx, os.data, os.length);
517*f5b1c8a1SJohn Marino 		}
518*f5b1c8a1SJohn Marino 		free(os.data);
519*f5b1c8a1SJohn Marino 		os.data = NULL;
520*f5b1c8a1SJohn Marino 		os.length = 0;
521*f5b1c8a1SJohn Marino 	} else
522*f5b1c8a1SJohn Marino 		ret->sid_ctx_length = 0;
523*f5b1c8a1SJohn Marino 
524*f5b1c8a1SJohn Marino 	/* 5 - Verify_result. */
525*f5b1c8a1SJohn Marino 	ai.length = 0;
526*f5b1c8a1SJohn Marino 	if (c.slen != 0L &&
527*f5b1c8a1SJohn Marino 	    *c.p == (V_ASN1_CONSTRUCTED | V_ASN1_CONTEXT_SPECIFIC | 5)) {
528*f5b1c8a1SJohn Marino 		c.q = c.p;
529*f5b1c8a1SJohn Marino 		Tinf = ASN1_get_object(&c.p, &Tlen, &Ttag, &Tclass, c.slen);
530*f5b1c8a1SJohn Marino 		if (Tinf & 0x80) {
531*f5b1c8a1SJohn Marino 			SSLerr(SSL_F_D2I_SSL_SESSION,
532*f5b1c8a1SJohn Marino 			    ERR_R_BAD_ASN1_OBJECT_HEADER);
533*f5b1c8a1SJohn Marino 			goto err;
534*f5b1c8a1SJohn Marino 		}
535*f5b1c8a1SJohn Marino 		if (Tinf == (V_ASN1_CONSTRUCTED + 1))
536*f5b1c8a1SJohn Marino 			Tlen = c.slen - (c.p - c.q) - 2;
537*f5b1c8a1SJohn Marino 		if (d2i_ASN1_INTEGER(&aip, &c.p, Tlen) == NULL) {
538*f5b1c8a1SJohn Marino 			SSLerr(SSL_F_D2I_SSL_SESSION, ERR_R_NESTED_ASN1_ERROR);
539*f5b1c8a1SJohn Marino 			goto err;
540*f5b1c8a1SJohn Marino 		}
541*f5b1c8a1SJohn Marino 		if (Tinf == (V_ASN1_CONSTRUCTED + 1)) {
542*f5b1c8a1SJohn Marino 			Tlen = c.slen - (c.p - c.q);
543*f5b1c8a1SJohn Marino 			if(!ASN1_const_check_infinite_end(&c.p, Tlen)) {
544*f5b1c8a1SJohn Marino 				SSLerr(SSL_F_D2I_SSL_SESSION,
545*f5b1c8a1SJohn Marino 				    ERR_R_MISSING_ASN1_EOS);
546*f5b1c8a1SJohn Marino 				goto err;
547*f5b1c8a1SJohn Marino 			}
548*f5b1c8a1SJohn Marino 		}
549*f5b1c8a1SJohn Marino 		c.slen -= (c.p - c.q);
550*f5b1c8a1SJohn Marino 	}
551*f5b1c8a1SJohn Marino 	if (ai.data != NULL) {
552*f5b1c8a1SJohn Marino 		ret->verify_result = ASN1_INTEGER_get(aip);
553*f5b1c8a1SJohn Marino 		free(ai.data);
554*f5b1c8a1SJohn Marino 		ai.data = NULL;
555*f5b1c8a1SJohn Marino 		ai.length = 0;
556*f5b1c8a1SJohn Marino 	} else
557*f5b1c8a1SJohn Marino 		ret->verify_result = X509_V_OK;
558*f5b1c8a1SJohn Marino 
559*f5b1c8a1SJohn Marino 	/* 6 - HostName (OCTET STRING). */
560*f5b1c8a1SJohn Marino 	os.length = 0;
561*f5b1c8a1SJohn Marino 	os.data = NULL;
562*f5b1c8a1SJohn Marino 	if (c.slen != 0L &&
563*f5b1c8a1SJohn Marino 	    *c.p == (V_ASN1_CONSTRUCTED | V_ASN1_CONTEXT_SPECIFIC | 6)) {
564*f5b1c8a1SJohn Marino 		c.q = c.p;
565*f5b1c8a1SJohn Marino 		Tinf = ASN1_get_object(&c.p, &Tlen, &Ttag, &Tclass, c.slen);
566*f5b1c8a1SJohn Marino 		if (Tinf & 0x80) {
567*f5b1c8a1SJohn Marino 			SSLerr(SSL_F_D2I_SSL_SESSION,
568*f5b1c8a1SJohn Marino 			    ERR_R_BAD_ASN1_OBJECT_HEADER);
569*f5b1c8a1SJohn Marino 			goto err;
570*f5b1c8a1SJohn Marino 		}
571*f5b1c8a1SJohn Marino 		if (Tinf == (V_ASN1_CONSTRUCTED + 1))
572*f5b1c8a1SJohn Marino 			Tlen = c.slen - (c.p - c.q) - 2;
573*f5b1c8a1SJohn Marino 		if (d2i_ASN1_OCTET_STRING(&osp, &c.p, Tlen) == NULL) {
574*f5b1c8a1SJohn Marino 			SSLerr(SSL_F_D2I_SSL_SESSION, ERR_R_NESTED_ASN1_ERROR);
575*f5b1c8a1SJohn Marino 			goto err;
576*f5b1c8a1SJohn Marino 		}
577*f5b1c8a1SJohn Marino 		if (Tinf == (V_ASN1_CONSTRUCTED + 1)) {
578*f5b1c8a1SJohn Marino 			Tlen = c.slen - (c.p - c.q);
579*f5b1c8a1SJohn Marino 			if(!ASN1_const_check_infinite_end(&c.p, Tlen)) {
580*f5b1c8a1SJohn Marino 				SSLerr(SSL_F_D2I_SSL_SESSION,
581*f5b1c8a1SJohn Marino 				    ERR_R_MISSING_ASN1_EOS);
582*f5b1c8a1SJohn Marino 				goto err;
583*f5b1c8a1SJohn Marino 			}
584*f5b1c8a1SJohn Marino 		}
585*f5b1c8a1SJohn Marino 		c.slen -= (c.p - c.q);
586*f5b1c8a1SJohn Marino 	}
587*f5b1c8a1SJohn Marino 	if (os.data) {
588*f5b1c8a1SJohn Marino 		ret->tlsext_hostname = strndup((char *)os.data, os.length);
589*f5b1c8a1SJohn Marino 		free(os.data);
590*f5b1c8a1SJohn Marino 		os.data = NULL;
591*f5b1c8a1SJohn Marino 		os.length = 0;
592*f5b1c8a1SJohn Marino 	} else
593*f5b1c8a1SJohn Marino 		ret->tlsext_hostname = NULL;
594*f5b1c8a1SJohn Marino 
595*f5b1c8a1SJohn Marino 	/* 7 - PSK identity hint (OCTET STRING). */
596*f5b1c8a1SJohn Marino 	/* 8 - PSK identity (OCTET STRING). */
597*f5b1c8a1SJohn Marino 
598*f5b1c8a1SJohn Marino 	/* 9 - Ticket lifetime. */
599*f5b1c8a1SJohn Marino 	ai.length = 0;
600*f5b1c8a1SJohn Marino 	if (c.slen != 0L &&
601*f5b1c8a1SJohn Marino 	    *c.p == (V_ASN1_CONSTRUCTED | V_ASN1_CONTEXT_SPECIFIC | 9)) {
602*f5b1c8a1SJohn Marino 		c.q = c.p;
603*f5b1c8a1SJohn Marino 		Tinf = ASN1_get_object(&c.p, &Tlen, &Ttag, &Tclass, c.slen);
604*f5b1c8a1SJohn Marino 		if (Tinf & 0x80) {
605*f5b1c8a1SJohn Marino 			SSLerr(SSL_F_D2I_SSL_SESSION,
606*f5b1c8a1SJohn Marino 			    ERR_R_BAD_ASN1_OBJECT_HEADER);
607*f5b1c8a1SJohn Marino 			goto err;
608*f5b1c8a1SJohn Marino 		}
609*f5b1c8a1SJohn Marino 		if (Tinf == (V_ASN1_CONSTRUCTED + 1))
610*f5b1c8a1SJohn Marino 			Tlen = c.slen - (c.p - c.q) - 2;
611*f5b1c8a1SJohn Marino 		if (d2i_ASN1_INTEGER(&aip, &c.p, Tlen) == NULL) {
612*f5b1c8a1SJohn Marino 			SSLerr(SSL_F_D2I_SSL_SESSION, ERR_R_NESTED_ASN1_ERROR);
613*f5b1c8a1SJohn Marino 			goto err;
614*f5b1c8a1SJohn Marino 		}
615*f5b1c8a1SJohn Marino 		if (Tinf == (V_ASN1_CONSTRUCTED + 1)) {
616*f5b1c8a1SJohn Marino 			Tlen = c.slen - (c.p - c.q);
617*f5b1c8a1SJohn Marino 			if(!ASN1_const_check_infinite_end(&c.p, Tlen)) {
618*f5b1c8a1SJohn Marino 				SSLerr(SSL_F_D2I_SSL_SESSION,
619*f5b1c8a1SJohn Marino 				    ERR_R_MISSING_ASN1_EOS);
620*f5b1c8a1SJohn Marino 				goto err;
621*f5b1c8a1SJohn Marino 			}
622*f5b1c8a1SJohn Marino 		}
623*f5b1c8a1SJohn Marino 		c.slen -= (c.p - c.q);
624*f5b1c8a1SJohn Marino 	}
625*f5b1c8a1SJohn Marino 	if (ai.data != NULL) {
626*f5b1c8a1SJohn Marino 		ret->tlsext_tick_lifetime_hint = ASN1_INTEGER_get(aip);
627*f5b1c8a1SJohn Marino 		free(ai.data);
628*f5b1c8a1SJohn Marino 		ai.data = NULL;
629*f5b1c8a1SJohn Marino 		ai.length = 0;
630*f5b1c8a1SJohn Marino 	} else if (ret->tlsext_ticklen && ret->session_id_length)
631*f5b1c8a1SJohn Marino 		ret->tlsext_tick_lifetime_hint = -1;
632*f5b1c8a1SJohn Marino 	else
633*f5b1c8a1SJohn Marino 		ret->tlsext_tick_lifetime_hint = 0;
634*f5b1c8a1SJohn Marino 	os.length = 0;
635*f5b1c8a1SJohn Marino 	os.data = NULL;
636*f5b1c8a1SJohn Marino 
637*f5b1c8a1SJohn Marino 	/* 10 - Ticket (OCTET STRING). */
638*f5b1c8a1SJohn Marino 	if (c.slen != 0L &&
639*f5b1c8a1SJohn Marino 	    *c.p == (V_ASN1_CONSTRUCTED | V_ASN1_CONTEXT_SPECIFIC | 10)) {
640*f5b1c8a1SJohn Marino 		c.q = c.p;
641*f5b1c8a1SJohn Marino 		Tinf = ASN1_get_object(&c.p, &Tlen, &Ttag, &Tclass, c.slen);
642*f5b1c8a1SJohn Marino 		if (Tinf & 0x80) {
643*f5b1c8a1SJohn Marino 			SSLerr(SSL_F_D2I_SSL_SESSION,
644*f5b1c8a1SJohn Marino 			    ERR_R_BAD_ASN1_OBJECT_HEADER);
645*f5b1c8a1SJohn Marino 			goto err;
646*f5b1c8a1SJohn Marino 		}
647*f5b1c8a1SJohn Marino 		if (Tinf == (V_ASN1_CONSTRUCTED + 1))
648*f5b1c8a1SJohn Marino 			Tlen = c.slen - (c.p - c.q) - 2;
649*f5b1c8a1SJohn Marino 		if (d2i_ASN1_OCTET_STRING(&osp, &c.p, Tlen) == NULL) {
650*f5b1c8a1SJohn Marino 			SSLerr(SSL_F_D2I_SSL_SESSION, ERR_R_NESTED_ASN1_ERROR);
651*f5b1c8a1SJohn Marino 			goto err;
652*f5b1c8a1SJohn Marino 		}
653*f5b1c8a1SJohn Marino 		if (Tinf == (V_ASN1_CONSTRUCTED + 1)) {
654*f5b1c8a1SJohn Marino 			Tlen = c.slen - (c.p - c.q);
655*f5b1c8a1SJohn Marino 			if(!ASN1_const_check_infinite_end(&c.p, Tlen)) {
656*f5b1c8a1SJohn Marino 				SSLerr(SSL_F_D2I_SSL_SESSION,
657*f5b1c8a1SJohn Marino 				    ERR_R_MISSING_ASN1_EOS);
658*f5b1c8a1SJohn Marino 				goto err;
659*f5b1c8a1SJohn Marino 			}
660*f5b1c8a1SJohn Marino 		}
661*f5b1c8a1SJohn Marino 		c.slen -= (c.p - c.q);
662*f5b1c8a1SJohn Marino 	}
663*f5b1c8a1SJohn Marino 	if (os.data) {
664*f5b1c8a1SJohn Marino 		ret->tlsext_tick = os.data;
665*f5b1c8a1SJohn Marino 		ret->tlsext_ticklen = os.length;
666*f5b1c8a1SJohn Marino 		os.data = NULL;
667*f5b1c8a1SJohn Marino 		os.length = 0;
668*f5b1c8a1SJohn Marino 	} else
669*f5b1c8a1SJohn Marino 		ret->tlsext_tick = NULL;
670*f5b1c8a1SJohn Marino 
671*f5b1c8a1SJohn Marino 	/* 11 - Compression method (OCTET STRING). */
672*f5b1c8a1SJohn Marino 	/* 12 - SRP username (OCTET STRING). */
673*f5b1c8a1SJohn Marino 
674*f5b1c8a1SJohn Marino 	if (!asn1_const_Finish(&c)) {
675*f5b1c8a1SJohn Marino 		SSLerr(SSL_F_D2I_SSL_SESSION, ERR_R_NESTED_ASN1_ERROR);
676*f5b1c8a1SJohn Marino 		goto err;
677*f5b1c8a1SJohn Marino 	}
678*f5b1c8a1SJohn Marino 
679*f5b1c8a1SJohn Marino 	*pp = c.p;
680*f5b1c8a1SJohn Marino 	if (a != NULL)
681*f5b1c8a1SJohn Marino 		*a = ret;
682*f5b1c8a1SJohn Marino 
683*f5b1c8a1SJohn Marino 	return (ret);
684*f5b1c8a1SJohn Marino 
685*f5b1c8a1SJohn Marino err:
686*f5b1c8a1SJohn Marino 	ERR_asprintf_error_data("offset=%d", (int)(c.q - *pp));
687*f5b1c8a1SJohn Marino 	if (ret != NULL && (a == NULL || *a != ret))
688*f5b1c8a1SJohn Marino 		SSL_SESSION_free(ret);
689*f5b1c8a1SJohn Marino 
690*f5b1c8a1SJohn Marino 	return (NULL);
691*f5b1c8a1SJohn Marino }
692