diff options
author | jsing <> | 2019-04-21 10:17:25 +0000 |
---|---|---|
committer | jsing <> | 2019-04-21 10:17:25 +0000 |
commit | 97b79555a90206c77bc3b25c9722207b0496b2e1 (patch) | |
tree | e6a02574dc8eebc391b57c7012b1a63b1f4a4d8d | |
parent | 3b6754802f797dc8df0764966cad58c88924eb7a (diff) | |
download | openbsd-97b79555a90206c77bc3b25c9722207b0496b2e1.tar.gz openbsd-97b79555a90206c77bc3b25c9722207b0496b2e1.tar.bz2 openbsd-97b79555a90206c77bc3b25c9722207b0496b2e1.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@
-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 | } |