-/* $OpenBSD: ssl_asn1.c,v 1.56 2018/03/20 16:10:57 jsing Exp $ */
+/* $OpenBSD: ssl_asn1.c,v 1.57 2018/08/27 16:42:48 jsing Exp $ */
/*
* Copyright (c) 2016 Joel Sing <jsing@openbsd.org>
*
return 0;
}
-int
-i2d_SSL_SESSION(SSL_SESSION *s, unsigned char **pp)
+static int
+SSL_SESSION_encode(SSL_SESSION *s, unsigned char **out, size_t *out_len,
+ int ticket_encoding)
{
CBB cbb, session, cipher_suite, session_id, master_key, time, timeout;
- CBB peer_cert, sidctx, verify_result, hostname, lifetime, ticket;
- CBB value;
- unsigned char *data = NULL, *peer_cert_bytes = NULL;
- size_t data_len = 0;
- int len, rv = -1;
+ CBB peer_cert, sidctx, verify_result, hostname, lifetime, ticket, value;
+ unsigned char *peer_cert_bytes = NULL;
+ int len, rv = 0;
uint16_t cid;
- if (s == NULL)
- return (0);
-
- if (s->cipher == NULL && s->cipher_id == 0)
- return (0);
-
if (!CBB_init(&cbb, 0))
goto err;
if (!CBB_add_u16(&cipher_suite, cid))
goto err;
- /* Session ID. */
+ /* Session ID - zero length for a ticket. */
if (!CBB_add_asn1(&session, &session_id, CBS_ASN1_OCTETSTRING))
goto err;
- if (!CBB_add_bytes(&session_id, s->session_id, s->session_id_length))
+ if (!CBB_add_bytes(&session_id, s->session_id,
+ ticket_encoding ? 0 : s->session_id_length))
goto err;
/* Master key. */
}
/* Ticket [10]. */
- if (s->tlsext_tick) {
+ if (s->tlsext_tick != NULL) {
if (!CBB_add_asn1(&session, &ticket, SSLASN1_TICKET_TAG))
goto err;
if (!CBB_add_asn1(&ticket, &value, CBS_ASN1_OCTETSTRING))
/* Compression method [11]. */
/* SRP username [12]. */
- if (!CBB_finish(&cbb, &data, &data_len))
+ if (!CBB_finish(&cbb, out, out_len))
+ goto err;
+
+ rv = 1;
+
+ err:
+ CBB_cleanup(&cbb);
+ free(peer_cert_bytes);
+
+ return rv;
+}
+
+int
+SSL_SESSION_ticket(SSL_SESSION *ss, unsigned char **out, size_t *out_len)
+{
+ if (ss == NULL)
+ return 0;
+
+ if (ss->cipher == NULL && ss->cipher_id == 0)
+ return 0;
+
+ return SSL_SESSION_encode(ss, out, out_len, 1);
+}
+
+int
+i2d_SSL_SESSION(SSL_SESSION *ss, unsigned char **pp)
+{
+ unsigned char *data = NULL;
+ size_t data_len = 0;
+ int rv = -1;
+
+ if (ss == NULL)
+ return 0;
+
+ if (ss->cipher == NULL && ss->cipher_id == 0)
+ return 0;
+
+ if (!SSL_SESSION_encode(ss, &data, &data_len, 0))
goto err;
if (data_len > INT_MAX)
rv = (int)data_len;
err:
- CBB_cleanup(&cbb);
freezero(data, data_len);
- free(peer_cert_bytes);
return rv;
}
-/* $OpenBSD: ssl_srvr.c,v 1.45 2018/08/24 18:10:25 jsing Exp $ */
+/* $OpenBSD: ssl_srvr.c,v 1.46 2018/08/27 16:42:48 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
ssl3_send_newsession_ticket(SSL *s)
{
CBB cbb, session_ticket, ticket;
- unsigned char *enc_ticket = NULL;
- unsigned char *senc = NULL;
- const unsigned char *const_p;
- unsigned char *p, *hmac;
- size_t hmac_len;
- int enc_ticket_len, len, slen;
- int slen_full = 0;
- SSL_SESSION *sess;
- unsigned int hlen;
- EVP_CIPHER_CTX ctx;
- HMAC_CTX hctx;
SSL_CTX *tctx = s->initial_ctx;
+ size_t enc_session_len, enc_session_max_len, hmac_len;
+ size_t session_len = 0;
+ unsigned char *enc_session = NULL, *session = NULL;
unsigned char iv[EVP_MAX_IV_LENGTH];
unsigned char key_name[16];
+ unsigned char *hmac;
+ unsigned int hlen;
+ EVP_CIPHER_CTX ctx;
+ HMAC_CTX hctx;
+ int len;
+
+ /*
+ * New Session Ticket - RFC 5077, section 3.3.
+ */
EVP_CIPHER_CTX_init(&ctx);
HMAC_CTX_init(&hctx);
SSL3_MT_NEWSESSION_TICKET))
goto err;
- /* get session encoding length */
- slen_full = i2d_SSL_SESSION(s->session, NULL);
- /*
- * Some length values are 16 bits, so forget it if session is
- * too long
- */
- if (slen_full > 0xFF00)
+ if (!SSL_SESSION_ticket(s->session, &session, &session_len))
goto err;
- senc = malloc(slen_full);
- if (!senc)
+ if (session_len > 0xffff)
goto err;
- p = senc;
- i2d_SSL_SESSION(s->session, &p);
/*
- * Create a fresh copy (not shared with other threads) to
- * clean up
+ * Initialize HMAC and cipher contexts. If callback is present
+ * it does all the work, otherwise use generated values from
+ * parent context.
*/
- const_p = senc;
- sess = d2i_SSL_SESSION(NULL, &const_p, slen_full);
- if (sess == NULL)
- goto err;
-
- /* ID is irrelevant for the ticket */
- sess->session_id_length = 0;
-
- slen = i2d_SSL_SESSION(sess, NULL);
- if (slen > slen_full) {
- /* shouldn't ever happen */
- goto err;
- }
- p = senc;
- i2d_SSL_SESSION(sess, &p);
- SSL_SESSION_free(sess);
-
- /*
- * Initialize HMAC and cipher contexts. If callback present
- * it does all the work otherwise use generated values
- * from parent ctx.
- */
- if (tctx->internal->tlsext_ticket_key_cb) {
+ if (tctx->internal->tlsext_ticket_key_cb != NULL) {
if (tctx->internal->tlsext_ticket_key_cb(s,
key_name, iv, &ctx, &hctx, 1) < 0) {
EVP_CIPHER_CTX_cleanup(&ctx);
memcpy(key_name, tctx->internal->tlsext_tick_key_name, 16);
}
- /* Encrypt the session ticket. */
- if ((enc_ticket = calloc(1, slen + EVP_MAX_BLOCK_LENGTH)) == NULL)
+ /* Encrypt the session state. */
+ enc_session_max_len = session_len + EVP_MAX_BLOCK_LENGTH;
+ if ((enc_session = calloc(1, enc_session_max_len)) == NULL)
goto err;
- enc_ticket_len = 0;
- if (!EVP_EncryptUpdate(&ctx, enc_ticket, &len, senc, slen))
+ enc_session_len = 0;
+ if (!EVP_EncryptUpdate(&ctx, enc_session, &len, session,
+ session_len))
goto err;
- enc_ticket_len += len;
- if (!EVP_EncryptFinal_ex(&ctx, enc_ticket + enc_ticket_len, &len))
+ enc_session_len += len;
+ if (!EVP_EncryptFinal_ex(&ctx, enc_session + enc_session_len,
+ &len))
goto err;
- enc_ticket_len += len;
+ enc_session_len += len;
- if (enc_ticket_len < 0 ||
- enc_ticket_len > slen + EVP_MAX_BLOCK_LENGTH)
+ if (enc_session_len > enc_session_max_len)
goto err;
/* Generate the HMAC. */
goto err;
if (!HMAC_Update(&hctx, iv, EVP_CIPHER_CTX_iv_length(&ctx)))
goto err;
- if (!HMAC_Update(&hctx, enc_ticket, enc_ticket_len))
+ if (!HMAC_Update(&hctx, enc_session, enc_session_len))
goto err;
if ((hmac_len = HMAC_size(&hctx)) <= 0)
goto err;
if (!CBB_add_bytes(&ticket, iv, EVP_CIPHER_CTX_iv_length(&ctx)))
goto err;
- if (!CBB_add_bytes(&ticket, enc_ticket, enc_ticket_len))
+ if (!CBB_add_bytes(&ticket, enc_session, enc_session_len))
goto err;
if (!CBB_add_space(&ticket, &hmac, hmac_len))
goto err;
if (!HMAC_Final(&hctx, hmac, &hlen))
goto err;
+ if (hlen != hmac_len)
+ goto err;
if (!ssl3_handshake_msg_finish(s, &cbb))
goto err;
EVP_CIPHER_CTX_cleanup(&ctx);
HMAC_CTX_cleanup(&hctx);
- freezero(senc, slen_full);
- free(enc_ticket);
+ freezero(session, session_len);
+ free(enc_session);
/* SSL3_ST_SW_SESSION_TICKET_B */
return (ssl3_handshake_write(s));
CBB_cleanup(&cbb);
EVP_CIPHER_CTX_cleanup(&ctx);
HMAC_CTX_cleanup(&hctx);
- freezero(senc, slen_full);
- free(enc_ticket);
+ freezero(session, session_len);
+ free(enc_session);
return (-1);
}