Coverage Report

Created: 2025-03-09 06:52

/src/libressl/ssl/ssl_asn1.c
Line
Count
Source (jump to first uncovered line)
1
/* $OpenBSD: ssl_asn1.c,v 1.69 2024/07/22 14:47:15 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 "bytestring.h"
24
#include "ssl_local.h"
25
26
6.93k
#define SSLASN1_TAG (CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC)
27
1.30k
#define SSLASN1_TIME_TAG    (SSLASN1_TAG | 1)
28
1.23k
#define SSLASN1_TIMEOUT_TAG   (SSLASN1_TAG | 2)
29
731
#define SSLASN1_PEER_CERT_TAG   (SSLASN1_TAG | 3)
30
1.12k
#define SSLASN1_SESSION_ID_CTX_TAG  (SSLASN1_TAG | 4)
31
767
#define SSLASN1_VERIFY_RESULT_TAG (SSLASN1_TAG | 5)
32
609
#define SSLASN1_HOSTNAME_TAG    (SSLASN1_TAG | 6)
33
636
#define SSLASN1_LIFETIME_TAG    (SSLASN1_TAG | 9)
34
530
#define SSLASN1_TICKET_TAG    (SSLASN1_TAG | 10)
35
36
static uint64_t
37
time_max(void)
38
887
{
39
887
  if (sizeof(time_t) == sizeof(int32_t))
40
0
    return INT32_MAX;
41
887
  if (sizeof(time_t) == sizeof(int64_t))
42
887
    return INT64_MAX;
43
0
  return 0;
44
887
}
45
46
static int
47
SSL_SESSION_encode(SSL_SESSION *s, unsigned char **out, size_t *out_len,
48
    int ticket_encoding)
49
405
{
50
405
  CBB cbb, session, cipher_suite, session_id, master_key, time, timeout;
51
405
  CBB peer_cert, sidctx, verify_result, hostname, lifetime, ticket, value;
52
405
  unsigned char *peer_cert_bytes = NULL;
53
405
  int len, rv = 0;
54
55
405
  if (!CBB_init(&cbb, 0))
56
0
    goto err;
57
58
405
  if (!CBB_add_asn1(&cbb, &session, CBS_ASN1_SEQUENCE))
59
0
    goto err;
60
61
  /* Session ASN1 version. */
62
405
  if (!CBB_add_asn1_uint64(&session, SSL_SESSION_ASN1_VERSION))
63
0
    goto err;
64
65
  /* TLS/SSL protocol version. */
66
405
  if (s->ssl_version < 0)
67
0
    goto err;
68
405
  if (!CBB_add_asn1_uint64(&session, s->ssl_version))
69
0
    goto err;
70
71
  /* Cipher suite value. */
72
405
  if (!CBB_add_asn1(&session, &cipher_suite, CBS_ASN1_OCTETSTRING))
73
0
    goto err;
74
405
  if (!CBB_add_u16(&cipher_suite, s->cipher_value))
75
0
    goto err;
76
77
  /* Session ID - zero length for a ticket. */
78
405
  if (!CBB_add_asn1(&session, &session_id, CBS_ASN1_OCTETSTRING))
79
0
    goto err;
80
405
  if (!CBB_add_bytes(&session_id, s->session_id,
81
405
      ticket_encoding ? 0 : s->session_id_length))
82
0
    goto err;
83
84
  /* Master key. */
85
405
  if (!CBB_add_asn1(&session, &master_key, CBS_ASN1_OCTETSTRING))
86
0
    goto err;
87
405
  if (!CBB_add_bytes(&master_key, s->master_key, s->master_key_length))
88
0
    goto err;
89
90
  /* Time [1]. */
91
405
  if (s->time != 0) {
92
405
    if (s->time < 0)
93
0
      goto err;
94
405
    if (!CBB_add_asn1(&session, &time, SSLASN1_TIME_TAG))
95
0
      goto err;
96
405
    if (!CBB_add_asn1_uint64(&time, s->time))
97
0
      goto err;
98
405
  }
99
100
  /* Timeout [2]. */
101
405
  if (s->timeout != 0) {
102
405
    if (s->timeout < 0)
103
0
      goto err;
104
405
    if (!CBB_add_asn1(&session, &timeout, SSLASN1_TIMEOUT_TAG))
105
0
      goto err;
106
405
    if (!CBB_add_asn1_uint64(&timeout, s->timeout))
107
0
      goto err;
108
405
  }
