diff options
| author | jsing <> | 2019-04-21 10:17:25 +0000 |
|---|---|---|
| committer | jsing <> | 2019-04-21 10:17:25 +0000 |
| commit | ff92701144072b1cbeb06a78e6615046efcafebd (patch) | |
| tree | e6a02574dc8eebc391b57c7012b1a63b1f4a4d8d /src/lib/libssl/t1_lib.c | |
| parent | e04015d3abb900af2ccd8c74ee188640c9be43bc (diff) | |
| download | openbsd-ff92701144072b1cbeb06a78e6615046efcafebd.tar.gz openbsd-ff92701144072b1cbeb06a78e6615046efcafebd.tar.bz2 openbsd-ff92701144072b1cbeb06a78e6615046efcafebd.zip | |
Start cleaning up tls_decrypt_ticket().
Rather than returning from multiple places and trying to clean up as we go,
move to a single exit point and clean/free in one place. Also invert the
logic that handles NULL sessions - fail early, rather than having an
indented if test for success.
ok tb@
Diffstat (limited to 'src/lib/libssl/t1_lib.c')
| -rw-r--r-- | src/lib/libssl/t1_lib.c | 121 |
1 files changed, 63 insertions, 58 deletions
diff --git a/src/lib/libssl/t1_lib.c b/src/lib/libssl/t1_lib.c index 5dbbdb7866..2147908819 100644 --- a/src/lib/libssl/t1_lib.c +++ b/src/lib/libssl/t1_lib.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: t1_lib.c,v 1.154 2019/03/25 17:27:31 jsing Exp $ */ | 1 | /* $OpenBSD: t1_lib.c,v 1.155 2019/04/21 10:17:25 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 | * |
| @@ -877,13 +877,17 @@ tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen, | |||
| 877 | const unsigned char *sess_id, int sesslen, SSL_SESSION **psess) | 877 | const unsigned char *sess_id, int sesslen, SSL_SESSION **psess) |
| 878 | { | 878 | { |
| 879 | SSL_SESSION *sess; | 879 | SSL_SESSION *sess; |
| 880 | unsigned char *sdec; | 880 | unsigned char *sdec = NULL; |
| 881 | const unsigned char *p; | 881 | const unsigned char *p; |
| 882 | int slen, mlen, renew_ticket = 0; | 882 | int slen, mlen, renew_ticket = 0; |
| 883 | unsigned char tick_hmac[EVP_MAX_MD_SIZE]; | 883 | unsigned char tick_hmac[EVP_MAX_MD_SIZE]; |
| 884 | HMAC_CTX hctx; | 884 | HMAC_CTX hctx; |
| 885 | EVP_CIPHER_CTX ctx; | 885 | EVP_CIPHER_CTX ctx; |
| 886 | SSL_CTX *tctx = s->initial_ctx; | 886 | SSL_CTX *tctx = s->initial_ctx; |
| 887 | int ret = -1; | ||
| 888 | |||
| 889 | HMAC_CTX_init(&hctx); | ||
| 890 | EVP_CIPHER_CTX_init(&ctx); | ||
| 887 | 891 | ||
| 888 | /* | 892 | /* |
| 889 | * The API guarantees EVP_MAX_IV_LENGTH bytes of space for | 893 | * The API guarantees EVP_MAX_IV_LENGTH bytes of space for |
| @@ -891,33 +895,31 @@ tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen, | |||
| 891 | * required for a session cookie is never less than this, | 895 | * required for a session cookie is never less than this, |
| 892 | * this check isn't too strict. The exact check comes later. | 896 | * this check isn't too strict. The exact check comes later. |
| 893 | */ | 897 | */ |
| 894 | if (eticklen < 16 + EVP_MAX_IV_LENGTH) | 898 | if (eticklen < 16 + EVP_MAX_IV_LENGTH) { |
| 895 | return 2; | 899 | ret = 2; |
| 900 | goto done; | ||
| 901 | } | ||
| 896 | 902 | ||
| 897 | /* Initialize session ticket encryption and HMAC contexts */ | 903 | /* Initialize session ticket encryption and HMAC contexts */ |
| 898 | HMAC_CTX_init(&hctx); | ||
| 899 | EVP_CIPHER_CTX_init(&ctx); | ||
| 900 | if (tctx->internal->tlsext_ticket_key_cb) { | 904 | if (tctx->internal->tlsext_ticket_key_cb) { |
| 901 | unsigned char *nctick = (unsigned char *)etick; | 905 | unsigned char *nctick = (unsigned char *)etick; |
| 902 | int rv = tctx->internal->tlsext_ticket_key_cb(s, | 906 | int rv = tctx->internal->tlsext_ticket_key_cb(s, |
| 903 | nctick, nctick + 16, &ctx, &hctx, 0); | 907 | nctick, nctick + 16, &ctx, &hctx, 0); |
| 904 | if (rv < 0) { | 908 | if (rv < 0) |
| 905 | HMAC_CTX_cleanup(&hctx); | 909 | goto err; |
| 906 | EVP_CIPHER_CTX_cleanup(&ctx); | ||
| 907 | return -1; | ||
| 908 | } | ||
| 909 | if (rv == 0) { | 910 | if (rv == 0) { |
| 910 | HMAC_CTX_cleanup(&hctx); | 911 | ret = 2; |
| 911 | EVP_CIPHER_CTX_cleanup(&ctx); | 912 | goto done; |
| 912 | return 2; | ||
| 913 | } | 913 | } |
| 914 | if (rv == 2) | 914 | if (rv == 2) |
| 915 | renew_ticket = 1; | 915 | renew_ticket = 1; |
| 916 | } else { | 916 | } else { |
| 917 | /* Check key name matches */ | 917 | /* Check key name matches */ |
| 918 | if (timingsafe_memcmp(etick, | 918 | if (timingsafe_memcmp(etick, |
| 919 | tctx->internal->tlsext_tick_key_name, 16)) | 919 | tctx->internal->tlsext_tick_key_name, 16)) { |
| 920 | return 2; | 920 | ret = 2; |
| 921 | goto done; | ||
| 922 | } | ||
| 921 | HMAC_Init_ex(&hctx, tctx->internal->tlsext_tick_hmac_key, | 923 | HMAC_Init_ex(&hctx, tctx->internal->tlsext_tick_hmac_key, |
| 922 | 16, tlsext_tick_md(), NULL); | 924 | 16, tlsext_tick_md(), NULL); |
| 923 | EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, | 925 | EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, |
| @@ -929,32 +931,24 @@ tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen, | |||
| 929 | * integrity checks on ticket. | 931 | * integrity checks on ticket. |
| 930 | */ | 932 | */ |
| 931 | mlen = HMAC_size(&hctx); | 933 | mlen = HMAC_size(&hctx); |
| 932 | if (mlen < 0) { | 934 | if (mlen < 0) |
| 933 | HMAC_CTX_cleanup(&hctx); | 935 | goto err; |
| 934 | EVP_CIPHER_CTX_cleanup(&ctx); | ||
| 935 | return -1; | ||
| 936 | } | ||
| 937 | 936 | ||
| 938 | /* Sanity check ticket length: must exceed keyname + IV + HMAC */ | 937 | /* Sanity check ticket length: must exceed keyname + IV + HMAC */ |
| 939 | if (eticklen <= 16 + EVP_CIPHER_CTX_iv_length(&ctx) + mlen) { | 938 | if (eticklen <= 16 + EVP_CIPHER_CTX_iv_length(&ctx) + mlen) { |
| 940 | HMAC_CTX_cleanup(&hctx); | 939 | ret = 2; |
| 941 | EVP_CIPHER_CTX_cleanup(&ctx); | 940 | goto done; |
| 942 | return 2; | ||
| 943 | } | 941 | } |
| 944 | eticklen -= mlen; | 942 | eticklen -= mlen; |
| 945 | 943 | ||
| 946 | /* Check HMAC of encrypted ticket */ | 944 | /* Check HMAC of encrypted ticket */ |
| 947 | if (HMAC_Update(&hctx, etick, eticklen) <= 0 || | 945 | if (HMAC_Update(&hctx, etick, eticklen) <= 0 || |
| 948 | HMAC_Final(&hctx, tick_hmac, NULL) <= 0) { | 946 | HMAC_Final(&hctx, tick_hmac, NULL) <= 0) |
| 949 | HMAC_CTX_cleanup(&hctx); | 947 | goto err; |
| 950 | EVP_CIPHER_CTX_cleanup(&ctx); | ||
| 951 | return -1; | ||
| 952 | } | ||
| 953 | 948 | ||
| 954 | HMAC_CTX_cleanup(&hctx); | ||
| 955 | if (timingsafe_memcmp(tick_hmac, etick + eticklen, mlen)) { | 949 | if (timingsafe_memcmp(tick_hmac, etick + eticklen, mlen)) { |
| 956 | EVP_CIPHER_CTX_cleanup(&ctx); | 950 | ret = 2; |
| 957 | return 2; | 951 | goto done; |
| 958 | } | 952 | } |
| 959 | 953 | ||
| 960 | /* Attempt to decrypt session data */ | 954 | /* Attempt to decrypt session data */ |
| @@ -964,38 +958,49 @@ tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen, | |||
| 964 | sdec = malloc(eticklen); | 958 | sdec = malloc(eticklen); |
| 965 | if (sdec == NULL || | 959 | if (sdec == NULL || |
| 966 | EVP_DecryptUpdate(&ctx, sdec, &slen, p, eticklen) <= 0) { | 960 | EVP_DecryptUpdate(&ctx, sdec, &slen, p, eticklen) <= 0) { |
| 967 | free(sdec); | 961 | ret = -1; |
| 968 | EVP_CIPHER_CTX_cleanup(&ctx); | 962 | goto done; |
| 969 | return -1; | ||
| 970 | } | 963 | } |
| 971 | if (EVP_DecryptFinal_ex(&ctx, sdec + slen, &mlen) <= 0) { | 964 | if (EVP_DecryptFinal_ex(&ctx, sdec + slen, &mlen) <= 0) { |
| 972 | free(sdec); | 965 | ret = 2; |
| 973 | EVP_CIPHER_CTX_cleanup(&ctx); | 966 | goto done; |
| 974 | return 2; | ||
| 975 | } | 967 | } |
| 976 | slen += mlen; | 968 | slen += mlen; |
| 977 | EVP_CIPHER_CTX_cleanup(&ctx); | ||
| 978 | p = sdec; | 969 | p = sdec; |
| 979 | 970 | ||
| 980 | sess = d2i_SSL_SESSION(NULL, &p, slen); | 971 | if ((sess = d2i_SSL_SESSION(NULL, &p, slen)) == NULL) { |
| 981 | free(sdec); | 972 | /* |
| 982 | if (sess) { | 973 | * For session parse failure, indicate that we need to send a |
| 983 | /* The session ID, if non-empty, is used by some clients to | 974 | * new ticket. |
| 984 | * detect that the ticket has been accepted. So we copy it to | ||
| 985 | * the session structure. If it is empty set length to zero | ||
| 986 | * as required by standard. | ||
| 987 | */ | 975 | */ |
| 988 | if (sesslen) | 976 | ERR_clear_error(); |
| 989 | memcpy(sess->session_id, sess_id, sesslen); | 977 | ret = 2; |
| 990 | sess->session_id_length = sesslen; | 978 | goto done; |
| 991 | *psess = sess; | ||
| 992 | if (renew_ticket) | ||
| 993 | return 4; | ||
| 994 | else | ||
| 995 | return 3; | ||
| 996 | } | 979 | } |
| 997 | ERR_clear_error(); | 980 | |
| 998 | /* For session parse failure, indicate that we need to send a new | 981 | /* |
| 999 | * ticket. */ | 982 | * The session ID, if non-empty, is used by some clients to detect that |
| 1000 | return 2; | 983 | * the ticket has been accepted. So we copy it to the session structure. |
| 984 | * If it is empty set length to zero as required by standard. | ||
| 985 | */ | ||
| 986 | if (sesslen) | ||
| 987 | memcpy(sess->session_id, sess_id, sesslen); | ||
| 988 | sess->session_id_length = sesslen; | ||
| 989 | *psess = sess; | ||
| 990 | if (renew_ticket) | ||
| 991 | ret = 4; | ||
| 992 | else | ||
| 993 | ret = 3; | ||
| 994 | |||
| 995 | goto done; | ||
| 996 | |||
| 997 | err: | ||
| 998 | ret = -1; | ||
| 999 | |||
| 1000 | done: | ||
| 1001 | free(sdec); | ||
| 1002 | HMAC_CTX_cleanup(&hctx); | ||
| 1003 | EVP_CIPHER_CTX_cleanup(&ctx); | ||
| 1004 | |||
| 1005 | return ret; | ||
| 1001 | } | 1006 | } |
