diff options
author | jsing <> | 2017-01-26 12:28:00 +0000 |
---|---|---|
committer | jsing <> | 2017-01-26 12:28:00 +0000 |
commit | 777045738b3a89cbe3ccc2e2323fff80b2188cf4 (patch) | |
tree | eec21d9939bafb73996cdd2c83332c32f0727630 | |
parent | 5ae189b08474853c519a12e66db1c17cfc3c9c8f (diff) | |
download | openbsd-777045738b3a89cbe3ccc2e2323fff80b2188cf4.tar.gz openbsd-777045738b3a89cbe3ccc2e2323fff80b2188cf4.tar.bz2 openbsd-777045738b3a89cbe3ccc2e2323fff80b2188cf4.zip |
Convert ssl3_get_client_hello() to CBS.
ok beck@
-rw-r--r-- | src/lib/libssl/ssl_srvr.c | 147 |
1 files changed, 71 insertions, 76 deletions
diff --git a/src/lib/libssl/ssl_srvr.c b/src/lib/libssl/ssl_srvr.c index 0b110d6a72..217ecafeec 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.4 2017/01/26 12:16:13 beck Exp $ */ | 1 | /* $OpenBSD: ssl_srvr.c,v 1.5 2017/01/26 12:28:00 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 | * |
@@ -719,8 +719,12 @@ ssl3_send_hello_request(SSL *s) | |||
719 | int | 719 | int |
720 | ssl3_get_client_hello(SSL *s) | 720 | ssl3_get_client_hello(SSL *s) |
721 | { | 721 | { |
722 | CBS cbs, client_random, session_id, cookie, cipher_suites; | ||
723 | CBS compression_methods; | ||
724 | uint16_t client_version; | ||
725 | uint8_t comp_method; | ||
726 | int comp_null; | ||
722 | int i, j, ok, al, ret = -1; | 727 | int i, j, ok, al, ret = -1; |
723 | unsigned int cookie_len; | ||
724 | long n; | 728 | long n; |
725 | unsigned long id; | 729 | unsigned long id; |
726 | unsigned char *p, *d; | 730 | unsigned char *p, *d; |
@@ -729,6 +733,7 @@ ssl3_get_client_hello(SSL *s) | |||
729 | unsigned long alg_k; | 733 | unsigned long alg_k; |
730 | const SSL_METHOD *method; | 734 | const SSL_METHOD *method; |
731 | uint16_t shared_version; | 735 | uint16_t shared_version; |
736 | unsigned char *end; | ||
732 | 737 | ||
733 | /* | 738 | /* |
734 | * We do this so that we will respond with our native type. | 739 | * We do this so that we will respond with our native type. |
@@ -745,23 +750,26 @@ ssl3_get_client_hello(SSL *s) | |||
745 | n = s->method->internal->ssl_get_message(s, SSL3_ST_SR_CLNT_HELLO_B, | 750 | n = s->method->internal->ssl_get_message(s, SSL3_ST_SR_CLNT_HELLO_B, |
746 | SSL3_ST_SR_CLNT_HELLO_C, SSL3_MT_CLIENT_HELLO, | 751 | SSL3_ST_SR_CLNT_HELLO_C, SSL3_MT_CLIENT_HELLO, |
747 | SSL3_RT_MAX_PLAIN_LENGTH, &ok); | 752 | SSL3_RT_MAX_PLAIN_LENGTH, &ok); |
748 | |||
749 | if (!ok) | 753 | if (!ok) |
750 | return ((int)n); | 754 | return ((int)n); |
751 | s->internal->first_packet = 0; | 755 | s->internal->first_packet = 0; |
752 | 756 | ||
757 | if (n < 0) | ||
758 | goto err; | ||
759 | |||
753 | d = p = (unsigned char *)s->internal->init_msg; | 760 | d = p = (unsigned char *)s->internal->init_msg; |
761 | end = d + n; | ||
762 | |||
763 | CBS_init(&cbs, s->internal->init_msg, n); | ||
754 | 764 | ||
755 | if (2 > n) | ||
756 | goto truncated; | ||
757 | /* | 765 | /* |
758 | * Use version from inside client hello, not from record header. | 766 | * Use version from inside client hello, not from record header. |
759 | * (may differ: see RFC 2246, Appendix E, second paragraph) | 767 | * (may differ: see RFC 2246, Appendix E, second paragraph) |
760 | */ | 768 | */ |
761 | s->client_version = (((int)p[0]) << 8)|(int)p[1]; | 769 | if (!CBS_get_u16(&cbs, &client_version)) |
762 | p += 2; | 770 | goto truncated; |
763 | 771 | ||
764 | if (ssl_max_shared_version(s, s->client_version, &shared_version) != 1) { | 772 | if (ssl_max_shared_version(s, client_version, &shared_version) != 1) { |
765 | SSLerror(SSL_R_WRONG_VERSION_NUMBER); | 773 | SSLerror(SSL_R_WRONG_VERSION_NUMBER); |
766 | if ((s->client_version >> 8) == SSL3_VERSION_MAJOR && | 774 | if ((s->client_version >> 8) == SSL3_VERSION_MAJOR && |
767 | !s->internal->enc_write_ctx && !s->internal->write_hash) { | 775 | !s->internal->enc_write_ctx && !s->internal->write_hash) { |
@@ -774,6 +782,7 @@ ssl3_get_client_hello(SSL *s) | |||
774 | al = SSL_AD_PROTOCOL_VERSION; | 782 | al = SSL_AD_PROTOCOL_VERSION; |
775 | goto f_err; | 783 | goto f_err; |
776 | } | 784 | } |
785 | s->client_version = client_version; | ||
777 | s->version = shared_version; | 786 | s->version = shared_version; |
778 | 787 | ||
779 | if ((method = tls1_get_server_method(shared_version)) == NULL) | 788 | if ((method = tls1_get_server_method(shared_version)) == NULL) |
@@ -784,39 +793,31 @@ ssl3_get_client_hello(SSL *s) | |||
784 | } | 793 | } |
785 | s->method = method; | 794 | s->method = method; |
786 | 795 | ||
796 | if (!CBS_get_bytes(&cbs, &client_random, SSL3_RANDOM_SIZE)) | ||
797 | goto truncated; | ||
798 | if (!CBS_get_u8_length_prefixed(&cbs, &session_id)) | ||
799 | goto truncated; | ||
800 | |||
787 | /* | 801 | /* |
788 | * If we require cookies (DTLS) and this ClientHello doesn't | 802 | * If we require cookies (DTLS) and this ClientHello doesn't |
789 | * contain one, just return since we do not want to | 803 | * contain one, just return since we do not want to |
790 | * allocate any memory yet. So check cookie length... | 804 | * allocate any memory yet. So check cookie length... |
791 | */ | 805 | */ |
792 | if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) { | 806 | if (SSL_IS_DTLS(s)) { |
793 | unsigned int session_length, cookie_length; | 807 | if (!CBS_get_u8_length_prefixed(&cbs, &cookie)) |
794 | |||
795 | if (p - d + SSL3_RANDOM_SIZE + 1 >= n) | ||
796 | goto truncated; | ||
797 | session_length = *(p + SSL3_RANDOM_SIZE); | ||
798 | |||
799 | if (p - d + SSL3_RANDOM_SIZE + session_length + 1 >= n) | ||
800 | goto truncated; | 808 | goto truncated; |
801 | cookie_length = p[SSL3_RANDOM_SIZE + session_length + 1]; | 809 | if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) { |
802 | 810 | if (CBS_len(&cookie) == 0) | |
803 | if (cookie_length == 0) | 811 | return (1); |
804 | return (1); | 812 | } |
805 | } | 813 | } |
806 | 814 | ||
807 | if (p - d + SSL3_RANDOM_SIZE + 1 > n) | 815 | if (!CBS_write_bytes(&client_random, s->s3->client_random, |
808 | goto truncated; | 816 | sizeof(s->s3->client_random), NULL)) |
809 | 817 | goto err; | |
810 | /* load the client random */ | ||
811 | memcpy(s->s3->client_random, p, SSL3_RANDOM_SIZE); | ||
812 | p += SSL3_RANDOM_SIZE; | ||
813 | |||
814 | /* get the session-id */ | ||
815 | j= *(p++); | ||
816 | if (p - d + j > n) | ||
817 | goto truncated; | ||
818 | 818 | ||
819 | s->internal->hit = 0; | 819 | s->internal->hit = 0; |
820 | |||
820 | /* | 821 | /* |
821 | * Versions before 0.9.7 always allow clients to resume sessions in | 822 | * Versions before 0.9.7 always allow clients to resume sessions in |
822 | * renegotiation. 0.9.7 and later allow this by default, but optionally | 823 | * renegotiation. 0.9.7 and later allow this by default, but optionally |
@@ -837,7 +838,10 @@ ssl3_get_client_hello(SSL *s) | |||
837 | if (!ssl_get_new_session(s, 1)) | 838 | if (!ssl_get_new_session(s, 1)) |
838 | goto err; | 839 | goto err; |
839 | } else { | 840 | } else { |
840 | i = ssl_get_prev_session(s, p, j, d + n); | 841 | /* XXX - pass CBS through instead... */ |
842 | i = ssl_get_prev_session(s, | ||
843 | (unsigned char *)CBS_data(&session_id), | ||
844 | CBS_len(&session_id), end); | ||
841 | if (i == 1) { /* previous session */ | 845 | if (i == 1) { /* previous session */ |
842 | s->internal->hit = 1; | 846 | s->internal->hit = 1; |
843 | } else if (i == -1) | 847 | } else if (i == -1) |
@@ -849,33 +853,27 @@ ssl3_get_client_hello(SSL *s) | |||
849 | } | 853 | } |
850 | } | 854 | } |
851 | 855 | ||
852 | p += j; | ||
853 | |||
854 | if (SSL_IS_DTLS(s)) { | 856 | if (SSL_IS_DTLS(s)) { |
855 | /* cookie stuff */ | ||
856 | if (p - d + 1 > n) | ||
857 | goto truncated; | ||
858 | cookie_len = *(p++); | ||
859 | |||
860 | /* | 857 | /* |
861 | * The ClientHello may contain a cookie even if the | 858 | * The ClientHello may contain a cookie even if the HelloVerify |
862 | * HelloVerify message has not been sent--make sure that it | 859 | * message has not been sent - make sure that it does not cause |
863 | * does not cause an overflow. | 860 | * an overflow. |
864 | */ | 861 | */ |
865 | if (cookie_len > sizeof(D1I(s)->rcvd_cookie)) { | 862 | if (CBS_len(&cookie) > sizeof(D1I(s)->rcvd_cookie)) { |
866 | /* too much data */ | ||
867 | al = SSL_AD_DECODE_ERROR; | 863 | al = SSL_AD_DECODE_ERROR; |
868 | SSLerror(SSL_R_COOKIE_MISMATCH); | 864 | SSLerror(SSL_R_COOKIE_MISMATCH); |
869 | goto f_err; | 865 | goto f_err; |
870 | } | 866 | } |
871 | 867 | ||
872 | if (p - d + cookie_len > n) | 868 | /* Verify the cookie if appropriate option is set. */ |
873 | goto truncated; | ||
874 | |||
875 | /* verify the cookie if appropriate option is set. */ | ||
876 | if ((SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) && | 869 | if ((SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) && |
877 | cookie_len > 0) { | 870 | CBS_len(&cookie) > 0) { |
878 | memcpy(D1I(s)->rcvd_cookie, p, cookie_len); | 871 | size_t cookie_len; |
872 | |||
873 | /* XXX - rcvd_cookie seems to only be used here... */ | ||
874 | if (!CBS_write_bytes(&cookie, D1I(s)->rcvd_cookie, | ||
875 | sizeof(D1I(s)->rcvd_cookie), &cookie_len)) | ||
876 | goto err; | ||
879 | 877 | ||
880 | if (s->ctx->internal->app_verify_cookie_cb != NULL) { | 878 | if (s->ctx->internal->app_verify_cookie_cb != NULL) { |
881 | if (s->ctx->internal->app_verify_cookie_cb(s, | 879 | if (s->ctx->internal->app_verify_cookie_cb(s, |
@@ -885,39 +883,37 @@ ssl3_get_client_hello(SSL *s) | |||
885 | goto f_err; | 883 | goto f_err; |
886 | } | 884 | } |
887 | /* else cookie verification succeeded */ | 885 | /* else cookie verification succeeded */ |
888 | } else if (timingsafe_memcmp(D1I(s)->rcvd_cookie, D1I(s)->cookie, | 886 | /* XXX - can d1->cookie_len > sizeof(rcvd_cookie) ? */ |
889 | D1I(s)->cookie_len) != 0) { | 887 | } else if (timingsafe_memcmp(D1I(s)->rcvd_cookie, |
888 | D1I(s)->cookie, D1I(s)->cookie_len) != 0) { | ||
890 | /* default verification */ | 889 | /* default verification */ |
891 | al = SSL_AD_HANDSHAKE_FAILURE; | 890 | al = SSL_AD_HANDSHAKE_FAILURE; |
892 | SSLerror(SSL_R_COOKIE_MISMATCH); | 891 | SSLerror(SSL_R_COOKIE_MISMATCH); |
893 | goto f_err; | 892 | goto f_err; |
894 | } | 893 | } |
895 | |||
896 | ret = 2; | 894 | ret = 2; |
897 | } | 895 | } |
898 | |||
899 | p += cookie_len; | ||
900 | } | 896 | } |
901 | 897 | ||
902 | if (p - d + 2 > n) | 898 | if (!CBS_get_u16_length_prefixed(&cbs, &cipher_suites)) |
903 | goto truncated; | 899 | goto truncated; |
904 | n2s(p, i); | 900 | |
905 | if ((i == 0) && (j != 0)) { | 901 | /* XXX - This logic seems wrong... */ |
902 | if (CBS_len(&cipher_suites) == 0 && CBS_len(&session_id) != 0) { | ||
906 | /* we need a cipher if we are not resuming a session */ | 903 | /* we need a cipher if we are not resuming a session */ |
907 | al = SSL_AD_ILLEGAL_PARAMETER; | 904 | al = SSL_AD_ILLEGAL_PARAMETER; |
908 | SSLerror(SSL_R_NO_CIPHERS_SPECIFIED); | 905 | SSLerror(SSL_R_NO_CIPHERS_SPECIFIED); |
909 | goto f_err; | 906 | goto f_err; |
910 | } | 907 | } |
911 | if (p - d + i > n) | 908 | |
912 | goto truncated; | 909 | if (CBS_len(&cipher_suites) > 0) { |
913 | if (i > 0) { | 910 | if ((ciphers = ssl_bytes_to_cipher_list(s, |
914 | if ((ciphers = ssl_bytes_to_cipher_list(s, p, i)) == NULL) | 911 | CBS_data(&cipher_suites), CBS_len(&cipher_suites))) == NULL) |
915 | goto err; | 912 | goto err; |
916 | } | 913 | } |
917 | p += i; | ||
918 | 914 | ||
919 | /* If it is a hit, check that the cipher is in the list */ | 915 | /* If it is a hit, check that the cipher is in the list */ |
920 | if ((s->internal->hit) && (i > 0)) { | 916 | if (s->internal->hit && CBS_len(&cipher_suites) > 0) { |
921 | j = 0; | 917 | j = 0; |
922 | id = s->session->cipher->id; | 918 | id = s->session->cipher->id; |
923 | 919 | ||
@@ -939,25 +935,24 @@ ssl3_get_client_hello(SSL *s) | |||
939 | } | 935 | } |
940 | } | 936 | } |
941 | 937 | ||
942 | /* compression */ | 938 | if (!CBS_get_u8_length_prefixed(&cbs, &compression_methods)) |
943 | if (p - d + 1 > n) | ||
944 | goto truncated; | ||
945 | i= *(p++); | ||
946 | if (p - d + i > n) | ||
947 | goto truncated; | 939 | goto truncated; |
948 | for (j = 0; j < i; j++) { | ||
949 | if (p[j] == 0) | ||
950 | break; | ||
951 | } | ||
952 | 940 | ||
953 | p += i; | 941 | comp_null = 0; |
954 | if (j >= i) { | 942 | while (CBS_len(&compression_methods) > 0) { |
955 | /* no compress */ | 943 | if (!CBS_get_u8(&compression_methods, &comp_method)) |
944 | goto truncated; | ||
945 | if (comp_method == 0) | ||
946 | comp_null = 1; | ||
947 | } | ||
948 | if (comp_null == 0) { | ||
956 | al = SSL_AD_DECODE_ERROR; | 949 | al = SSL_AD_DECODE_ERROR; |
957 | SSLerror(SSL_R_NO_COMPRESSION_SPECIFIED); | 950 | SSLerror(SSL_R_NO_COMPRESSION_SPECIFIED); |
958 | goto f_err; | 951 | goto f_err; |
959 | } | 952 | } |
960 | 953 | ||
954 | p = (unsigned char *)CBS_data(&cbs); | ||
955 | |||
961 | /* TLS extensions*/ | 956 | /* TLS extensions*/ |
962 | if (!ssl_parse_clienthello_tlsext(s, &p, d, n, &al)) { | 957 | if (!ssl_parse_clienthello_tlsext(s, &p, d, n, &al)) { |
963 | /* 'al' set by ssl_parse_clienthello_tlsext */ | 958 | /* 'al' set by ssl_parse_clienthello_tlsext */ |