109
110
  /* Peer certificate [3]. */
111
405
  if (s->peer_cert != NULL) {
112
2
    if ((len = i2d_X509(s->peer_cert, &peer_cert_bytes)) <= 0)
113
0
      goto err;
114
2
    if (!CBB_add_asn1(&session, &peer_cert, SSLASN1_PEER_CERT_TAG))
115
0
      goto err;
116
2
    if (!CBB_add_bytes(&peer_cert, peer_cert_bytes, len))
117
0
      goto err;
118
2
  }
119
120
  /* Session ID context [4]. */
121
  /* XXX - Actually handle this as optional? */
122
405
  if (!CBB_add_asn1(&session, &sidctx, SSLASN1_SESSION_ID_CTX_TAG))
123
0
    goto err;
124
405
  if (!CBB_add_asn1(&sidctx, &value, CBS_ASN1_OCTETSTRING))
125
0
    goto err;
126
405
  if (!CBB_add_bytes(&value, s->sid_ctx, s->sid_ctx_length))
127
0
    goto err;
128
129
  /* Verify result [5]. */
130
405
  if (s->verify_result != X509_V_OK) {
131
81
    if (s->verify_result < 0)
132
0
      goto err;
133
81
    if (!CBB_add_asn1(&session, &verify_result,
134
81
        SSLASN1_VERIFY_RESULT_TAG))
135
0
      goto err;
136
81
    if (!CBB_add_asn1_uint64(&verify_result, s->verify_result))
137
0
      goto err;
138
81
  }
139
140
  /* Hostname [6]. */
141
405
  if (s->tlsext_hostname != NULL) {
142
1
    if (!CBB_add_asn1(&session, &hostname, SSLASN1_HOSTNAME_TAG))
143
0
      goto err;
144
1
    if (!CBB_add_asn1(&hostname, &value, CBS_ASN1_OCTETSTRING))
145
0
      goto err;
146
1
    if (!CBB_add_bytes(&value, (const uint8_t *)s->tlsext_hostname,
147
1
        strlen(s->tlsext_hostname)))
148
0
      goto err;
149
1
  }
150
151
  /* PSK identity hint [7]. */
152
  /* PSK identity [8]. */
153
154
  /* Ticket lifetime hint [9]. */
155
405
  if (s->tlsext_tick_lifetime_hint > 0) {
156
48
    if (!CBB_add_asn1(&session, &lifetime, SSLASN1_LIFETIME_TAG))
157
0
      goto err;
158
48
    if (!CBB_add_asn1_uint64(&lifetime,
159
48
        s->tlsext_tick_lifetime_hint))
160
0
      goto err;
161
48
  }
162
163
  /* Ticket [10]. */
164
405
  if (s->tlsext_tick != NULL) {
165
10
    if (!CBB_add_asn1(&session, &ticket, SSLASN1_TICKET_TAG))
166
0
      goto err;
167
10
    if (!CBB_add_asn1(&ticket, &value, CBS_ASN1_OCTETSTRING))
168
0
      goto err;
169
10
    if (!CBB_add_bytes(&value, s->tlsext_tick, s->tlsext_ticklen))
170
0
      goto err;
171
10
  }
172
173
  /* Compression method [11]. */
174
  /* SRP username [12]. */
175
176
405
  if (!CBB_finish(&cbb, out, out_len))
177
0
    goto err;
178
179
405
  rv = 1;
180
181
405
 err:
182
405
  CBB_cleanup(&cbb);
183
405
  free(peer_cert_bytes);
184
185
405
  return rv;
