GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libssl/ssl_asn1.c Lines: 149 161 92.5 %
Date: 2017-11-07 Branches: 106 178 59.6 %

Line Branch Exec Source
1
/* $OpenBSD: ssl_asn1.c,v 1.55 2017/05/06 16:18:36 jsing Exp $ */
2
/*
3
 * Copyright (c) 2016 Joel Sing <jsing@openbsd.org>
4
 *
5
 * Permission to use, copy, modify, and distribute this software for any
6
 * purpose with or without fee is hereby granted, provided that the above
7
 * copyright notice and this permission notice appear in all copies.
8
 *
9
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
 */
17
18
#include <limits.h>
19
20
#include <openssl/ssl.h>
21
#include <openssl/x509.h>
22
23
#include "ssl_locl.h"
24
25
#include "bytestring.h"
26
27
#define SSLASN1_TAG	(CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC)
28
#define SSLASN1_TIME_TAG		(SSLASN1_TAG | 1)
29
#define SSLASN1_TIMEOUT_TAG		(SSLASN1_TAG | 2)
30
#define SSLASN1_PEER_CERT_TAG		(SSLASN1_TAG | 3)
31
#define SSLASN1_SESSION_ID_CTX_TAG	(SSLASN1_TAG | 4)
32
#define SSLASN1_VERIFY_RESULT_TAG	(SSLASN1_TAG | 5)
33
#define SSLASN1_HOSTNAME_TAG		(SSLASN1_TAG | 6)
34
#define SSLASN1_LIFETIME_TAG		(SSLASN1_TAG | 9)
35
#define SSLASN1_TICKET_TAG		(SSLASN1_TAG | 10)
36
37
static uint64_t
38
time_max(void)
39
{
40
	if (sizeof(time_t) == sizeof(int32_t))
41
		return INT32_MAX;
42
	if (sizeof(time_t) == sizeof(int64_t))
43
508
		return INT64_MAX;
44
	return 0;
45
}
46
47
int
48
i2d_SSL_SESSION(SSL_SESSION *s, unsigned char **pp)
49
{
50
2000
	CBB cbb, session, cipher_suite, session_id, master_key, time, timeout;
51
1000
	CBB peer_cert, sidctx, verify_result, hostname, lifetime, ticket;
52
1000
	CBB value;
53
1000
	unsigned char *data = NULL, *peer_cert_bytes = NULL;
54
1000
	size_t data_len = 0;
55
	int len, rv = -1;
56
	uint16_t cid;
57
58
1000
	if (s == NULL)
59
		return (0);
60
61

1516
	if (s->cipher == NULL && s->cipher_id == 0)
62
		return (0);
63
64
1000
	if (!CBB_init(&cbb, 0))
65
		goto err;
66
67
1000
	if (!CBB_add_asn1(&cbb, &session, CBS_ASN1_SEQUENCE))
68
		goto err;
69
70
	/* Session ASN1 version. */
71
1000
	if (!CBB_add_asn1_uint64(&session, SSL_SESSION_ASN1_VERSION))
72
		goto err;
73
74
	/* TLS/SSL protocol version. */
75
1000
	if (s->ssl_version < 0)
76
		goto err;
77
1000
	if (!CBB_add_asn1_uint64(&session, s->ssl_version))
78
		goto err;
79
80
	/* Cipher suite ID. */
81
	/* XXX - require cipher to be non-NULL or always/only use cipher_id. */
82
1000
	cid = (uint16_t)(s->cipher_id & 0xffff);
83
1000
	if (s->cipher != NULL)
84
484
		cid = ssl3_cipher_get_value(s->cipher);
85
1000
	if (!CBB_add_asn1(&session, &cipher_suite, CBS_ASN1_OCTETSTRING))
86
		goto err;
87
1000
	if (!CBB_add_u16(&cipher_suite, cid))
88
		goto err;
89
90
	/* Session ID. */
91
1000
	if (!CBB_add_asn1(&session, &session_id, CBS_ASN1_OCTETSTRING))
92
		goto err;
93
1000
	if (!CBB_add_bytes(&session_id, s->session_id, s->session_id_length))
94
		goto err;
95
96
	/* Master key. */
97
1000
	if (!CBB_add_asn1(&session, &master_key, CBS_ASN1_OCTETSTRING))
98
		goto err;
99
1000
	if (!CBB_add_bytes(&master_key, s->master_key, s->master_key_length))
100
		goto err;
101
102
	/* Time [1]. */
103
1000
	if (s->time != 0) {
104
980
		if (s->time < 0)
105
			goto err;
106
976
		if (!CBB_add_asn1(&session, &time, SSLASN1_TIME_TAG))
107
			goto err;
108
976
		if (!CBB_add_asn1_uint64(&time, s->time))
109
			goto err;
110
	}
111
112
	/* Timeout [2]. */
113
996
	if (s->timeout != 0) {
114
980
		if (s->timeout < 0)
115
			goto err;
116
976
		if (!CBB_add_asn1(&session, &timeout, SSLASN1_TIMEOUT_TAG))
117
			goto err;
118
976
		if (!CBB_add_asn1_uint64(&timeout, s->timeout))
119
			goto err;
120
	}
121
122
	/* Peer certificate [3]. */
123
992
	if (s->peer != NULL) {
124
128
		if ((len = i2d_X509(s->peer, &peer_cert_bytes)) <= 0)
125
			goto err;
126
128
		if (!CBB_add_asn1(&session, &peer_cert, SSLASN1_PEER_CERT_TAG))
127
			goto err;
128
128
		if (!CBB_add_bytes(&peer_cert, peer_cert_bytes, len))
129
			goto err;
130
	}
131
132
	/* Session ID context [4]. */
133
	/* XXX - Actually handle this as optional? */
134
992
	if (!CBB_add_asn1(&session, &sidctx, SSLASN1_SESSION_ID_CTX_TAG))
135
		goto err;
136
992
	if (!CBB_add_asn1(&sidctx, &value, CBS_ASN1_OCTETSTRING))
137
		goto err;
138
992
	if (!CBB_add_bytes(&value, s->sid_ctx, s->sid_ctx_length))
139
		goto err;
140
141
	/* Verify result [5]. */
142
992
	if (s->verify_result != X509_V_OK) {
143
32
		if (s->verify_result < 0)
144
			goto err;
145
32
		if (!CBB_add_asn1(&session, &verify_result,
146
		    SSLASN1_VERIFY_RESULT_TAG))
147
			goto err;
148
32
		if (!CBB_add_asn1_uint64(&verify_result, s->verify_result))
149
			goto err;
150
	}
151
152
	/* Hostname [6]. */
153
992
	if (s->tlsext_hostname != NULL) {
154
8
		if (!CBB_add_asn1(&session, &hostname, SSLASN1_HOSTNAME_TAG))
155
			goto err;
156
8
		if (!CBB_add_asn1(&hostname, &value, CBS_ASN1_OCTETSTRING))
157
			goto err;
158
16
		if (!CBB_add_bytes(&value, (const uint8_t *)s->tlsext_hostname,
159
8
		    strlen(s->tlsext_hostname)))
160
			goto err;
161
	}
162
163
	/* PSK identity hint [7]. */
164
	/* PSK identity [8]. */
165
166
	/* Ticket lifetime hint [9]. */
167
992
	if (s->tlsext_tick_lifetime_hint > 0) {
168
16
		if (!CBB_add_asn1(&session, &lifetime, SSLASN1_LIFETIME_TAG))
169
			goto err;
170
16
		if (!CBB_add_asn1_uint64(&lifetime,
171
16
		    s->tlsext_tick_lifetime_hint))
172
			goto err;
173
	}
174
175
	/* Ticket [10]. */
176
992
	if (s->tlsext_tick) {
177
16
		if (!CBB_add_asn1(&session, &ticket, SSLASN1_TICKET_TAG))
178
			goto err;
179
16
		if (!CBB_add_asn1(&ticket, &value, CBS_ASN1_OCTETSTRING))
180
			goto err;
181
16
		if (!CBB_add_bytes(&value, s->tlsext_tick, s->tlsext_ticklen))
182
			goto err;
183
	}
184
185
	/* Compression method [11]. */
186
	/* SRP username [12]. */
187
188
1984
	if (!CBB_finish(&cbb, &data, &data_len))
189
		goto err;
190
191
992
	if (data_len > INT_MAX)
192
		goto err;
193
194
992
	if (pp != NULL) {
195
496
		if (*pp == NULL) {
196
			*pp = data;
197
			data = NULL;
198
		} else {
199
496
			memcpy(*pp, data, data_len);
200
496
			*pp += data_len;
201
		}
202
	}
203
204
992
	rv = (int)data_len;
205
206
 err:
207
1000
	CBB_cleanup(&session);
208
1000
	freezero(data, data_len);
209
1000
	free(peer_cert_bytes);
210
211
1000
	return rv;
212
1000
}
213
214
SSL_SESSION *
215
d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp, long length)
216
{
217
508
	CBS cbs, session, cipher_suite, session_id, master_key, peer_cert;
218
254
	CBS hostname, ticket;
219
254
	uint64_t version, tls_version, stime, timeout, verify_result, lifetime;
220
254
	const unsigned char *peer_cert_bytes;
221
254
	uint16_t cipher_value;
222
	SSL_SESSION *s = NULL;
223
254
	size_t data_len;
224
254
	int present;
225
226
254
	if (a != NULL)
227
12
		s = *a;
228
229
254
	if (s == NULL) {
230
242
		if ((s = SSL_SESSION_new()) == NULL) {
231
			SSLerrorx(ERR_R_MALLOC_FAILURE);
232
			return (NULL);
233
		}
234
	}
235
236
254
	CBS_init(&cbs, *pp, length);
237
238
254
	if (!CBS_get_asn1(&cbs, &session, CBS_ASN1_SEQUENCE))
239
		goto err;
240
241
	/* Session ASN1 version. */
242
508
	if (!CBS_get_asn1_uint64(&session, &version))
243
		goto err;
244
254
	if (version != SSL_SESSION_ASN1_VERSION)
245
		goto err;
246
247
	/* TLS/SSL Protocol Version. */
248
508
	if (!CBS_get_asn1_uint64(&session, &tls_version))
249
		goto err;
250
254
	if (tls_version > INT_MAX)
251
		goto err;
252
254
	s->ssl_version = (int)tls_version;
253
254
	/* Cipher suite. */
255
254
	if (!CBS_get_asn1(&session, &cipher_suite, CBS_ASN1_OCTETSTRING))
256
		goto err;
257
254
	if (!CBS_get_u16(&cipher_suite, &cipher_value))
258
		goto err;
259
254
	if (CBS_len(&cipher_suite) != 0)
260
		goto err;
261
262
	/* XXX - populate cipher instead? */
263
254
	s->cipher = NULL;
264
254
	s->cipher_id = SSL3_CK_ID | cipher_value;
265
266
	/* Session ID. */
267
254
	if (!CBS_get_asn1(&session, &session_id, CBS_ASN1_OCTETSTRING))
268
		goto err;
269
508
	if (!CBS_write_bytes(&session_id, s->session_id, sizeof(s->session_id),
270
	    &data_len))
271
		goto err;
272
254
	if (data_len > UINT_MAX)
273
		goto err;
274
254
	s->session_id_length = (unsigned int)data_len;
275
276
	/* Master key. */
277
254
	if (!CBS_get_asn1(&session, &master_key, CBS_ASN1_OCTETSTRING))
278
		goto err;
279
508
	if (!CBS_write_bytes(&master_key, s->master_key, sizeof(s->master_key),
280
	    &data_len))
281
		goto err;
282
254
	if (data_len > INT_MAX)
283
		goto err;
284
254
	s->master_key_length = (int)data_len;
285
286
	/* Time [1]. */
287
254
	s->time = time(NULL);
288
254
	if (!CBS_get_optional_asn1_uint64(&session, &stime, SSLASN1_TIME_TAG,
289
	    0))
290
		goto err;
291
254
	if (stime > time_max())
292
		goto err;
293
254
	if (stime != 0)
294
246
		s->time = (time_t)stime;
295
296
	/* Timeout [2]. */
297
254
	s->timeout = 3;
298
508
	if (!CBS_get_optional_asn1_uint64(&session, &timeout,
299
	    SSLASN1_TIMEOUT_TAG, 0))
300
		goto err;
301
254
	if (timeout > LONG_MAX)
302
		goto err;
303
254
	if (timeout != 0)
304
246
		s->timeout = (long)timeout;
305
306
	/* Peer certificate [3]. */
307
254
	X509_free(s->peer);
308
254
	s->peer = NULL;
309
254
	if (!CBS_get_optional_asn1(&session, &peer_cert, &present,
310
	    SSLASN1_PEER_CERT_TAG))
311
		goto err;
312
254
	if (present) {
313
34
		data_len = CBS_len(&peer_cert);
314
34
		if (data_len > LONG_MAX)
315
			goto err;
316
34
		peer_cert_bytes = CBS_data(&peer_cert);
317
68
		if (d2i_X509(&s->peer, &peer_cert_bytes,
318
68
		    (long)data_len) == NULL)
319
			goto err;
320
	}
321
322
	/* Session ID context [4]. */
323
254
	s->sid_ctx_length = 0;
324
254
	if (!CBS_get_optional_asn1_octet_string(&session, &session_id, &present,
325
	    SSLASN1_SESSION_ID_CTX_TAG))
326
		goto err;
327
254
	if (present) {
328
508
		if (!CBS_write_bytes(&session_id, (uint8_t *)&s->sid_ctx,
329
		    sizeof(s->sid_ctx), &data_len))
330
			goto err;
331
254
		if (data_len > UINT_MAX)
332
			goto err;
333
254
		s->sid_ctx_length = (unsigned int)data_len;
334
254
	}
335
336
	/* Verify result [5]. */
337
254
	s->verify_result = X509_V_OK;
338
508
	if (!CBS_get_optional_asn1_uint64(&session, &verify_result,
339
	    SSLASN1_VERIFY_RESULT_TAG, X509_V_OK))
340
		goto err;
341
254
	if (verify_result > LONG_MAX)
342
		goto err;
343
254
	s->verify_result = (long)verify_result;
344
345
	/* Hostname [6]. */
346
254
	free(s->tlsext_hostname);
347
254
	s->tlsext_hostname = NULL;
348
254
	if (!CBS_get_optional_asn1_octet_string(&session, &hostname, &present,
349
	    SSLASN1_HOSTNAME_TAG))
350
		goto err;
351
254
	if (present) {
352
4
		if (CBS_contains_zero_byte(&hostname))
353
			goto err;
354
4
		if (!CBS_strdup(&hostname, &s->tlsext_hostname))
355
			goto err;
356
	}
357
358
	/* PSK identity hint [7]. */
359
	/* PSK identity [8]. */
360
361
	/* Ticket lifetime [9]. */
362
254
	s->tlsext_tick_lifetime_hint = 0;
363
	/* XXX - tlsext_ticklen is not yet set... */
364

254
	if (s->tlsext_ticklen > 0 && s->session_id_length > 0)
365
		s->tlsext_tick_lifetime_hint = -1;
366
508
	if (!CBS_get_optional_asn1_uint64(&session, &lifetime,
367
	    SSLASN1_LIFETIME_TAG, 0))
368
		goto err;
369
254
	if (lifetime > LONG_MAX)
370
		goto err;
371
254
	if (lifetime > 0)
372
6
		s->tlsext_tick_lifetime_hint = (long)lifetime;
373
374
	/* Ticket [10]. */
375
254
	free(s->tlsext_tick);
376
254
	s->tlsext_tick = NULL;
377
254
	if (!CBS_get_optional_asn1_octet_string(&session, &ticket, &present,
378
	    SSLASN1_TICKET_TAG))
379
		goto err;
380
254
	if (present) {
381
6
		if (!CBS_stow(&ticket, &s->tlsext_tick, &s->tlsext_ticklen))
382
			goto err;
383
	}
384
385
	/* Compression method [11]. */
386
	/* SRP username [12]. */
387
388
254
	*pp = CBS_data(&cbs);
389
390
254
	if (a != NULL)
391
12
		*a = s;
392
393
254
	return (s);
394
395
err:
396
	ERR_asprintf_error_data("offset=%d", (int)(CBS_data(&cbs) - *pp));
397
398
	if (s != NULL && (a == NULL || *a != s))
399
		SSL_SESSION_free(s);
400
401
	return (NULL);
402
254
}