1*de0e0e4dSAntonio Huete Jimenez /* $OpenBSD: ssl_asn1.c,v 1.65 2022/06/07 17:53:42 tb Exp $ */
272c33676SMaxim Ag /*
372c33676SMaxim Ag * Copyright (c) 2016 Joel Sing <jsing@openbsd.org>
4f5b1c8a1SJohn Marino *
572c33676SMaxim Ag * Permission to use, copy, modify, and distribute this software for any
672c33676SMaxim Ag * purpose with or without fee is hereby granted, provided that the above
772c33676SMaxim Ag * copyright notice and this permission notice appear in all copies.
8f5b1c8a1SJohn Marino *
972c33676SMaxim Ag * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1072c33676SMaxim Ag * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1172c33676SMaxim Ag * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1272c33676SMaxim Ag * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1372c33676SMaxim Ag * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1472c33676SMaxim Ag * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1572c33676SMaxim Ag * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16f5b1c8a1SJohn Marino */
17f5b1c8a1SJohn Marino
1872c33676SMaxim Ag #include <limits.h>
1972c33676SMaxim Ag
2072c33676SMaxim Ag #include <openssl/ssl.h>
2172c33676SMaxim Ag #include <openssl/x509.h>
22f5b1c8a1SJohn Marino
2372c33676SMaxim Ag #include "bytestring.h"
24*de0e0e4dSAntonio Huete Jimenez #include "ssl_locl.h"
25f5b1c8a1SJohn Marino
2672c33676SMaxim Ag #define SSLASN1_TAG (CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC)
2772c33676SMaxim Ag #define SSLASN1_TIME_TAG (SSLASN1_TAG | 1)
2872c33676SMaxim Ag #define SSLASN1_TIMEOUT_TAG (SSLASN1_TAG | 2)
2972c33676SMaxim Ag #define SSLASN1_PEER_CERT_TAG (SSLASN1_TAG | 3)
3072c33676SMaxim Ag #define SSLASN1_SESSION_ID_CTX_TAG (SSLASN1_TAG | 4)
3172c33676SMaxim Ag #define SSLASN1_VERIFY_RESULT_TAG (SSLASN1_TAG | 5)
3272c33676SMaxim Ag #define SSLASN1_HOSTNAME_TAG (SSLASN1_TAG | 6)
3372c33676SMaxim Ag #define SSLASN1_LIFETIME_TAG (SSLASN1_TAG | 9)
3472c33676SMaxim Ag #define SSLASN1_TICKET_TAG (SSLASN1_TAG | 10)
35f5b1c8a1SJohn Marino
3672c33676SMaxim Ag static uint64_t
time_max(void)3772c33676SMaxim Ag time_max(void)
3872c33676SMaxim Ag {
3972c33676SMaxim Ag if (sizeof(time_t) == sizeof(int32_t))
4072c33676SMaxim Ag return INT32_MAX;
4172c33676SMaxim Ag if (sizeof(time_t) == sizeof(int64_t))
4272c33676SMaxim Ag return INT64_MAX;
4372c33676SMaxim Ag return 0;
4472c33676SMaxim Ag }
4572c33676SMaxim Ag
4672c33676SMaxim Ag static int
SSL_SESSION_encode(SSL_SESSION * s,unsigned char ** out,size_t * out_len,int ticket_encoding)4772c33676SMaxim Ag SSL_SESSION_encode(SSL_SESSION *s, unsigned char **out, size_t *out_len,
4872c33676SMaxim Ag int ticket_encoding)
4972c33676SMaxim Ag {
5072c33676SMaxim Ag CBB cbb, session, cipher_suite, session_id, master_key, time, timeout;
5172c33676SMaxim Ag CBB peer_cert, sidctx, verify_result, hostname, lifetime, ticket, value;
5272c33676SMaxim Ag unsigned char *peer_cert_bytes = NULL;
5372c33676SMaxim Ag int len, rv = 0;
5472c33676SMaxim Ag uint16_t cid;
5572c33676SMaxim Ag
5672c33676SMaxim Ag if (!CBB_init(&cbb, 0))
5772c33676SMaxim Ag goto err;
5872c33676SMaxim Ag
5972c33676SMaxim Ag if (!CBB_add_asn1(&cbb, &session, CBS_ASN1_SEQUENCE))
6072c33676SMaxim Ag goto err;
6172c33676SMaxim Ag
6272c33676SMaxim Ag /* Session ASN1 version. */
6372c33676SMaxim Ag if (!CBB_add_asn1_uint64(&session, SSL_SESSION_ASN1_VERSION))
6472c33676SMaxim Ag goto err;
6572c33676SMaxim Ag
6672c33676SMaxim Ag /* TLS/SSL protocol version. */
6772c33676SMaxim Ag if (s->ssl_version < 0)
6872c33676SMaxim Ag goto err;
6972c33676SMaxim Ag if (!CBB_add_asn1_uint64(&session, s->ssl_version))
7072c33676SMaxim Ag goto err;
7172c33676SMaxim Ag
7272c33676SMaxim Ag /* Cipher suite ID. */
7372c33676SMaxim Ag /* XXX - require cipher to be non-NULL or always/only use cipher_id. */
74*de0e0e4dSAntonio Huete Jimenez cid = (uint16_t)(s->cipher_id & SSL3_CK_VALUE_MASK);
7572c33676SMaxim Ag if (s->cipher != NULL)
7672c33676SMaxim Ag cid = ssl3_cipher_get_value(s->cipher);
7772c33676SMaxim Ag if (!CBB_add_asn1(&session, &cipher_suite, CBS_ASN1_OCTETSTRING))
7872c33676SMaxim Ag goto err;
7972c33676SMaxim Ag if (!CBB_add_u16(&cipher_suite, cid))
8072c33676SMaxim Ag goto err;
8172c33676SMaxim Ag
8272c33676SMaxim Ag /* Session ID - zero length for a ticket. */
8372c33676SMaxim Ag if (!CBB_add_asn1(&session, &session_id, CBS_ASN1_OCTETSTRING))
8472c33676SMaxim Ag goto err;
8572c33676SMaxim Ag if (!CBB_add_bytes(&session_id, s->session_id,
8672c33676SMaxim Ag ticket_encoding ? 0 : s->session_id_length))
8772c33676SMaxim Ag goto err;
8872c33676SMaxim Ag
8972c33676SMaxim Ag /* Master key. */
9072c33676SMaxim Ag if (!CBB_add_asn1(&session, &master_key, CBS_ASN1_OCTETSTRING))
9172c33676SMaxim Ag goto err;
9272c33676SMaxim Ag if (!CBB_add_bytes(&master_key, s->master_key, s->master_key_length))
9372c33676SMaxim Ag goto err;
9472c33676SMaxim Ag
9572c33676SMaxim Ag /* Time [1]. */
9672c33676SMaxim Ag if (s->time != 0) {
9772c33676SMaxim Ag if (s->time < 0)
9872c33676SMaxim Ag goto err;
9972c33676SMaxim Ag if (!CBB_add_asn1(&session, &time, SSLASN1_TIME_TAG))
10072c33676SMaxim Ag goto err;
10172c33676SMaxim Ag if (!CBB_add_asn1_uint64(&time, s->time))
10272c33676SMaxim Ag goto err;
10372c33676SMaxim Ag }
10472c33676SMaxim Ag
10572c33676SMaxim Ag /* Timeout [2]. */
10672c33676SMaxim Ag if (s->timeout != 0) {
10772c33676SMaxim Ag if (s->timeout < 0)
10872c33676SMaxim Ag goto err;
10972c33676SMaxim Ag if (!CBB_add_asn1(&session, &timeout, SSLASN1_TIMEOUT_TAG))
11072c33676SMaxim Ag goto err;
11172c33676SMaxim Ag if (!CBB_add_asn1_uint64(&timeout, s->timeout))
11272c33676SMaxim Ag goto err;
11372c33676SMaxim Ag }
11472c33676SMaxim Ag
11572c33676SMaxim Ag /* Peer certificate [3]. */
116*de0e0e4dSAntonio Huete Jimenez if (s->peer_cert != NULL) {
117*de0e0e4dSAntonio Huete Jimenez if ((len = i2d_X509(s->peer_cert, &peer_cert_bytes)) <= 0)
11872c33676SMaxim Ag goto err;
11972c33676SMaxim Ag if (!CBB_add_asn1(&session, &peer_cert, SSLASN1_PEER_CERT_TAG))
12072c33676SMaxim Ag goto err;
12172c33676SMaxim Ag if (!CBB_add_bytes(&peer_cert, peer_cert_bytes, len))
12272c33676SMaxim Ag goto err;
12372c33676SMaxim Ag }
12472c33676SMaxim Ag
12572c33676SMaxim Ag /* Session ID context [4]. */
12672c33676SMaxim Ag /* XXX - Actually handle this as optional? */
12772c33676SMaxim Ag if (!CBB_add_asn1(&session, &sidctx, SSLASN1_SESSION_ID_CTX_TAG))
12872c33676SMaxim Ag goto err;
12972c33676SMaxim Ag if (!CBB_add_asn1(&sidctx, &value, CBS_ASN1_OCTETSTRING))
13072c33676SMaxim Ag goto err;
13172c33676SMaxim Ag if (!CBB_add_bytes(&value, s->sid_ctx, s->sid_ctx_length))
13272c33676SMaxim Ag goto err;
13372c33676SMaxim Ag
13472c33676SMaxim Ag /* Verify result [5]. */
13572c33676SMaxim Ag if (s->verify_result != X509_V_OK) {
13672c33676SMaxim Ag if (s->verify_result < 0)
13772c33676SMaxim Ag goto err;
13872c33676SMaxim Ag if (!CBB_add_asn1(&session, &verify_result,
13972c33676SMaxim Ag SSLASN1_VERIFY_RESULT_TAG))
14072c33676SMaxim Ag goto err;
14172c33676SMaxim Ag if (!CBB_add_asn1_uint64(&verify_result, s->verify_result))
14272c33676SMaxim Ag goto err;
14372c33676SMaxim Ag }
14472c33676SMaxim Ag
14572c33676SMaxim Ag /* Hostname [6]. */
14672c33676SMaxim Ag if (s->tlsext_hostname != NULL) {
14772c33676SMaxim Ag if (!CBB_add_asn1(&session, &hostname, SSLASN1_HOSTNAME_TAG))
14872c33676SMaxim Ag goto err;
14972c33676SMaxim Ag if (!CBB_add_asn1(&hostname, &value, CBS_ASN1_OCTETSTRING))
15072c33676SMaxim Ag goto err;
15172c33676SMaxim Ag if (!CBB_add_bytes(&value, (const uint8_t *)s->tlsext_hostname,
15272c33676SMaxim Ag strlen(s->tlsext_hostname)))
15372c33676SMaxim Ag goto err;
15472c33676SMaxim Ag }
15572c33676SMaxim Ag
15672c33676SMaxim Ag /* PSK identity hint [7]. */
15772c33676SMaxim Ag /* PSK identity [8]. */
15872c33676SMaxim Ag
15972c33676SMaxim Ag /* Ticket lifetime hint [9]. */
16072c33676SMaxim Ag if (s->tlsext_tick_lifetime_hint > 0) {
16172c33676SMaxim Ag if (!CBB_add_asn1(&session, &lifetime, SSLASN1_LIFETIME_TAG))
16272c33676SMaxim Ag goto err;
16372c33676SMaxim Ag if (!CBB_add_asn1_uint64(&lifetime,
16472c33676SMaxim Ag s->tlsext_tick_lifetime_hint))
16572c33676SMaxim Ag goto err;
16672c33676SMaxim Ag }
16772c33676SMaxim Ag
16872c33676SMaxim Ag /* Ticket [10]. */
16972c33676SMaxim Ag if (s->tlsext_tick != NULL) {
17072c33676SMaxim Ag if (!CBB_add_asn1(&session, &ticket, SSLASN1_TICKET_TAG))
17172c33676SMaxim Ag goto err;
17272c33676SMaxim Ag if (!CBB_add_asn1(&ticket, &value, CBS_ASN1_OCTETSTRING))
17372c33676SMaxim Ag goto err;
17472c33676SMaxim Ag if (!CBB_add_bytes(&value, s->tlsext_tick, s->tlsext_ticklen))
17572c33676SMaxim Ag goto err;
17672c33676SMaxim Ag }
17772c33676SMaxim Ag
17872c33676SMaxim Ag /* Compression method [11]. */
17972c33676SMaxim Ag /* SRP username [12]. */
18072c33676SMaxim Ag
18172c33676SMaxim Ag if (!CBB_finish(&cbb, out, out_len))
18272c33676SMaxim Ag goto err;
18372c33676SMaxim Ag
18472c33676SMaxim Ag rv = 1;
18572c33676SMaxim Ag
18672c33676SMaxim Ag err:
18772c33676SMaxim Ag CBB_cleanup(&cbb);
18872c33676SMaxim Ag free(peer_cert_bytes);
18972c33676SMaxim Ag
19072c33676SMaxim Ag return rv;
19172c33676SMaxim Ag }
192f5b1c8a1SJohn Marino
193f5b1c8a1SJohn Marino int
SSL_SESSION_ticket(SSL_SESSION * ss,unsigned char ** out,size_t * out_len)19472c33676SMaxim Ag SSL_SESSION_ticket(SSL_SESSION *ss, unsigned char **out, size_t *out_len)
195f5b1c8a1SJohn Marino {
19672c33676SMaxim Ag if (ss == NULL)
19772c33676SMaxim Ag return 0;
198f5b1c8a1SJohn Marino
19972c33676SMaxim Ag if (ss->cipher == NULL && ss->cipher_id == 0)
20072c33676SMaxim Ag return 0;
201f5b1c8a1SJohn Marino
20272c33676SMaxim Ag return SSL_SESSION_encode(ss, out, out_len, 1);
203f5b1c8a1SJohn Marino }
204f5b1c8a1SJohn Marino
20572c33676SMaxim Ag int
i2d_SSL_SESSION(SSL_SESSION * ss,unsigned char ** pp)20672c33676SMaxim Ag i2d_SSL_SESSION(SSL_SESSION *ss, unsigned char **pp)
20772c33676SMaxim Ag {
20872c33676SMaxim Ag unsigned char *data = NULL;
20972c33676SMaxim Ag size_t data_len = 0;
21072c33676SMaxim Ag int rv = -1;
21172c33676SMaxim Ag
21272c33676SMaxim Ag if (ss == NULL)
21372c33676SMaxim Ag return 0;
21472c33676SMaxim Ag
21572c33676SMaxim Ag if (ss->cipher == NULL && ss->cipher_id == 0)
21672c33676SMaxim Ag return 0;
21772c33676SMaxim Ag
21872c33676SMaxim Ag if (!SSL_SESSION_encode(ss, &data, &data_len, 0))
21972c33676SMaxim Ag goto err;
22072c33676SMaxim Ag
22172c33676SMaxim Ag if (data_len > INT_MAX)
22272c33676SMaxim Ag goto err;
22372c33676SMaxim Ag
22472c33676SMaxim Ag if (pp != NULL) {
22572c33676SMaxim Ag if (*pp == NULL) {
22672c33676SMaxim Ag *pp = data;
22772c33676SMaxim Ag data = NULL;
22872c33676SMaxim Ag } else {
22972c33676SMaxim Ag memcpy(*pp, data, data_len);
23072c33676SMaxim Ag *pp += data_len;
23172c33676SMaxim Ag }
232f5b1c8a1SJohn Marino }
233f5b1c8a1SJohn Marino
23472c33676SMaxim Ag rv = (int)data_len;
235f5b1c8a1SJohn Marino
23672c33676SMaxim Ag err:
23772c33676SMaxim Ag freezero(data, data_len);
238f5b1c8a1SJohn Marino
23972c33676SMaxim Ag return rv;
240f5b1c8a1SJohn Marino }
241f5b1c8a1SJohn Marino
242f5b1c8a1SJohn Marino SSL_SESSION *
d2i_SSL_SESSION(SSL_SESSION ** a,const unsigned char ** pp,long length)243f5b1c8a1SJohn Marino d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp, long length)
244f5b1c8a1SJohn Marino {
24572c33676SMaxim Ag CBS cbs, session, cipher_suite, session_id, master_key, peer_cert;
24672c33676SMaxim Ag CBS hostname, ticket;
24772c33676SMaxim Ag uint64_t version, tls_version, stime, timeout, verify_result, lifetime;
24872c33676SMaxim Ag const unsigned char *peer_cert_bytes;
24972c33676SMaxim Ag uint16_t cipher_value;
25072c33676SMaxim Ag SSL_SESSION *s = NULL;
25172c33676SMaxim Ag size_t data_len;
25272c33676SMaxim Ag int present;
253f5b1c8a1SJohn Marino
254f5b1c8a1SJohn Marino if (a != NULL)
25572c33676SMaxim Ag s = *a;
256f5b1c8a1SJohn Marino
25772c33676SMaxim Ag if (s == NULL) {
25872c33676SMaxim Ag if ((s = SSL_SESSION_new()) == NULL) {
25972c33676SMaxim Ag SSLerrorx(ERR_R_MALLOC_FAILURE);
26072c33676SMaxim Ag return (NULL);
26172c33676SMaxim Ag }
26272c33676SMaxim Ag }
26372c33676SMaxim Ag
26472c33676SMaxim Ag CBS_init(&cbs, *pp, length);
26572c33676SMaxim Ag
26672c33676SMaxim Ag if (!CBS_get_asn1(&cbs, &session, CBS_ASN1_SEQUENCE))
26772c33676SMaxim Ag goto err;
26872c33676SMaxim Ag
26972c33676SMaxim Ag /* Session ASN1 version. */
27072c33676SMaxim Ag if (!CBS_get_asn1_uint64(&session, &version))
27172c33676SMaxim Ag goto err;
27272c33676SMaxim Ag if (version != SSL_SESSION_ASN1_VERSION)
27372c33676SMaxim Ag goto err;
27472c33676SMaxim Ag
27572c33676SMaxim Ag /* TLS/SSL Protocol Version. */
27672c33676SMaxim Ag if (!CBS_get_asn1_uint64(&session, &tls_version))
27772c33676SMaxim Ag goto err;
27872c33676SMaxim Ag if (tls_version > INT_MAX)
27972c33676SMaxim Ag goto err;
28072c33676SMaxim Ag s->ssl_version = (int)tls_version;
28172c33676SMaxim Ag
28272c33676SMaxim Ag /* Cipher suite. */
28372c33676SMaxim Ag if (!CBS_get_asn1(&session, &cipher_suite, CBS_ASN1_OCTETSTRING))
28472c33676SMaxim Ag goto err;
28572c33676SMaxim Ag if (!CBS_get_u16(&cipher_suite, &cipher_value))
28672c33676SMaxim Ag goto err;
28772c33676SMaxim Ag if (CBS_len(&cipher_suite) != 0)
28872c33676SMaxim Ag goto err;
28972c33676SMaxim Ag
29072c33676SMaxim Ag /* XXX - populate cipher instead? */
29172c33676SMaxim Ag s->cipher = NULL;
29272c33676SMaxim Ag s->cipher_id = SSL3_CK_ID | cipher_value;
29372c33676SMaxim Ag
29472c33676SMaxim Ag /* Session ID. */
29572c33676SMaxim Ag if (!CBS_get_asn1(&session, &session_id, CBS_ASN1_OCTETSTRING))
29672c33676SMaxim Ag goto err;
29772c33676SMaxim Ag if (!CBS_write_bytes(&session_id, s->session_id, sizeof(s->session_id),
298*de0e0e4dSAntonio Huete Jimenez &s->session_id_length))
29972c33676SMaxim Ag goto err;
30072c33676SMaxim Ag
30172c33676SMaxim Ag /* Master key. */
30272c33676SMaxim Ag if (!CBS_get_asn1(&session, &master_key, CBS_ASN1_OCTETSTRING))
30372c33676SMaxim Ag goto err;
30472c33676SMaxim Ag if (!CBS_write_bytes(&master_key, s->master_key, sizeof(s->master_key),
305*de0e0e4dSAntonio Huete Jimenez &s->master_key_length))
30672c33676SMaxim Ag goto err;
30772c33676SMaxim Ag
30872c33676SMaxim Ag /* Time [1]. */
30972c33676SMaxim Ag s->time = time(NULL);
31072c33676SMaxim Ag if (!CBS_get_optional_asn1_uint64(&session, &stime, SSLASN1_TIME_TAG,
31172c33676SMaxim Ag 0))
31272c33676SMaxim Ag goto err;
31372c33676SMaxim Ag if (stime > time_max())
31472c33676SMaxim Ag goto err;
31572c33676SMaxim Ag if (stime != 0)
31672c33676SMaxim Ag s->time = (time_t)stime;
31772c33676SMaxim Ag
31872c33676SMaxim Ag /* Timeout [2]. */
31972c33676SMaxim Ag s->timeout = 3;
32072c33676SMaxim Ag if (!CBS_get_optional_asn1_uint64(&session, &timeout,
32172c33676SMaxim Ag SSLASN1_TIMEOUT_TAG, 0))
32272c33676SMaxim Ag goto err;
32372c33676SMaxim Ag if (timeout > LONG_MAX)
32472c33676SMaxim Ag goto err;
32572c33676SMaxim Ag if (timeout != 0)
32672c33676SMaxim Ag s->timeout = (long)timeout;
32772c33676SMaxim Ag
32872c33676SMaxim Ag /* Peer certificate [3]. */
329*de0e0e4dSAntonio Huete Jimenez X509_free(s->peer_cert);
330*de0e0e4dSAntonio Huete Jimenez s->peer_cert = NULL;
33172c33676SMaxim Ag if (!CBS_get_optional_asn1(&session, &peer_cert, &present,
33272c33676SMaxim Ag SSLASN1_PEER_CERT_TAG))
33372c33676SMaxim Ag goto err;
33472c33676SMaxim Ag if (present) {
33572c33676SMaxim Ag data_len = CBS_len(&peer_cert);
33672c33676SMaxim Ag if (data_len > LONG_MAX)
33772c33676SMaxim Ag goto err;
33872c33676SMaxim Ag peer_cert_bytes = CBS_data(&peer_cert);
339*de0e0e4dSAntonio Huete Jimenez if (d2i_X509(&s->peer_cert, &peer_cert_bytes,
34072c33676SMaxim Ag (long)data_len) == NULL)
34172c33676SMaxim Ag goto err;
34272c33676SMaxim Ag }
34372c33676SMaxim Ag
34472c33676SMaxim Ag /* Session ID context [4]. */
34572c33676SMaxim Ag s->sid_ctx_length = 0;
34672c33676SMaxim Ag if (!CBS_get_optional_asn1_octet_string(&session, &session_id, &present,
34772c33676SMaxim Ag SSLASN1_SESSION_ID_CTX_TAG))
34872c33676SMaxim Ag goto err;
34972c33676SMaxim Ag if (present) {
35072c33676SMaxim Ag if (!CBS_write_bytes(&session_id, (uint8_t *)&s->sid_ctx,
351*de0e0e4dSAntonio Huete Jimenez sizeof(s->sid_ctx), &s->sid_ctx_length))
35272c33676SMaxim Ag goto err;
35372c33676SMaxim Ag }
35472c33676SMaxim Ag
35572c33676SMaxim Ag /* Verify result [5]. */
35672c33676SMaxim Ag s->verify_result = X509_V_OK;
35772c33676SMaxim Ag if (!CBS_get_optional_asn1_uint64(&session, &verify_result,
35872c33676SMaxim Ag SSLASN1_VERIFY_RESULT_TAG, X509_V_OK))
35972c33676SMaxim Ag goto err;
36072c33676SMaxim Ag if (verify_result > LONG_MAX)
36172c33676SMaxim Ag goto err;
36272c33676SMaxim Ag s->verify_result = (long)verify_result;
36372c33676SMaxim Ag
36472c33676SMaxim Ag /* Hostname [6]. */
36572c33676SMaxim Ag free(s->tlsext_hostname);
36672c33676SMaxim Ag s->tlsext_hostname = NULL;
36772c33676SMaxim Ag if (!CBS_get_optional_asn1_octet_string(&session, &hostname, &present,
36872c33676SMaxim Ag SSLASN1_HOSTNAME_TAG))
36972c33676SMaxim Ag goto err;
37072c33676SMaxim Ag if (present) {
37172c33676SMaxim Ag if (CBS_contains_zero_byte(&hostname))
37272c33676SMaxim Ag goto err;
37372c33676SMaxim Ag if (!CBS_strdup(&hostname, &s->tlsext_hostname))
37472c33676SMaxim Ag goto err;
37572c33676SMaxim Ag }
37672c33676SMaxim Ag
37772c33676SMaxim Ag /* PSK identity hint [7]. */
37872c33676SMaxim Ag /* PSK identity [8]. */
37972c33676SMaxim Ag
38072c33676SMaxim Ag /* Ticket lifetime [9]. */
38172c33676SMaxim Ag s->tlsext_tick_lifetime_hint = 0;
38272c33676SMaxim Ag if (!CBS_get_optional_asn1_uint64(&session, &lifetime,
38372c33676SMaxim Ag SSLASN1_LIFETIME_TAG, 0))
38472c33676SMaxim Ag goto err;
385*de0e0e4dSAntonio Huete Jimenez if (lifetime > UINT32_MAX)
38672c33676SMaxim Ag goto err;
38772c33676SMaxim Ag if (lifetime > 0)
388*de0e0e4dSAntonio Huete Jimenez s->tlsext_tick_lifetime_hint = (uint32_t)lifetime;
38972c33676SMaxim Ag
39072c33676SMaxim Ag /* Ticket [10]. */
39172c33676SMaxim Ag free(s->tlsext_tick);
39272c33676SMaxim Ag s->tlsext_tick = NULL;
39372c33676SMaxim Ag if (!CBS_get_optional_asn1_octet_string(&session, &ticket, &present,
39472c33676SMaxim Ag SSLASN1_TICKET_TAG))
39572c33676SMaxim Ag goto err;
39672c33676SMaxim Ag if (present) {
39772c33676SMaxim Ag if (!CBS_stow(&ticket, &s->tlsext_tick, &s->tlsext_ticklen))
39872c33676SMaxim Ag goto err;
39972c33676SMaxim Ag }
40072c33676SMaxim Ag
40172c33676SMaxim Ag /* Compression method [11]. */
40272c33676SMaxim Ag /* SRP username [12]. */
40372c33676SMaxim Ag
40472c33676SMaxim Ag *pp = CBS_data(&cbs);
40572c33676SMaxim Ag
40672c33676SMaxim Ag if (a != NULL)
40772c33676SMaxim Ag *a = s;
40872c33676SMaxim Ag
40972c33676SMaxim Ag return (s);
410f5b1c8a1SJohn Marino
411f5b1c8a1SJohn Marino err:
41272c33676SMaxim Ag ERR_asprintf_error_data("offset=%d", (int)(CBS_data(&cbs) - *pp));
41372c33676SMaxim Ag
41472c33676SMaxim Ag if (s != NULL && (a == NULL || *a != s))
41572c33676SMaxim Ag SSL_SESSION_free(s);
416f5b1c8a1SJohn Marino
417f5b1c8a1SJohn Marino return (NULL);
418f5b1c8a1SJohn Marino }
419