diff options
author | jsing <> | 2018-08-27 16:42:48 +0000 |
---|---|---|
committer | jsing <> | 2018-08-27 16:42:48 +0000 |
commit | 8007465805b60ee08ec66aa02d3525e1a058629c (patch) | |
tree | 71671a4717389a51b5152df1689cea13e657f8ca | |
parent | efb4b7d294563bb79e9a64739754b78928308802 (diff) | |
download | openbsd-8007465805b60ee08ec66aa02d3525e1a058629c.tar.gz openbsd-8007465805b60ee08ec66aa02d3525e1a058629c.tar.bz2 openbsd-8007465805b60ee08ec66aa02d3525e1a058629c.zip |
Simplify new session ticket encoding/generation.
The original code did a crazy encode/malloc/encode/decode/modify/encode
dance, in order to encode a session in the form needed to encrypt then add
to a session ticket. By modifying the encoding functions slightly, we can
do this entire dance as a single encode.
Inspired by similar changes in BoringSSL.
ok inoguchi@ tb@
-rw-r--r-- | src/lib/libssl/ssl_asn1.c | 69 | ||||
-rw-r--r-- | src/lib/libssl/ssl_locl.h | 4 | ||||
-rw-r--r-- | src/lib/libssl/ssl_srvr.c | 101 |
3 files changed, 90 insertions, 84 deletions
diff --git a/src/lib/libssl/ssl_asn1.c b/src/lib/libssl/ssl_asn1.c index 0ca442faa0..94fc8685fc 100644 --- a/src/lib/libssl/ssl_asn1.c +++ b/src/lib/libssl/ssl_asn1.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssl_asn1.c,v 1.56 2018/03/20 16:10:57 jsing Exp $ */ | 1 | /* $OpenBSD: ssl_asn1.c,v 1.57 2018/08/27 16:42:48 jsing Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2016 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2016 Joel Sing <jsing@openbsd.org> |
4 | * | 4 | * |
@@ -44,23 +44,16 @@ time_max(void) | |||
44 | return 0; | 44 | return 0; |
45 | } | 45 | } |
46 | 46 | ||
47 | int | 47 | static int |
48 | i2d_SSL_SESSION(SSL_SESSION *s, unsigned char **pp) | 48 | SSL_SESSION_encode(SSL_SESSION *s, unsigned char **out, size_t *out_len, |
49 | int ticket_encoding) | ||
49 | { | 50 | { |
50 | CBB cbb, session, cipher_suite, session_id, master_key, time, timeout; | 51 | CBB cbb, session, cipher_suite, session_id, master_key, time, timeout; |
51 | CBB peer_cert, sidctx, verify_result, hostname, lifetime, ticket; | 52 | CBB peer_cert, sidctx, verify_result, hostname, lifetime, ticket, value; |
52 | CBB value; | 53 | unsigned char *peer_cert_bytes = NULL; |
53 | unsigned char *data = NULL, *peer_cert_bytes = NULL; | 54 | int len, rv = 0; |
54 | size_t data_len = 0; | ||
55 | int len, rv = -1; | ||
56 | uint16_t cid; | 55 | uint16_t cid; |
57 | 56 | ||
58 | if (s == NULL) | ||
59 | return (0); | ||
60 | |||
61 | if (s->cipher == NULL && s->cipher_id == 0) | ||
62 | return (0); | ||
63 | |||
64 | if (!CBB_init(&cbb, 0)) | 57 | if (!CBB_init(&cbb, 0)) |
65 | goto err; | 58 | goto err; |
66 | 59 | ||
@@ -87,10 +80,11 @@ i2d_SSL_SESSION(SSL_SESSION *s, unsigned char **pp) | |||
87 | if (!CBB_add_u16(&cipher_suite, cid)) | 80 | if (!CBB_add_u16(&cipher_suite, cid)) |
88 | goto err; | 81 | goto err; |
89 | 82 | ||
90 | /* Session ID. */ | 83 | /* Session ID - zero length for a ticket. */ |
91 | if (!CBB_add_asn1(&session, &session_id, CBS_ASN1_OCTETSTRING)) | 84 | if (!CBB_add_asn1(&session, &session_id, CBS_ASN1_OCTETSTRING)) |
92 | goto err; | 85 | goto err; |
93 | if (!CBB_add_bytes(&session_id, s->session_id, s->session_id_length)) | 86 | if (!CBB_add_bytes(&session_id, s->session_id, |
87 | ticket_encoding ? 0 : s->session_id_length)) | ||
94 | goto err; | 88 | goto err; |
95 | 89 | ||
96 | /* Master key. */ | 90 | /* Master key. */ |
@@ -173,7 +167,7 @@ i2d_SSL_SESSION(SSL_SESSION *s, unsigned char **pp) | |||
173 | } | 167 | } |
174 | 168 | ||
175 | /* Ticket [10]. */ | 169 | /* Ticket [10]. */ |
176 | if (s->tlsext_tick) { | 170 | if (s->tlsext_tick != NULL) { |
177 | if (!CBB_add_asn1(&session, &ticket, SSLASN1_TICKET_TAG)) | 171 | if (!CBB_add_asn1(&session, &ticket, SSLASN1_TICKET_TAG)) |
178 | goto err; | 172 | goto err; |
179 | if (!CBB_add_asn1(&ticket, &value, CBS_ASN1_OCTETSTRING)) | 173 | if (!CBB_add_asn1(&ticket, &value, CBS_ASN1_OCTETSTRING)) |
@@ -185,7 +179,44 @@ i2d_SSL_SESSION(SSL_SESSION *s, unsigned char **pp) | |||
185 | /* Compression method [11]. */ | 179 | /* Compression method [11]. */ |
186 | /* SRP username [12]. */ | 180 | /* SRP username [12]. */ |
187 | 181 | ||
188 | if (!CBB_finish(&cbb, &data, &data_len)) | 182 | if (!CBB_finish(&cbb, out, out_len)) |
183 | goto err; | ||
184 | |||
185 | rv = 1; | ||
186 | |||
187 | err: | ||
188 | CBB_cleanup(&cbb); | ||
189 | free(peer_cert_bytes); | ||
190 | |||
191 | return rv; | ||
192 | } | ||
193 | |||
194 | int | ||
195 | SSL_SESSION_ticket(SSL_SESSION *ss, unsigned char **out, size_t *out_len) | ||
196 | { | ||
197 | if (ss == NULL) | ||
198 | return 0; | ||
199 | |||
200 | if (ss->cipher == NULL && ss->cipher_id == 0) | ||
201 | return 0; | ||
202 | |||
203 | return SSL_SESSION_encode(ss, out, out_len, 1); | ||
204 | } | ||
205 | |||
206 | int | ||
207 | i2d_SSL_SESSION(SSL_SESSION *ss, unsigned char **pp) | ||
208 | { | ||
209 | unsigned char *data = NULL; | ||
210 | size_t data_len = 0; | ||
211 | int rv = -1; | ||
212 | |||
213 | if (ss == NULL) | ||
214 | return 0; | ||
215 | |||
216 | if (ss->cipher == NULL && ss->cipher_id == 0) | ||
217 | return 0; | ||
218 | |||
219 | if (!SSL_SESSION_encode(ss, &data, &data_len, 0)) | ||
189 | goto err; | 220 | goto err; |
190 | 221 | ||
191 | if (data_len > INT_MAX) | 222 | if (data_len > INT_MAX) |
@@ -204,9 +235,7 @@ i2d_SSL_SESSION(SSL_SESSION *s, unsigned char **pp) | |||
204 | rv = (int)data_len; | 235 | rv = (int)data_len; |
205 | 236 | ||
206 | err: | 237 | err: |
207 | CBB_cleanup(&cbb); | ||
208 | freezero(data, data_len); | 238 | freezero(data, data_len); |
209 | free(peer_cert_bytes); | ||
210 | 239 | ||
211 | return rv; | 240 | return rv; |
212 | } | 241 | } |
diff --git a/src/lib/libssl/ssl_locl.h b/src/lib/libssl/ssl_locl.h index 44afd1717e..39aabb05fb 100644 --- a/src/lib/libssl/ssl_locl.h +++ b/src/lib/libssl/ssl_locl.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssl_locl.h,v 1.209 2018/08/24 18:10:25 jsing Exp $ */ | 1 | /* $OpenBSD: ssl_locl.h,v 1.210 2018/08/27 16:42:48 jsing Exp $ */ |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
@@ -1089,6 +1089,8 @@ int ssl_has_ecc_ciphers(SSL *s); | |||
1089 | int ssl_verify_alarm_type(long type); | 1089 | int ssl_verify_alarm_type(long type); |
1090 | void ssl_load_ciphers(void); | 1090 | void ssl_load_ciphers(void); |
1091 | 1091 | ||
1092 | int SSL_SESSION_ticket(SSL_SESSION *ss, unsigned char **out, size_t *out_len); | ||
1093 | |||
1092 | const SSL_CIPHER *ssl3_get_cipher_by_char(const unsigned char *p); | 1094 | const SSL_CIPHER *ssl3_get_cipher_by_char(const unsigned char *p); |
1093 | int ssl3_put_cipher_by_char(const SSL_CIPHER *c, unsigned char *p); | 1095 | int ssl3_put_cipher_by_char(const SSL_CIPHER *c, unsigned char *p); |
1094 | int ssl3_send_server_certificate(SSL *s); | 1096 | int ssl3_send_server_certificate(SSL *s); |
diff --git a/src/lib/libssl/ssl_srvr.c b/src/lib/libssl/ssl_srvr.c index f06491e558..b099fdb8b1 100644 --- a/src/lib/libssl/ssl_srvr.c +++ b/src/lib/libssl/ssl_srvr.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssl_srvr.c,v 1.45 2018/08/24 18:10:25 jsing Exp $ */ | 1 | /* $OpenBSD: ssl_srvr.c,v 1.46 2018/08/27 16:42:48 jsing Exp $ */ |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
@@ -2526,20 +2526,21 @@ int | |||
2526 | ssl3_send_newsession_ticket(SSL *s) | 2526 | ssl3_send_newsession_ticket(SSL *s) |
2527 | { | 2527 | { |
2528 | CBB cbb, session_ticket, ticket; | 2528 | CBB cbb, session_ticket, ticket; |
2529 | unsigned char *enc_ticket = NULL; | ||
2530 | unsigned char *senc = NULL; | ||
2531 | const unsigned char *const_p; | ||
2532 | unsigned char *p, *hmac; | ||
2533 | size_t hmac_len; | ||
2534 | int enc_ticket_len, len, slen; | ||
2535 | int slen_full = 0; | ||
2536 | SSL_SESSION *sess; | ||
2537 | unsigned int hlen; | ||
2538 | EVP_CIPHER_CTX ctx; | ||
2539 | HMAC_CTX hctx; | ||
2540 | SSL_CTX *tctx = s->initial_ctx; | 2529 | SSL_CTX *tctx = s->initial_ctx; |
2530 | size_t enc_session_len, enc_session_max_len, hmac_len; | ||
2531 | size_t session_len = 0; | ||
2532 | unsigned char *enc_session = NULL, *session = NULL; | ||
2541 | unsigned char iv[EVP_MAX_IV_LENGTH]; | 2533 | unsigned char iv[EVP_MAX_IV_LENGTH]; |
2542 | unsigned char key_name[16]; | 2534 | unsigned char key_name[16]; |
2535 | unsigned char *hmac; | ||
2536 | unsigned int hlen; | ||
2537 | EVP_CIPHER_CTX ctx; | ||
2538 | HMAC_CTX hctx; | ||
2539 | int len; | ||
2540 | |||
2541 | /* | ||
2542 | * New Session Ticket - RFC 5077, section 3.3. | ||
2543 | */ | ||
2543 | 2544 | ||
2544 | EVP_CIPHER_CTX_init(&ctx); | 2545 | EVP_CIPHER_CTX_init(&ctx); |
2545 | HMAC_CTX_init(&hctx); | 2546 | HMAC_CTX_init(&hctx); |
@@ -2551,47 +2552,17 @@ ssl3_send_newsession_ticket(SSL *s) | |||
2551 | SSL3_MT_NEWSESSION_TICKET)) | 2552 | SSL3_MT_NEWSESSION_TICKET)) |
2552 | goto err; | 2553 | goto err; |
2553 | 2554 | ||
2554 | /* get session encoding length */ | 2555 | if (!SSL_SESSION_ticket(s->session, &session, &session_len)) |
2555 | slen_full = i2d_SSL_SESSION(s->session, NULL); | ||
2556 | /* | ||
2557 | * Some length values are 16 bits, so forget it if session is | ||
2558 | * too long | ||
2559 | */ | ||
2560 | if (slen_full > 0xFF00) | ||
2561 | goto err; | 2556 | goto err; |
2562 | senc = malloc(slen_full); | 2557 | if (session_len > 0xffff) |
2563 | if (!senc) | ||
2564 | goto err; | 2558 | goto err; |
2565 | p = senc; | ||
2566 | i2d_SSL_SESSION(s->session, &p); | ||
2567 | 2559 | ||
2568 | /* | 2560 | /* |
2569 | * Create a fresh copy (not shared with other threads) to | 2561 | * Initialize HMAC and cipher contexts. If callback is present |
2570 | * clean up | 2562 | * it does all the work, otherwise use generated values from |
2563 | * parent context. | ||
2571 | */ | 2564 | */ |
2572 | const_p = senc; | 2565 | if (tctx->internal->tlsext_ticket_key_cb != NULL) { |
2573 | sess = d2i_SSL_SESSION(NULL, &const_p, slen_full); | ||
2574 | if (sess == NULL) | ||
2575 | goto err; | ||
2576 | |||
2577 | /* ID is irrelevant for the ticket */ | ||
2578 | sess->session_id_length = 0; | ||
2579 | |||
2580 | slen = i2d_SSL_SESSION(sess, NULL); | ||
2581 | if (slen > slen_full) { | ||
2582 | /* shouldn't ever happen */ | ||
2583 | goto err; | ||
2584 | } | ||
2585 | p = senc; | ||
2586 | i2d_SSL_SESSION(sess, &p); | ||
2587 | SSL_SESSION_free(sess); | ||
2588 | |||
2589 | /* | ||
2590 | * Initialize HMAC and cipher contexts. If callback present | ||
2591 | * it does all the work otherwise use generated values | ||
2592 | * from parent ctx. | ||
2593 | */ | ||
2594 | if (tctx->internal->tlsext_ticket_key_cb) { | ||
2595 | if (tctx->internal->tlsext_ticket_key_cb(s, | 2566 | if (tctx->internal->tlsext_ticket_key_cb(s, |
2596 | key_name, iv, &ctx, &hctx, 1) < 0) { | 2567 | key_name, iv, &ctx, &hctx, 1) < 0) { |
2597 | EVP_CIPHER_CTX_cleanup(&ctx); | 2568 | EVP_CIPHER_CTX_cleanup(&ctx); |
@@ -2606,19 +2577,21 @@ ssl3_send_newsession_ticket(SSL *s) | |||
2606 | memcpy(key_name, tctx->internal->tlsext_tick_key_name, 16); | 2577 | memcpy(key_name, tctx->internal->tlsext_tick_key_name, 16); |
2607 | } | 2578 | } |
2608 | 2579 | ||
2609 | /* Encrypt the session ticket. */ | 2580 | /* Encrypt the session state. */ |
2610 | if ((enc_ticket = calloc(1, slen + EVP_MAX_BLOCK_LENGTH)) == NULL) | 2581 | enc_session_max_len = session_len + EVP_MAX_BLOCK_LENGTH; |
2582 | if ((enc_session = calloc(1, enc_session_max_len)) == NULL) | ||
2611 | goto err; | 2583 | goto err; |
2612 | enc_ticket_len = 0; | 2584 | enc_session_len = 0; |
2613 | if (!EVP_EncryptUpdate(&ctx, enc_ticket, &len, senc, slen)) | 2585 | if (!EVP_EncryptUpdate(&ctx, enc_session, &len, session, |
2586 | session_len)) | ||
2614 | goto err; | 2587 | goto err; |
2615 | enc_ticket_len += len; | 2588 | enc_session_len += len; |
2616 | if (!EVP_EncryptFinal_ex(&ctx, enc_ticket + enc_ticket_len, &len)) | 2589 | if (!EVP_EncryptFinal_ex(&ctx, enc_session + enc_session_len, |
2590 | &len)) | ||
2617 | goto err; | 2591 | goto err; |
2618 | enc_ticket_len += len; | 2592 | enc_session_len += len; |
2619 | 2593 | ||
2620 | if (enc_ticket_len < 0 || | 2594 | if (enc_session_len > enc_session_max_len) |
2621 | enc_ticket_len > slen + EVP_MAX_BLOCK_LENGTH) | ||
2622 | goto err; | 2595 | goto err; |
2623 | 2596 | ||
2624 | /* Generate the HMAC. */ | 2597 | /* Generate the HMAC. */ |
@@ -2626,7 +2599,7 @@ ssl3_send_newsession_ticket(SSL *s) | |||
2626 | goto err; | 2599 | goto err; |
2627 | if (!HMAC_Update(&hctx, iv, EVP_CIPHER_CTX_iv_length(&ctx))) | 2600 | if (!HMAC_Update(&hctx, iv, EVP_CIPHER_CTX_iv_length(&ctx))) |
2628 | goto err; | 2601 | goto err; |
2629 | if (!HMAC_Update(&hctx, enc_ticket, enc_ticket_len)) | 2602 | if (!HMAC_Update(&hctx, enc_session, enc_session_len)) |
2630 | goto err; | 2603 | goto err; |
2631 | 2604 | ||
2632 | if ((hmac_len = HMAC_size(&hctx)) <= 0) | 2605 | if ((hmac_len = HMAC_size(&hctx)) <= 0) |
@@ -2648,13 +2621,15 @@ ssl3_send_newsession_ticket(SSL *s) | |||
2648 | goto err; | 2621 | goto err; |
2649 | if (!CBB_add_bytes(&ticket, iv, EVP_CIPHER_CTX_iv_length(&ctx))) | 2622 | if (!CBB_add_bytes(&ticket, iv, EVP_CIPHER_CTX_iv_length(&ctx))) |
2650 | goto err; | 2623 | goto err; |
2651 | if (!CBB_add_bytes(&ticket, enc_ticket, enc_ticket_len)) | 2624 | if (!CBB_add_bytes(&ticket, enc_session, enc_session_len)) |
2652 | goto err; | 2625 | goto err; |
2653 | if (!CBB_add_space(&ticket, &hmac, hmac_len)) | 2626 | if (!CBB_add_space(&ticket, &hmac, hmac_len)) |
2654 | goto err; | 2627 | goto err; |
2655 | 2628 | ||
2656 | if (!HMAC_Final(&hctx, hmac, &hlen)) | 2629 | if (!HMAC_Final(&hctx, hmac, &hlen)) |
2657 | goto err; | 2630 | goto err; |
2631 | if (hlen != hmac_len) | ||
2632 | goto err; | ||
2658 | 2633 | ||
2659 | if (!ssl3_handshake_msg_finish(s, &cbb)) | 2634 | if (!ssl3_handshake_msg_finish(s, &cbb)) |
2660 | goto err; | 2635 | goto err; |
@@ -2664,8 +2639,8 @@ ssl3_send_newsession_ticket(SSL *s) | |||
2664 | 2639 | ||
2665 | EVP_CIPHER_CTX_cleanup(&ctx); | 2640 | EVP_CIPHER_CTX_cleanup(&ctx); |
2666 | HMAC_CTX_cleanup(&hctx); | 2641 | HMAC_CTX_cleanup(&hctx); |
2667 | freezero(senc, slen_full); | 2642 | freezero(session, session_len); |
2668 | free(enc_ticket); | 2643 | free(enc_session); |
2669 | 2644 | ||
2670 | /* SSL3_ST_SW_SESSION_TICKET_B */ | 2645 | /* SSL3_ST_SW_SESSION_TICKET_B */ |
2671 | return (ssl3_handshake_write(s)); | 2646 | return (ssl3_handshake_write(s)); |
@@ -2674,8 +2649,8 @@ ssl3_send_newsession_ticket(SSL *s) | |||
2674 | CBB_cleanup(&cbb); | 2649 | CBB_cleanup(&cbb); |
2675 | EVP_CIPHER_CTX_cleanup(&ctx); | 2650 | EVP_CIPHER_CTX_cleanup(&ctx); |
2676 | HMAC_CTX_cleanup(&hctx); | 2651 | HMAC_CTX_cleanup(&hctx); |
2677 | freezero(senc, slen_full); | 2652 | freezero(session, session_len); |
2678 | free(enc_ticket); | 2653 | free(enc_session); |
2679 | 2654 | ||
2680 | return (-1); | 2655 | return (-1); |
2681 | } | 2656 | } |