tzdata: update to 2018g
[unleashed.git] / lib / libssl / ssl_asn1.c
blob94fc8685fc91fb70b87254b1da0229f0b2e9a3d6
1 /* $OpenBSD: ssl_asn1.c,v 1.57 2018/08/27 16:42:48 jsing Exp $ */
2 /*
3 * Copyright (c) 2016 Joel Sing <jsing@openbsd.org>
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.
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.
18 #include <limits.h>
20 #include <openssl/ssl.h>
21 #include <openssl/x509.h>
23 #include "ssl_locl.h"
25 #include "bytestring.h"
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)
37 static uint64_t
38 time_max(void)
40 if (sizeof(time_t) == sizeof(int32_t))
41 return INT32_MAX;
42 if (sizeof(time_t) == sizeof(int64_t))
43 return INT64_MAX;
44 return 0;
47 static int
48 SSL_SESSION_encode(SSL_SESSION *s, unsigned char **out, size_t *out_len,
49 int ticket_encoding)
51 CBB cbb, session, cipher_suite, session_id, master_key, time, timeout;
52 CBB peer_cert, sidctx, verify_result, hostname, lifetime, ticket, value;
53 unsigned char *peer_cert_bytes = NULL;
54 int len, rv = 0;
55 uint16_t cid;
57 if (!CBB_init(&cbb, 0))
58 goto err;
60 if (!CBB_add_asn1(&cbb, &session, CBS_ASN1_SEQUENCE))
61 goto err;
63 /* Session ASN1 version. */
64 if (!CBB_add_asn1_uint64(&session, SSL_SESSION_ASN1_VERSION))
65 goto err;
67 /* TLS/SSL protocol version. */
68 if (s->ssl_version < 0)
69 goto err;
70 if (!CBB_add_asn1_uint64(&session, s->ssl_version))
71 goto err;
73 /* Cipher suite ID. */
74 /* XXX - require cipher to be non-NULL or always/only use cipher_id. */
75 cid = (uint16_t)(s->cipher_id & 0xffff);
76 if (s->cipher != NULL)
77 cid = ssl3_cipher_get_value(s->cipher);
78 if (!CBB_add_asn1(&session, &cipher_suite, CBS_ASN1_OCTETSTRING))
79 goto err;
80 if (!CBB_add_u16(&cipher_suite, cid))
81 goto err;
83 /* Session ID - zero length for a ticket. */
84 if (!CBB_add_asn1(&session, &session_id, CBS_ASN1_OCTETSTRING))
85 goto err;
86 if (!CBB_add_bytes(&session_id, s->session_id,
87 ticket_encoding ? 0 : s->session_id_length))
88 goto err;
90 /* Master key. */
91 if (!CBB_add_asn1(&session, &master_key, CBS_ASN1_OCTETSTRING))
92 goto err;
93 if (!CBB_add_bytes(&master_key, s->master_key, s->master_key_length))
94 goto err;
96 /* Time [1]. */
97 if (s->time != 0) {
98 if (s->time < 0)
99 goto err;
100 if (!CBB_add_asn1(&session, &time, SSLASN1_TIME_TAG))
101 goto err;
102 if (!CBB_add_asn1_uint64(&time, s->time))
103 goto err;
106 /* Timeout [2]. */
107 if (s->timeout != 0) {
108 if (s->timeout < 0)
109 goto err;
110 if (!CBB_add_asn1(&session, &timeout, SSLASN1_TIMEOUT_TAG))
111 goto err;
112 if (!CBB_add_asn1_uint64(&timeout, s->timeout))
113 goto err;
116 /* Peer certificate [3]. */
117 if (s->peer != NULL) {
118 if ((len = i2d_X509(s->peer, &peer_cert_bytes)) <= 0)
119 goto err;
120 if (!CBB_add_asn1(&session, &peer_cert, SSLASN1_PEER_CERT_TAG))
121 goto err;
122 if (!CBB_add_bytes(&peer_cert, peer_cert_bytes, len))
123 goto err;
126 /* Session ID context [4]. */
127 /* XXX - Actually handle this as optional? */
128 if (!CBB_add_asn1(&session, &sidctx, SSLASN1_SESSION_ID_CTX_TAG))
129 goto err;
130 if (!CBB_add_asn1(&sidctx, &value, CBS_ASN1_OCTETSTRING))
131 goto err;
132 if (!CBB_add_bytes(&value, s->sid_ctx, s->sid_ctx_length))
133 goto err;
135 /* Verify result [5]. */
136 if (s->verify_result != X509_V_OK) {
137 if (s->verify_result < 0)
138 goto err;
139 if (!CBB_add_asn1(&session, &verify_result,
140 SSLASN1_VERIFY_RESULT_TAG))
141 goto err;
142 if (!CBB_add_asn1_uint64(&verify_result, s->verify_result))
143 goto err;
146 /* Hostname [6]. */
147 if (s->tlsext_hostname != NULL) {
148 if (!CBB_add_asn1(&session, &hostname, SSLASN1_HOSTNAME_TAG))
149 goto err;
150 if (!CBB_add_asn1(&hostname, &value, CBS_ASN1_OCTETSTRING))
151 goto err;
152 if (!CBB_add_bytes(&value, (const uint8_t *)s->tlsext_hostname,
153 strlen(s->tlsext_hostname)))
154 goto err;
157 /* PSK identity hint [7]. */
158 /* PSK identity [8]. */
160 /* Ticket lifetime hint [9]. */
161 if (s->tlsext_tick_lifetime_hint > 0) {
162 if (!CBB_add_asn1(&session, &lifetime, SSLASN1_LIFETIME_TAG))
163 goto err;
164 if (!CBB_add_asn1_uint64(&lifetime,
165 s->tlsext_tick_lifetime_hint))
166 goto err;
169 /* Ticket [10]. */
170 if (s->tlsext_tick != NULL) {
171 if (!CBB_add_asn1(&session, &ticket, SSLASN1_TICKET_TAG))
172 goto err;
173 if (!CBB_add_asn1(&ticket, &value, CBS_ASN1_OCTETSTRING))
174 goto err;
175 if (!CBB_add_bytes(&value, s->tlsext_tick, s->tlsext_ticklen))
176 goto err;
179 /* Compression method [11]. */
180 /* SRP username [12]. */
182 if (!CBB_finish(&cbb, out, out_len))
183 goto err;
185 rv = 1;
187 err:
188 CBB_cleanup(&cbb);
189 free(peer_cert_bytes);
191 return rv;
195 SSL_SESSION_ticket(SSL_SESSION *ss, unsigned char **out, size_t *out_len)
197 if (ss == NULL)
198 return 0;
200 if (ss->cipher == NULL && ss->cipher_id == 0)
201 return 0;
203 return SSL_SESSION_encode(ss, out, out_len, 1);
207 i2d_SSL_SESSION(SSL_SESSION *ss, unsigned char **pp)
209 unsigned char *data = NULL;
210 size_t data_len = 0;
211 int rv = -1;
213 if (ss == NULL)
214 return 0;
216 if (ss->cipher == NULL && ss->cipher_id == 0)
217 return 0;
219 if (!SSL_SESSION_encode(ss, &data, &data_len, 0))
220 goto err;
222 if (data_len > INT_MAX)
223 goto err;
225 if (pp != NULL) {
226 if (*pp == NULL) {
227 *pp = data;
228 data = NULL;
229 } else {
230 memcpy(*pp, data, data_len);
231 *pp += data_len;
235 rv = (int)data_len;
237 err:
238 freezero(data, data_len);
240 return rv;
243 SSL_SESSION *
244 d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp, long length)
246 CBS cbs, session, cipher_suite, session_id, master_key, peer_cert;
247 CBS hostname, ticket;
248 uint64_t version, tls_version, stime, timeout, verify_result, lifetime;
249 const unsigned char *peer_cert_bytes;
250 uint16_t cipher_value;
251 SSL_SESSION *s = NULL;
252 size_t data_len;
253 int present;
255 if (a != NULL)
256 s = *a;
258 if (s == NULL) {
259 if ((s = SSL_SESSION_new()) == NULL) {
260 SSLerrorx(ERR_R_MALLOC_FAILURE);
261 return (NULL);
265 CBS_init(&cbs, *pp, length);
267 if (!CBS_get_asn1(&cbs, &session, CBS_ASN1_SEQUENCE))
268 goto err;
270 /* Session ASN1 version. */
271 if (!CBS_get_asn1_uint64(&session, &version))
272 goto err;
273 if (version != SSL_SESSION_ASN1_VERSION)
274 goto err;
276 /* TLS/SSL Protocol Version. */
277 if (!CBS_get_asn1_uint64(&session, &tls_version))
278 goto err;
279 if (tls_version > INT_MAX)
280 goto err;
281 s->ssl_version = (int)tls_version;
283 /* Cipher suite. */
284 if (!CBS_get_asn1(&session, &cipher_suite, CBS_ASN1_OCTETSTRING))
285 goto err;
286 if (!CBS_get_u16(&cipher_suite, &cipher_value))
287 goto err;
288 if (CBS_len(&cipher_suite) != 0)
289 goto err;
291 /* XXX - populate cipher instead? */
292 s->cipher = NULL;
293 s->cipher_id = SSL3_CK_ID | cipher_value;
295 /* Session ID. */
296 if (!CBS_get_asn1(&session, &session_id, CBS_ASN1_OCTETSTRING))
297 goto err;
298 if (!CBS_write_bytes(&session_id, s->session_id, sizeof(s->session_id),
299 &data_len))
300 goto err;
301 if (data_len > UINT_MAX)
302 goto err;
303 s->session_id_length = (unsigned int)data_len;
305 /* Master key. */
306 if (!CBS_get_asn1(&session, &master_key, CBS_ASN1_OCTETSTRING))
307 goto err;
308 if (!CBS_write_bytes(&master_key, s->master_key, sizeof(s->master_key),
309 &data_len))
310 goto err;
311 if (data_len > INT_MAX)
312 goto err;
313 s->master_key_length = (int)data_len;
315 /* Time [1]. */
316 s->time = time(NULL);
317 if (!CBS_get_optional_asn1_uint64(&session, &stime, SSLASN1_TIME_TAG,
319 goto err;
320 if (stime > time_max())
321 goto err;
322 if (stime != 0)
323 s->time = (time_t)stime;
325 /* Timeout [2]. */
326 s->timeout = 3;
327 if (!CBS_get_optional_asn1_uint64(&session, &timeout,
328 SSLASN1_TIMEOUT_TAG, 0))
329 goto err;
330 if (timeout > LONG_MAX)
331 goto err;
332 if (timeout != 0)
333 s->timeout = (long)timeout;
335 /* Peer certificate [3]. */
336 X509_free(s->peer);
337 s->peer = NULL;
338 if (!CBS_get_optional_asn1(&session, &peer_cert, &present,
339 SSLASN1_PEER_CERT_TAG))
340 goto err;
341 if (present) {
342 data_len = CBS_len(&peer_cert);
343 if (data_len > LONG_MAX)
344 goto err;
345 peer_cert_bytes = CBS_data(&peer_cert);
346 if (d2i_X509(&s->peer, &peer_cert_bytes,
347 (long)data_len) == NULL)
348 goto err;
351 /* Session ID context [4]. */
352 s->sid_ctx_length = 0;
353 if (!CBS_get_optional_asn1_octet_string(&session, &session_id, &present,
354 SSLASN1_SESSION_ID_CTX_TAG))
355 goto err;
356 if (present) {
357 if (!CBS_write_bytes(&session_id, (uint8_t *)&s->sid_ctx,
358 sizeof(s->sid_ctx), &data_len))
359 goto err;
360 if (data_len > UINT_MAX)
361 goto err;
362 s->sid_ctx_length = (unsigned int)data_len;
365 /* Verify result [5]. */
366 s->verify_result = X509_V_OK;
367 if (!CBS_get_optional_asn1_uint64(&session, &verify_result,
368 SSLASN1_VERIFY_RESULT_TAG, X509_V_OK))
369 goto err;
370 if (verify_result > LONG_MAX)
371 goto err;
372 s->verify_result = (long)verify_result;
374 /* Hostname [6]. */
375 free(s->tlsext_hostname);
376 s->tlsext_hostname = NULL;
377 if (!CBS_get_optional_asn1_octet_string(&session, &hostname, &present,
378 SSLASN1_HOSTNAME_TAG))
379 goto err;
380 if (present) {
381 if (CBS_contains_zero_byte(&hostname))
382 goto err;
383 if (!CBS_strdup(&hostname, &s->tlsext_hostname))
384 goto err;
387 /* PSK identity hint [7]. */
388 /* PSK identity [8]. */
390 /* Ticket lifetime [9]. */
391 s->tlsext_tick_lifetime_hint = 0;
392 /* XXX - tlsext_ticklen is not yet set... */
393 if (s->tlsext_ticklen > 0 && s->session_id_length > 0)
394 s->tlsext_tick_lifetime_hint = -1;
395 if (!CBS_get_optional_asn1_uint64(&session, &lifetime,
396 SSLASN1_LIFETIME_TAG, 0))
397 goto err;
398 if (lifetime > LONG_MAX)
399 goto err;
400 if (lifetime > 0)
401 s->tlsext_tick_lifetime_hint = (long)lifetime;
403 /* Ticket [10]. */
404 free(s->tlsext_tick);
405 s->tlsext_tick = NULL;
406 if (!CBS_get_optional_asn1_octet_string(&session, &ticket, &present,
407 SSLASN1_TICKET_TAG))
408 goto err;
409 if (present) {
410 if (!CBS_stow(&ticket, &s->tlsext_tick, &s->tlsext_ticklen))
411 goto err;
414 /* Compression method [11]. */
415 /* SRP username [12]. */
417 *pp = CBS_data(&cbs);
419 if (a != NULL)
420 *a = s;
422 return (s);
424 err:
425 ERR_asprintf_error_data("offset=%d", (int)(CBS_data(&cbs) - *pp));
427 if (s != NULL && (a == NULL || *a != s))
428 SSL_SESSION_free(s);
430 return (NULL);