diff options
| author | jsing <> | 2018-08-27 16:42:48 +0000 |
|---|---|---|
| committer | jsing <> | 2018-08-27 16:42:48 +0000 |
| commit | 3214e561f5d16cffff1ac02e8f9fcf7cd78bafc8 (patch) | |
| tree | 71671a4717389a51b5152df1689cea13e657f8ca /src | |
| parent | 26a03876b975111cf08bf5fdfe07c4c8c404abaa (diff) | |
| download | openbsd-3214e561f5d16cffff1ac02e8f9fcf7cd78bafc8.tar.gz openbsd-3214e561f5d16cffff1ac02e8f9fcf7cd78bafc8.tar.bz2 openbsd-3214e561f5d16cffff1ac02e8f9fcf7cd78bafc8.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@
Diffstat (limited to 'src')
| -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 | } |