186
405
}
187
188
int
189
SSL_SESSION_ticket(SSL_SESSION *ss, unsigned char **out, size_t *out_len)
190
0
{
191
0
  if (ss == NULL)
192
0
    return 0;
193
194
0
  if (ss->cipher_value == 0)
195
0
    return 0;
196
197
0
  return SSL_SESSION_encode(ss, out, out_len, 1);
198
0
}
199
200
int
201
i2d_SSL_SESSION(SSL_SESSION *ss, unsigned char **pp)
202
406
{
203
406
  unsigned char *data = NULL;
204
406
  size_t data_len = 0;
205
406
  int rv = -1;
206
207
406
  if (ss == NULL)
208
0
    return 0;
209
210
406
  if (ss->cipher_value == 0)
211
1
    return 0;
212
213
405
  if (!SSL_SESSION_encode(ss, &data, &data_len, 0))
214
0
    goto err;
215
216
405
  if (data_len > INT_MAX)
217
0
    goto err;
218
219
405
  if (pp != NULL) {
220
405
    if (*pp == NULL) {
221
405
      *pp = data;
222
405
      data = NULL;
223
405
    } else {
224
0
      memcpy(*pp, data, data_len);
225
0
      *pp += data_len;
226
0
    }
227
405
  }
228
229
405
  rv = (int)data_len;
230
231
405
 err:
232
405
  freezero(data, data_len);
233
234
405
  return rv;
235
405
}
236
LSSL_ALIAS(i2d_SSL_SESSION);
237
238
SSL_SESSION *
239
d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp, long length)
240
10.6k
{
241
10.6k
  CBS cbs, session, cipher_suite, session_id, master_key, peer_cert;
242
10.6k
  CBS hostname, ticket;
243
10.6k
  uint64_t version, tls_version, stime, timeout, verify_result, lifetime;
244
10.6k
  const unsigned char *peer_cert_bytes;
245
10.6k
  SSL_SESSION *s = NULL;
246
10.6k
  size_t data_len;
247
10.6k
  int present;
248
249
10.6k
  if (a != NULL)
250
0
    s = *a;
251
252
10.6k
  if (s == NULL) {
253
10.6k
    if ((s = SSL_SESSION_new()) == NULL) {
254
0
      SSLerrorx(ERR_R_MALLOC_FAILURE);
255
0
      return (NULL);
256
0
    }
257
10.6k
  }
258
259
10.6k
  CBS_init(&cbs, *pp, length);
260
261
10.6k
  if (!CBS_get_asn1(&cbs, &session, CBS_ASN1_SEQUENCE))
262
7.69k
    goto err;
263
264
  /* Session ASN1 version. */
265
2.92k
  if (!CBS_get_asn1_uint64(&session, &version))
266
1.35k
    goto err;
267
1.56k
  if (version != SSL_SESSION_ASN1_VERSION)
268
449
    goto err;
269
270
  /* TLS/SSL Protocol Version. */
271
1.12k
  if (!CBS_get_asn1_uint64(&session, &tls_version))
272
111
    goto err;
273
1.00k
  if (tls_version > INT_MAX)
274
57
    goto err;
275
952
  s->ssl_version = (int)tls_version;
276
277
  /* Cipher suite value. */
278
952
  if (!CBS_get_asn1(&session, &cipher_suite, CBS_ASN1_OCTETSTRING))
279
38
    goto err;
280
914
  if (!CBS_get_u16(&cipher_suite, &s->cipher_value))
281
1
    goto err;
282
913
  if (CBS_len(&cipher_suite) != 0)
283
1
    goto err;
284
285
  /* Session ID. */
286
912
  if (!CBS_get_asn1(&session, &session_id, CBS_ASN1_OCTETSTRING))
287
1
    goto err;
288
911
  if (!CBS_write_bytes(&session_id, s->session_id, sizeof(s->session_id),
289
911
      &s->session_id_length))
290
5
    goto err;
291
292
  /* Master key. */
293
906
  if (!CBS_get_asn1(&session, &master_key, CBS_ASN1_OCTETSTRING))
294
2
    goto err;
295
904
  if (!CBS_write_bytes(&master_key, s->master_key, sizeof(s->master_key),
296
904
      &s->master_key_length))
297
1
    goto err;
298
299
  /* Time [1]. */
300
903
  s->time = time(NULL);
301
903
  if (!CBS_get_optional_asn1_uint64(&session, &stime, SSLASN1_TIME_TAG,
302
903
      0))
303
16
    goto err;
304
887
  if (stime > time_max())
305
61
    goto err;
306
826
  if (stime != 0)
307
91
    s->time = (time_t)stime;
308
309
  /* Timeout [2]. */
310
826
  s->timeout = 3;
311
826
  if (!CBS_get_optional_asn1_uint64(&session, &timeout,
312
826
      SSLASN1_TIMEOUT_TAG, 0))
313
43
    goto err;
314
783
  if (timeout > LONG_MAX)
315
54
    goto err;
316
729
  if (timeout != 0)
317
86
    s->timeout = (long)timeout;
318
319
  /* Peer certificate [3]. */
320
729
  X509_free(s->peer_cert);
321
729
  s->peer_cert = NULL;
322
729
  if (!CBS_get_optional_asn1(&session, &peer_cert, &present,
323
729
      SSLASN1_PEER_CERT_TAG))
324
1
    goto err;
325
728
  if (present) {
326
14
    data_len = CBS_len(&peer_cert);
327
14
    if (data_len > LONG_MAX)
328
0
      goto err;
329
14
    peer_cert_bytes = CBS_data(&peer_cert);
330
14
    if (d2i_X509(&s->peer_cert, &peer_cert_bytes,
331
14
        (long)data_len) == NULL)
332
11
      goto err;
333
14
  }
334
335
  /* Session ID context [4]. */
336
717
  s->sid_ctx_length = 0;
337
717
  if (!CBS_get_optional_asn1_octet_string(&session, &session_id, &present,
338
717
      SSLASN1_SESSION_ID_CTX_TAG))
339
29
    goto err;
340
688
  if (present) {
341
10
    if (!CBS_write_bytes(&session_id, (uint8_t *)&s->sid_ctx,
342
10
        sizeof(s->sid_ctx), &s->sid_ctx_length))
343
2
      goto err;
344
10
  }
345
346
  /* Verify result [5]. */
347
686
  s->verify_result = X509_V_OK;
348
686
  if (!CBS_get_optional_asn1_uint64(&session, &verify_result,
349
686
      SSLASN1_VERIFY_RESULT_TAG, X509_V_OK))
350
19
    goto err;
351
667
  if (verify_result > LONG_MAX)
352
59
    goto err;
353
608
  s->verify_result = (long)verify_result;
354
355
  /* Hostname [6]. */
356
608
  free(s->tlsext_hostname);
357
608
  s->tlsext_hostname = NULL;
358
608
  if (!CBS_get_optional_asn1_octet_string(&session, &hostname, &present,
359
608
      SSLASN1_HOSTNAME_TAG))
360
18
    goto err;
361
590
  if (present) {
362
3
    if (CBS_contains_zero_byte(&hostname))
363
2
      goto err;
364
1
    if (!CBS_strdup(&hostname, &s->tlsext_hostname))
365
0
      goto err;
366
1
  }
367
368
  /* PSK identity hint [7]. */
369
  /* PSK identity [8]. */
370
371
  /* Ticket lifetime [9]. */
372
588
  s->tlsext_tick_lifetime_hint = 0;
373
588
  if (!CBS_get_optional_asn1_uint64(&session, &lifetime,
374
588
      SSLASN1_LIFETIME_TAG, 0))
375
8
    goto err;
376
580
  if (lifetime > UINT32_MAX)
377
60
    goto err;
378
520
  if (lifetime > 0)
379
49
    s->tlsext_tick_lifetime_hint = (uint32_t)lifetime;
380
381
  /* Ticket [10]. */
382
520
  free(s->tlsext_tick);
383
520
  s->tlsext_tick = NULL;
384
520
  if (!CBS_get_optional_asn1_octet_string(&session, &ticket, &present,
385
520
      SSLASN1_TICKET_TAG))
386
114
    goto err;
387
406
  if (present) {
388
11
    if (!CBS_stow(&ticket, &s->tlsext_tick, &s->tlsext_ticklen))
389
0
      goto err;
390
11
  }
391
392
  /* Compression method [11]. */
393
  /* SRP username [12]. */
394
395
406
  *pp = CBS_data(&cbs);
396
397
406
  if (a != NULL)
398
0
    *a = s;
399
400
406
  return (s);
401
402
10.2k
 err:
403
10.2k
  ERR_asprintf_error_data("offset=%d", (int)(CBS_data(&cbs) - *pp));
404
405
10.2k
  if (s != NULL && (a == NULL || *a != s))
406
10.2k
    SSL_SESSION_free(s);
407
408
10.2k
  return (NULL);
409
406
}
410
LSSL_ALIAS(d2i_SSL_SESSION);