diff options
Diffstat (limited to '')
| -rw-r--r-- | src/lib/libssl/s3_clnt.c | 678 |
1 files changed, 351 insertions, 327 deletions
diff --git a/src/lib/libssl/s3_clnt.c b/src/lib/libssl/s3_clnt.c index 343b0a8cfe..c2f5ea4e07 100644 --- a/src/lib/libssl/s3_clnt.c +++ b/src/lib/libssl/s3_clnt.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: s3_clnt.c,v 1.132 2015/09/12 20:23:56 jsing Exp $ */ | 1 | /* $OpenBSD: s3_clnt.c,v 1.133 2015/09/12 20:56:14 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 | * |
| @@ -1853,372 +1853,400 @@ ssl3_get_server_done(SSL *s) | |||
| 1853 | return (ret); | 1853 | return (ret); |
| 1854 | } | 1854 | } |
| 1855 | 1855 | ||
| 1856 | int | 1856 | static int |
| 1857 | ssl3_send_client_key_exchange(SSL *s) | 1857 | ssl3_client_kex_rsa(SSL *s, SESS_CERT *sess_cert, unsigned char *p, int *outlen) |
| 1858 | { | 1858 | { |
| 1859 | unsigned char *p, *q; | 1859 | unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH]; |
| 1860 | int n; | 1860 | EVP_PKEY *pkey = NULL; |
| 1861 | unsigned long alg_k; | 1861 | unsigned char *q; |
| 1862 | EVP_PKEY *pkey = NULL; | 1862 | int ret = -1; |
| 1863 | EC_KEY *clnt_ecdh = NULL; | 1863 | int n; |
| 1864 | const EC_POINT *srvr_ecpoint = NULL; | 1864 | |
| 1865 | EVP_PKEY *srvr_pub_pkey = NULL; | 1865 | pkey = X509_get_pubkey(sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509); |
| 1866 | unsigned char *encodedPoint = NULL; | 1866 | if (pkey == NULL || pkey->type != EVP_PKEY_RSA || |
| 1867 | int encoded_pt_len = 0; | 1867 | pkey->pkey.rsa == NULL) { |
| 1868 | BN_CTX *bn_ctx = NULL; | 1868 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, |
| 1869 | ERR_R_INTERNAL_ERROR); | ||
| 1870 | goto err; | ||
| 1871 | } | ||
| 1869 | 1872 | ||
| 1870 | if (s->state == SSL3_ST_CW_KEY_EXCH_A) { | 1873 | tmp_buf[0] = s->client_version >> 8; |
| 1871 | p = ssl3_handshake_msg_start(s, SSL3_MT_CLIENT_KEY_EXCHANGE); | 1874 | tmp_buf[1] = s->client_version & 0xff; |
| 1875 | arc4random_buf(&tmp_buf[2], sizeof(tmp_buf) - 2); | ||
| 1872 | 1876 | ||
| 1873 | alg_k = s->s3->tmp.new_cipher->algorithm_mkey; | 1877 | s->session->master_key_length = sizeof(tmp_buf); |
| 1874 | 1878 | ||
| 1875 | if (s->session->sess_cert == NULL) { | 1879 | q = p; |
| 1876 | ssl3_send_alert(s, SSL3_AL_FATAL, | 1880 | p += 2; |
| 1877 | SSL_AD_UNEXPECTED_MESSAGE); | ||
| 1878 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, | ||
| 1879 | ERR_R_INTERNAL_ERROR); | ||
| 1880 | goto err; | ||
| 1881 | } | ||
| 1882 | 1881 | ||
| 1883 | if (alg_k & SSL_kRSA) { | 1882 | n = RSA_public_encrypt(sizeof(tmp_buf), tmp_buf, p, pkey->pkey.rsa, |
| 1884 | RSA *rsa; | 1883 | RSA_PKCS1_PADDING); |
| 1885 | unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH]; | 1884 | if (n <= 0) { |
| 1885 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, | ||
| 1886 | SSL_R_BAD_RSA_ENCRYPT); | ||
| 1887 | goto err; | ||
| 1888 | } | ||
| 1886 | 1889 | ||
| 1887 | pkey = X509_get_pubkey( | 1890 | s2n(n, q); |
| 1888 | s->session->sess_cert->peer_pkeys[ | 1891 | n += 2; |
| 1889 | SSL_PKEY_RSA_ENC].x509); | ||
| 1890 | if ((pkey == NULL) || | ||
| 1891 | (pkey->type != EVP_PKEY_RSA) || | ||
| 1892 | (pkey->pkey.rsa == NULL)) { | ||
| 1893 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, | ||
| 1894 | ERR_R_INTERNAL_ERROR); | ||
| 1895 | EVP_PKEY_free(pkey); | ||
| 1896 | goto err; | ||
| 1897 | } | ||
| 1898 | rsa = pkey->pkey.rsa; | ||
| 1899 | EVP_PKEY_free(pkey); | ||
| 1900 | 1892 | ||
| 1901 | tmp_buf[0] = s->client_version >> 8; | 1893 | s->session->master_key_length = |
| 1902 | tmp_buf[1] = s->client_version & 0xff; | 1894 | s->method->ssl3_enc->generate_master_secret(s, |
| 1903 | arc4random_buf(&tmp_buf[2], sizeof(tmp_buf) - 2); | 1895 | s->session->master_key, tmp_buf, sizeof(tmp_buf)); |
| 1904 | 1896 | ||
| 1905 | s->session->master_key_length = sizeof tmp_buf; | 1897 | *outlen = n; |
| 1898 | ret = 1; | ||
| 1906 | 1899 | ||
| 1907 | q = p; | 1900 | err: |
| 1908 | /* Fix buf for TLS and beyond */ | 1901 | explicit_bzero(tmp_buf, sizeof(tmp_buf)); |
| 1909 | p += 2; | 1902 | EVP_PKEY_free(pkey); |
| 1910 | 1903 | ||
| 1911 | n = RSA_public_encrypt(sizeof tmp_buf, | 1904 | return (ret); |
| 1912 | tmp_buf, p, rsa, RSA_PKCS1_PADDING); | 1905 | } |
| 1913 | if (n <= 0) { | ||
| 1914 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, | ||
| 1915 | SSL_R_BAD_RSA_ENCRYPT); | ||
| 1916 | goto err; | ||
| 1917 | } | ||
| 1918 | 1906 | ||
| 1919 | /* Fix buf for TLS and beyond */ | 1907 | static int |
| 1920 | s2n(n, q); | 1908 | ssl3_client_kex_dhe(SSL *s, SESS_CERT *sess_cert, unsigned char *p, int *outlen) |
| 1921 | n += 2; | 1909 | { |
| 1910 | DH *dh_srvr = NULL, *dh_clnt = NULL; | ||
| 1911 | int ret = -1; | ||
| 1912 | int n; | ||
| 1913 | |||
| 1914 | /* Ensure that we have an ephemeral key for DHE. */ | ||
| 1915 | if (sess_cert->peer_dh_tmp == NULL) { | ||
| 1916 | ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); | ||
| 1917 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, | ||
| 1918 | SSL_R_UNABLE_TO_FIND_DH_PARAMETERS); | ||
| 1919 | goto err; | ||
| 1920 | } | ||
| 1921 | dh_srvr = sess_cert->peer_dh_tmp; | ||
| 1922 | 1922 | ||
| 1923 | s->session->master_key_length = | 1923 | /* Generate a new random key. */ |
| 1924 | s->method->ssl3_enc->generate_master_secret( | 1924 | if ((dh_clnt = DHparams_dup(dh_srvr)) == NULL) { |
| 1925 | s, s->session->master_key, tmp_buf, sizeof tmp_buf); | 1925 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_DH_LIB); |
| 1926 | explicit_bzero(tmp_buf, sizeof tmp_buf); | 1926 | goto err; |
| 1927 | } else if (alg_k & SSL_kDHE) { | 1927 | } |
| 1928 | DH *dh_srvr, *dh_clnt; | 1928 | if (!DH_generate_key(dh_clnt)) { |
| 1929 | 1929 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_DH_LIB); | |
| 1930 | /* Ensure that we have an ephemeral key for DHE. */ | 1930 | goto err; |
| 1931 | if (s->session->sess_cert->peer_dh_tmp == NULL) { | 1931 | } |
| 1932 | ssl3_send_alert(s, SSL3_AL_FATAL, | ||
| 1933 | SSL_AD_HANDSHAKE_FAILURE); | ||
| 1934 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, | ||
| 1935 | SSL_R_UNABLE_TO_FIND_DH_PARAMETERS); | ||
| 1936 | goto err; | ||
| 1937 | } | ||
| 1938 | dh_srvr = s->session->sess_cert->peer_dh_tmp; | ||
| 1939 | 1932 | ||
| 1940 | /* Generate a new random key. */ | 1933 | /* |
| 1941 | if ((dh_clnt = DHparams_dup(dh_srvr)) == NULL) { | 1934 | * Use the 'p' output buffer for the DH key, but make sure to clear |
| 1942 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, | 1935 | * it out afterwards. |
| 1943 | ERR_R_DH_LIB); | 1936 | */ |
| 1944 | goto err; | 1937 | n = DH_compute_key(p, dh_srvr->pub_key, dh_clnt); |
| 1945 | } | 1938 | if (n <= 0) { |
| 1946 | if (!DH_generate_key(dh_clnt)) { | 1939 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_DH_LIB); |
| 1947 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, | 1940 | goto err; |
| 1948 | ERR_R_DH_LIB); | 1941 | } |
| 1949 | DH_free(dh_clnt); | ||
| 1950 | goto err; | ||
| 1951 | } | ||
| 1952 | 1942 | ||
| 1953 | /* | 1943 | /* Generate master key from the result. */ |
| 1954 | * Use the 'p' output buffer for the DH key, but | 1944 | s->session->master_key_length = |
| 1955 | * make sure to clear it out afterwards. | 1945 | s->method->ssl3_enc->generate_master_secret(s, |
| 1956 | */ | 1946 | s->session->master_key, p, n); |
| 1957 | n = DH_compute_key(p, dh_srvr->pub_key, dh_clnt); | ||
| 1958 | if (n <= 0) { | ||
| 1959 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, | ||
| 1960 | ERR_R_DH_LIB); | ||
| 1961 | DH_free(dh_clnt); | ||
| 1962 | goto err; | ||
| 1963 | } | ||
| 1964 | 1947 | ||
| 1965 | /* Generate master key from the result. */ | 1948 | /* Clean up. */ |
| 1966 | s->session->master_key_length = | 1949 | explicit_bzero(p, n); |
| 1967 | s->method->ssl3_enc->generate_master_secret(s, | ||
| 1968 | s->session->master_key, p, n); | ||
| 1969 | 1950 | ||
| 1970 | /* Clean up. */ | 1951 | /* Send off the data. */ |
| 1971 | explicit_bzero(p, n); | 1952 | n = BN_num_bytes(dh_clnt->pub_key); |
| 1953 | s2n(n, p); | ||
| 1954 | BN_bn2bin(dh_clnt->pub_key, p); | ||
| 1955 | n += 2; | ||
| 1972 | 1956 | ||
| 1973 | /* Send off the data. */ | 1957 | *outlen = n; |
| 1974 | n = BN_num_bytes(dh_clnt->pub_key); | 1958 | ret = 1; |
| 1975 | s2n(n, p); | ||
| 1976 | BN_bn2bin(dh_clnt->pub_key, p); | ||
| 1977 | n += 2; | ||
| 1978 | 1959 | ||
| 1979 | DH_free(dh_clnt); | 1960 | err: |
| 1961 | DH_free(dh_clnt); | ||
| 1980 | 1962 | ||
| 1981 | /* perhaps clean things up a bit EAY EAY EAY EAY*/ | 1963 | return (ret); |
| 1982 | } else if (alg_k & (SSL_kECDHE|SSL_kECDHr|SSL_kECDHe)) { | 1964 | } |
| 1983 | const EC_GROUP *srvr_group = NULL; | ||
| 1984 | EC_KEY *tkey; | ||
| 1985 | int field_size = 0; | ||
| 1986 | |||
| 1987 | /* Ensure that we have an ephemeral key for ECDHE. */ | ||
| 1988 | if ((alg_k & SSL_kECDHE) && | ||
| 1989 | s->session->sess_cert->peer_ecdh_tmp == NULL) { | ||
| 1990 | ssl3_send_alert(s, SSL3_AL_FATAL, | ||
| 1991 | SSL_AD_HANDSHAKE_FAILURE); | ||
| 1992 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, | ||
| 1993 | ERR_R_INTERNAL_ERROR); | ||
| 1994 | goto err; | ||
| 1995 | } | ||
| 1996 | tkey = s->session->sess_cert->peer_ecdh_tmp; | ||
| 1997 | |||
| 1998 | if (alg_k & (SSL_kECDHr|SSL_kECDHe)) { | ||
| 1999 | /* Get the Server Public Key from Cert */ | ||
| 2000 | srvr_pub_pkey = X509_get_pubkey(s->session-> \ | ||
| 2001 | sess_cert->peer_pkeys[SSL_PKEY_ECC].x509); | ||
| 2002 | if (srvr_pub_pkey != NULL && | ||
| 2003 | srvr_pub_pkey->type == EVP_PKEY_EC) | ||
| 2004 | tkey = srvr_pub_pkey->pkey.ec; | ||
| 2005 | } | ||
| 2006 | 1965 | ||
| 2007 | if (tkey == NULL) { | 1966 | static int |
| 2008 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, | 1967 | ssl3_client_kex_ecdh(SSL *s, SESS_CERT *sess_cert, unsigned char *p, |
| 2009 | ERR_R_INTERNAL_ERROR); | 1968 | int *outlen) |
| 2010 | goto err; | 1969 | { |
| 2011 | } | 1970 | EC_KEY *clnt_ecdh = NULL; |
| 1971 | const EC_GROUP *srvr_group = NULL; | ||
| 1972 | const EC_POINT *srvr_ecpoint = NULL; | ||
| 1973 | EVP_PKEY *srvr_pub_pkey = NULL; | ||
| 1974 | BN_CTX *bn_ctx = NULL; | ||
| 1975 | unsigned char *encodedPoint = NULL; | ||
| 1976 | unsigned long alg_k; | ||
| 1977 | int encoded_pt_len = 0; | ||
| 1978 | int field_size = 0; | ||
| 1979 | EC_KEY *tkey; | ||
| 1980 | int ret = -1; | ||
| 1981 | int n; | ||
| 2012 | 1982 | ||
| 2013 | srvr_group = EC_KEY_get0_group(tkey); | 1983 | alg_k = s->s3->tmp.new_cipher->algorithm_mkey; |
| 2014 | srvr_ecpoint = EC_KEY_get0_public_key(tkey); | ||
| 2015 | 1984 | ||
| 2016 | if ((srvr_group == NULL) || (srvr_ecpoint == NULL)) { | 1985 | /* Ensure that we have an ephemeral key for ECDHE. */ |
| 2017 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, | 1986 | if ((alg_k & SSL_kECDHE) && sess_cert->peer_ecdh_tmp == NULL) { |
| 2018 | ERR_R_INTERNAL_ERROR); | 1987 | ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); |
| 2019 | goto err; | 1988 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, |
| 2020 | } | 1989 | ERR_R_INTERNAL_ERROR); |
| 1990 | goto err; | ||
| 1991 | } | ||
| 1992 | tkey = sess_cert->peer_ecdh_tmp; | ||
| 1993 | |||
| 1994 | if (alg_k & (SSL_kECDHr|SSL_kECDHe)) { | ||
| 1995 | /* Get the Server Public Key from certificate. */ | ||
| 1996 | srvr_pub_pkey = X509_get_pubkey( | ||
| 1997 | sess_cert->peer_pkeys[SSL_PKEY_ECC].x509); | ||
| 1998 | if (srvr_pub_pkey != NULL && srvr_pub_pkey->type == EVP_PKEY_EC) | ||
| 1999 | tkey = srvr_pub_pkey->pkey.ec; | ||
| 2000 | } | ||
| 2021 | 2001 | ||
| 2022 | if ((clnt_ecdh = EC_KEY_new()) == NULL) { | 2002 | if (tkey == NULL) { |
| 2023 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, | 2003 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, |
| 2024 | ERR_R_MALLOC_FAILURE); | 2004 | ERR_R_INTERNAL_ERROR); |
| 2025 | goto err; | 2005 | goto err; |
| 2026 | } | 2006 | } |
| 2027 | 2007 | ||
| 2028 | if (!EC_KEY_set_group(clnt_ecdh, srvr_group)) { | 2008 | srvr_group = EC_KEY_get0_group(tkey); |
| 2029 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, | 2009 | srvr_ecpoint = EC_KEY_get0_public_key(tkey); |
| 2030 | ERR_R_EC_LIB); | ||
| 2031 | goto err; | ||
| 2032 | } | ||
| 2033 | 2010 | ||
| 2034 | /* Generate a new ECDH key pair */ | 2011 | if (srvr_group == NULL || srvr_ecpoint == NULL) { |
| 2035 | if (!(EC_KEY_generate_key(clnt_ecdh))) { | 2012 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, |
| 2036 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, | 2013 | ERR_R_INTERNAL_ERROR); |
| 2037 | ERR_R_ECDH_LIB); | 2014 | goto err; |
| 2038 | goto err; | 2015 | } |
| 2039 | } | ||
| 2040 | 2016 | ||
| 2041 | /* | 2017 | if ((clnt_ecdh = EC_KEY_new()) == NULL) { |
| 2042 | * Use the 'p' output buffer for the ECDH key, but | 2018 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, |
| 2043 | * make sure to clear it out afterwards. | 2019 | ERR_R_MALLOC_FAILURE); |
| 2044 | */ | 2020 | goto err; |
| 2045 | field_size = EC_GROUP_get_degree(srvr_group); | 2021 | } |
| 2046 | if (field_size <= 0) { | ||
| 2047 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, | ||
| 2048 | ERR_R_ECDH_LIB); | ||
| 2049 | goto err; | ||
| 2050 | } | ||
| 2051 | n = ECDH_compute_key(p, (field_size + 7) / 8, | ||
| 2052 | srvr_ecpoint, clnt_ecdh, NULL); | ||
| 2053 | if (n <= 0) { | ||
| 2054 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, | ||
| 2055 | ERR_R_ECDH_LIB); | ||
| 2056 | goto err; | ||
| 2057 | } | ||
| 2058 | 2022 | ||
| 2059 | /* generate master key from the result */ | 2023 | if (!EC_KEY_set_group(clnt_ecdh, srvr_group)) { |
| 2060 | s->session->master_key_length = | 2024 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_EC_LIB); |
| 2061 | s->method->ssl3_enc->generate_master_secret(s, | 2025 | goto err; |
| 2062 | s->session->master_key, p, n); | 2026 | } |
| 2063 | 2027 | ||
| 2064 | /* Clean up. */ | 2028 | /* Generate a new ECDH key pair */ |
| 2065 | explicit_bzero(p, n); | 2029 | if (!(EC_KEY_generate_key(clnt_ecdh))) { |
| 2030 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB); | ||
| 2031 | goto err; | ||
| 2032 | } | ||
| 2066 | 2033 | ||
| 2067 | /* | 2034 | /* |
| 2068 | * First check the size of encoding and | 2035 | * Use the 'p' output buffer for the ECDH key, but make sure to clear |
| 2069 | * allocate memory accordingly. | 2036 | * it out afterwards. |
| 2070 | */ | 2037 | */ |
| 2071 | encoded_pt_len = EC_POINT_point2oct(srvr_group, | 2038 | field_size = EC_GROUP_get_degree(srvr_group); |
| 2072 | EC_KEY_get0_public_key(clnt_ecdh), | 2039 | if (field_size <= 0) { |
| 2073 | POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL); | 2040 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB); |
| 2041 | goto err; | ||
| 2042 | } | ||
| 2043 | n = ECDH_compute_key(p, (field_size + 7) / 8, srvr_ecpoint, clnt_ecdh, | ||
| 2044 | NULL); | ||
| 2045 | if (n <= 0) { | ||
| 2046 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB); | ||
| 2047 | goto err; | ||
| 2048 | } | ||
| 2074 | 2049 | ||
| 2075 | encodedPoint = malloc(encoded_pt_len); | 2050 | /* Generate master key from the result. */ |
| 2051 | s->session->master_key_length = | ||
| 2052 | s->method->ssl3_enc->generate_master_secret(s, | ||
| 2053 | s->session->master_key, p, n); | ||
| 2076 | 2054 | ||
| 2077 | bn_ctx = BN_CTX_new(); | 2055 | /* Clean up. */ |
| 2078 | if ((encodedPoint == NULL) || (bn_ctx == NULL)) { | 2056 | explicit_bzero(p, n); |
| 2079 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, | ||
| 2080 | ERR_R_MALLOC_FAILURE); | ||
| 2081 | goto err; | ||
| 2082 | } | ||
| 2083 | 2057 | ||
| 2084 | /* Encode the public key */ | 2058 | /* |
| 2085 | n = EC_POINT_point2oct(srvr_group, | 2059 | * First check the size of encoding and allocate memory accordingly. |
| 2086 | EC_KEY_get0_public_key(clnt_ecdh), | 2060 | */ |
| 2087 | POINT_CONVERSION_UNCOMPRESSED, encodedPoint, | 2061 | encoded_pt_len = EC_POINT_point2oct(srvr_group, |
| 2088 | encoded_pt_len, bn_ctx); | 2062 | EC_KEY_get0_public_key(clnt_ecdh), |
| 2089 | 2063 | POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL); | |
| 2090 | *p = n; /* length of encoded point */ | 2064 | |
| 2091 | /* Encoded point will be copied here */ | 2065 | bn_ctx = BN_CTX_new(); |
| 2092 | p += 1; | 2066 | encodedPoint = malloc(encoded_pt_len); |
| 2093 | 2067 | if (encodedPoint == NULL || bn_ctx == NULL) { | |
| 2094 | /* copy the point */ | 2068 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, |
| 2095 | memcpy((unsigned char *)p, encodedPoint, n); | 2069 | ERR_R_MALLOC_FAILURE); |
| 2096 | /* increment n to account for length field */ | 2070 | goto err; |
| 2097 | n += 1; | 2071 | } |
| 2098 | |||
| 2099 | /* Free allocated memory */ | ||
| 2100 | BN_CTX_free(bn_ctx); | ||
| 2101 | free(encodedPoint); | ||
| 2102 | EC_KEY_free(clnt_ecdh); | ||
| 2103 | EVP_PKEY_free(srvr_pub_pkey); | ||
| 2104 | } else if (alg_k & SSL_kGOST) { | ||
| 2105 | /* GOST key exchange message creation */ | ||
| 2106 | EVP_PKEY_CTX *pkey_ctx; | ||
| 2107 | X509 *peer_cert; | ||
| 2108 | |||
| 2109 | size_t msglen; | ||
| 2110 | unsigned int md_len; | ||
| 2111 | unsigned char premaster_secret[32], shared_ukm[32], | ||
| 2112 | tmp[256]; | ||
| 2113 | EVP_MD_CTX *ukm_hash; | ||
| 2114 | EVP_PKEY *pub_key; | ||
| 2115 | int nid; | ||
| 2116 | 2072 | ||
| 2117 | /* Get server sertificate PKEY and create ctx from it */ | 2073 | /* Encode the public key */ |
| 2118 | peer_cert = s->session->sess_cert->peer_pkeys[SSL_PKEY_GOST01].x509; | 2074 | n = EC_POINT_point2oct(srvr_group, EC_KEY_get0_public_key(clnt_ecdh), |
| 2119 | if (!peer_cert) { | 2075 | POINT_CONVERSION_UNCOMPRESSED, encodedPoint, encoded_pt_len, |
| 2120 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, | 2076 | bn_ctx); |
| 2121 | SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER); | ||
| 2122 | goto err; | ||
| 2123 | } | ||
| 2124 | 2077 | ||
| 2125 | pub_key = X509_get_pubkey(peer_cert); | 2078 | *p = n; /* length of encoded point */ |
| 2126 | pkey_ctx = EVP_PKEY_CTX_new(pub_key, NULL); | 2079 | /* Encoded point will be copied here */ |
| 2080 | p += 1; | ||
| 2127 | 2081 | ||
| 2128 | /* | 2082 | /* copy the point */ |
| 2129 | * If we have send a certificate, and certificate key | 2083 | memcpy((unsigned char *)p, encodedPoint, n); |
| 2130 | * parameters match those of server certificate, use | 2084 | /* increment n to account for length field */ |
| 2131 | * certificate key for key exchange. | 2085 | n += 1; |
| 2132 | * Otherwise, generate ephemeral key pair. | ||
| 2133 | */ | ||
| 2134 | EVP_PKEY_encrypt_init(pkey_ctx); | ||
| 2135 | 2086 | ||
| 2136 | /* Generate session key. */ | 2087 | *outlen = n; |
| 2137 | arc4random_buf(premaster_secret, 32); | 2088 | ret = 1; |
| 2138 | 2089 | ||
| 2139 | /* | 2090 | err: |
| 2140 | * If we have client certificate, use its secret as | 2091 | /* Free allocated memory */ |
| 2141 | * peer key. | 2092 | BN_CTX_free(bn_ctx); |
| 2142 | */ | 2093 | free(encodedPoint); |
| 2143 | if (s->s3->tmp.cert_req && s->cert->key->privatekey) { | 2094 | EC_KEY_free(clnt_ecdh); |
| 2144 | if (EVP_PKEY_derive_set_peer(pkey_ctx, | 2095 | EVP_PKEY_free(srvr_pub_pkey); |
| 2145 | s->cert->key->privatekey) <=0) { | 2096 | |
| 2146 | /* | 2097 | return (ret); |
| 2147 | * If there was an error - just ignore | 2098 | } |
| 2148 | * it. Ephemeral key would be used. | 2099 | |
| 2149 | */ | 2100 | static int |
| 2150 | ERR_clear_error(); | 2101 | ssl3_client_kex_gost(SSL *s, SESS_CERT *sess_cert, unsigned char *p, |
| 2151 | } | 2102 | int *outlen) |
| 2152 | } | 2103 | { |
| 2104 | unsigned char premaster_secret[32], shared_ukm[32], tmp[256]; | ||
| 2105 | EVP_PKEY *pub_key = NULL; | ||
| 2106 | EVP_PKEY_CTX *pkey_ctx; | ||
| 2107 | X509 *peer_cert; | ||
| 2108 | size_t msglen; | ||
| 2109 | unsigned int md_len; | ||
| 2110 | EVP_MD_CTX *ukm_hash; | ||
| 2111 | int ret = -1; | ||
| 2112 | int nid; | ||
| 2113 | int n; | ||
| 2114 | |||
| 2115 | /* Get server sertificate PKEY and create ctx from it */ | ||
| 2116 | peer_cert = sess_cert->peer_pkeys[SSL_PKEY_GOST01].x509; | ||
| 2117 | if (peer_cert == NULL) { | ||
| 2118 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, | ||
| 2119 | SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER); | ||
| 2120 | goto err; | ||
| 2121 | } | ||
| 2122 | |||
| 2123 | pub_key = X509_get_pubkey(peer_cert); | ||
| 2124 | pkey_ctx = EVP_PKEY_CTX_new(pub_key, NULL); | ||
| 2125 | |||
| 2126 | /* | ||
| 2127 | * If we have send a certificate, and certificate key parameters match | ||
| 2128 | * those of server certificate, use certificate key for key exchange. | ||
| 2129 | * Otherwise, generate ephemeral key pair. | ||
| 2130 | */ | ||
| 2131 | EVP_PKEY_encrypt_init(pkey_ctx); | ||
| 2132 | |||
| 2133 | /* Generate session key. */ | ||
| 2134 | arc4random_buf(premaster_secret, 32); | ||
| 2153 | 2135 | ||
| 2136 | /* | ||
| 2137 | * If we have client certificate, use its secret as peer key. | ||
| 2138 | */ | ||
| 2139 | if (s->s3->tmp.cert_req && s->cert->key->privatekey) { | ||
| 2140 | if (EVP_PKEY_derive_set_peer(pkey_ctx, | ||
| 2141 | s->cert->key->privatekey) <=0) { | ||
| 2154 | /* | 2142 | /* |
| 2155 | * Compute shared IV and store it in algorithm-specific | 2143 | * If there was an error - just ignore it. |
| 2156 | * context data. | 2144 | * Ephemeral key would be used. |
| 2157 | */ | 2145 | */ |
| 2158 | ukm_hash = EVP_MD_CTX_create(); | 2146 | ERR_clear_error(); |
| 2159 | if (ukm_hash == NULL) { | 2147 | } |
| 2160 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, | 2148 | } |
| 2161 | ERR_R_MALLOC_FAILURE); | ||
| 2162 | explicit_bzero(premaster_secret, | ||
| 2163 | sizeof(premaster_secret)); | ||
| 2164 | goto err; | ||
| 2165 | } | ||
| 2166 | 2149 | ||
| 2167 | if (ssl_get_algorithm2(s) & SSL_HANDSHAKE_MAC_GOST94) | 2150 | /* |
| 2168 | nid = NID_id_GostR3411_94; | 2151 | * Compute shared IV and store it in algorithm-specific context data. |
| 2169 | else | 2152 | */ |
| 2170 | nid = NID_id_tc26_gost3411_2012_256; | 2153 | ukm_hash = EVP_MD_CTX_create(); |
| 2171 | if (!EVP_DigestInit(ukm_hash, EVP_get_digestbynid(nid))) | 2154 | if (ukm_hash == NULL) { |
| 2155 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, | ||
| 2156 | ERR_R_MALLOC_FAILURE); | ||
| 2157 | goto err; | ||
| 2158 | } | ||
| 2159 | |||
| 2160 | if (ssl_get_algorithm2(s) & SSL_HANDSHAKE_MAC_GOST94) | ||
| 2161 | nid = NID_id_GostR3411_94; | ||
| 2162 | else | ||
| 2163 | nid = NID_id_tc26_gost3411_2012_256; | ||
| 2164 | if (!EVP_DigestInit(ukm_hash, EVP_get_digestbynid(nid))) | ||
| 2165 | goto err; | ||
| 2166 | EVP_DigestUpdate(ukm_hash, s->s3->client_random, SSL3_RANDOM_SIZE); | ||
| 2167 | EVP_DigestUpdate(ukm_hash, s->s3->server_random, SSL3_RANDOM_SIZE); | ||
| 2168 | EVP_DigestFinal_ex(ukm_hash, shared_ukm, &md_len); | ||
| 2169 | EVP_MD_CTX_destroy(ukm_hash); | ||
| 2170 | if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_ENCRYPT, | ||
| 2171 | EVP_PKEY_CTRL_SET_IV, 8, shared_ukm) < 0) { | ||
| 2172 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, SSL_R_LIBRARY_BUG); | ||
| 2173 | goto err; | ||
| 2174 | } | ||
| 2175 | |||
| 2176 | /* | ||
| 2177 | * Make GOST keytransport blob message, encapsulate it into sequence. | ||
| 2178 | */ | ||
| 2179 | *(p++) = V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED; | ||
| 2180 | msglen = 255; | ||
| 2181 | if (EVP_PKEY_encrypt(pkey_ctx, tmp, &msglen, premaster_secret, | ||
| 2182 | 32) < 0) { | ||
| 2183 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, SSL_R_LIBRARY_BUG); | ||
| 2184 | goto err; | ||
| 2185 | } | ||
| 2186 | if (msglen >= 0x80) { | ||
| 2187 | *(p++) = 0x81; | ||
| 2188 | *(p++) = msglen & 0xff; | ||
| 2189 | n = msglen + 3; | ||
| 2190 | } else { | ||
| 2191 | *(p++) = msglen & 0xff; | ||
| 2192 | n = msglen + 2; | ||
| 2193 | } | ||
| 2194 | memcpy(p, tmp, msglen); | ||
| 2195 | |||
| 2196 | /* Check if pubkey from client certificate was used. */ | ||
| 2197 | if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2, | ||
| 2198 | NULL) > 0) { | ||
| 2199 | /* Set flag "skip certificate verify". */ | ||
| 2200 | s->s3->flags |= TLS1_FLAGS_SKIP_CERT_VERIFY; | ||
| 2201 | } | ||
| 2202 | EVP_PKEY_CTX_free(pkey_ctx); | ||
| 2203 | s->session->master_key_length = | ||
| 2204 | s->method->ssl3_enc->generate_master_secret(s, | ||
| 2205 | s->session->master_key, premaster_secret, 32); | ||
| 2206 | |||
| 2207 | *outlen = n; | ||
| 2208 | ret = 1; | ||
| 2209 | |||
| 2210 | err: | ||
| 2211 | explicit_bzero(premaster_secret, sizeof(premaster_secret)); | ||
| 2212 | EVP_PKEY_free(pub_key); | ||
| 2213 | |||
| 2214 | return (ret); | ||
| 2215 | } | ||
| 2216 | |||
| 2217 | int | ||
| 2218 | ssl3_send_client_key_exchange(SSL *s) | ||
| 2219 | { | ||
| 2220 | SESS_CERT *sess_cert; | ||
| 2221 | unsigned long alg_k; | ||
| 2222 | unsigned char *p; | ||
| 2223 | int n; | ||
| 2224 | |||
| 2225 | if (s->state == SSL3_ST_CW_KEY_EXCH_A) { | ||
| 2226 | p = ssl3_handshake_msg_start(s, SSL3_MT_CLIENT_KEY_EXCHANGE); | ||
| 2227 | |||
| 2228 | alg_k = s->s3->tmp.new_cipher->algorithm_mkey; | ||
| 2229 | |||
| 2230 | if ((sess_cert = s->session->sess_cert) == NULL) { | ||
| 2231 | ssl3_send_alert(s, SSL3_AL_FATAL, | ||
| 2232 | SSL_AD_UNEXPECTED_MESSAGE); | ||
| 2233 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, | ||
| 2234 | ERR_R_INTERNAL_ERROR); | ||
| 2235 | goto err; | ||
| 2236 | } | ||
| 2237 | |||
| 2238 | if (alg_k & SSL_kRSA) { | ||
| 2239 | if (ssl3_client_kex_rsa(s, sess_cert, p, &n) != 1) | ||
| 2172 | goto err; | 2240 | goto err; |
| 2173 | EVP_DigestUpdate(ukm_hash, | 2241 | } else if (alg_k & SSL_kDHE) { |
| 2174 | s->s3->client_random, SSL3_RANDOM_SIZE); | 2242 | if (ssl3_client_kex_dhe(s, sess_cert, p, &n) != 1) |
| 2175 | EVP_DigestUpdate(ukm_hash, | ||
| 2176 | s->s3->server_random, SSL3_RANDOM_SIZE); | ||
| 2177 | EVP_DigestFinal_ex(ukm_hash, shared_ukm, &md_len); | ||
| 2178 | EVP_MD_CTX_destroy(ukm_hash); | ||
| 2179 | if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_ENCRYPT, | ||
| 2180 | EVP_PKEY_CTRL_SET_IV, 8, shared_ukm) < 0) { | ||
| 2181 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, | ||
| 2182 | SSL_R_LIBRARY_BUG); | ||
| 2183 | explicit_bzero(premaster_secret, | ||
| 2184 | sizeof(premaster_secret)); | ||
| 2185 | goto err; | 2243 | goto err; |
| 2186 | } | 2244 | } else if (alg_k & (SSL_kECDHE|SSL_kECDHr|SSL_kECDHe)) { |
| 2187 | 2245 | if (ssl3_client_kex_ecdh(s, sess_cert, p, &n) != 1) | |
| 2188 | /* | 2246 | goto err; |
| 2189 | * Make GOST keytransport blob message, encapsulate it | 2247 | } else if (alg_k & SSL_kGOST) { |
| 2190 | * into sequence. | 2248 | if (ssl3_client_kex_gost(s, sess_cert, p, &n) != 1) |
| 2191 | */ | ||
| 2192 | *(p++) = V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED; | ||
| 2193 | msglen = 255; | ||
| 2194 | if (EVP_PKEY_encrypt(pkey_ctx, tmp, &msglen, | ||
| 2195 | premaster_secret, 32) < 0) { | ||
| 2196 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, | ||
| 2197 | SSL_R_LIBRARY_BUG); | ||
| 2198 | goto err; | 2249 | goto err; |
| 2199 | } | ||
| 2200 | if (msglen >= 0x80) { | ||
| 2201 | *(p++) = 0x81; | ||
| 2202 | *(p++) = msglen & 0xff; | ||
| 2203 | n = msglen + 3; | ||
| 2204 | } else { | ||
| 2205 | *(p++) = msglen & 0xff; | ||
| 2206 | n = msglen + 2; | ||
| 2207 | } | ||
| 2208 | memcpy(p, tmp, msglen); | ||
| 2209 | /* Check if pubkey from client certificate was used. */ | ||
| 2210 | if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, -1, | ||
| 2211 | EVP_PKEY_CTRL_PEER_KEY, 2, NULL) > 0) { | ||
| 2212 | /* Set flag "skip certificate verify". */ | ||
| 2213 | s->s3->flags |= TLS1_FLAGS_SKIP_CERT_VERIFY; | ||
| 2214 | } | ||
| 2215 | EVP_PKEY_CTX_free(pkey_ctx); | ||
| 2216 | s->session->master_key_length = | ||
| 2217 | s->method->ssl3_enc->generate_master_secret(s, | ||
| 2218 | s->session->master_key, premaster_secret, 32); | ||
| 2219 | EVP_PKEY_free(pub_key); | ||
| 2220 | explicit_bzero(premaster_secret, | ||
| 2221 | sizeof(premaster_secret)); | ||
| 2222 | } else { | 2250 | } else { |
| 2223 | ssl3_send_alert(s, SSL3_AL_FATAL, | 2251 | ssl3_send_alert(s, SSL3_AL_FATAL, |
| 2224 | SSL_AD_HANDSHAKE_FAILURE); | 2252 | SSL_AD_HANDSHAKE_FAILURE); |
| @@ -2236,10 +2264,6 @@ ssl3_send_client_key_exchange(SSL *s) | |||
| 2236 | return (ssl3_handshake_write(s)); | 2264 | return (ssl3_handshake_write(s)); |
| 2237 | 2265 | ||
| 2238 | err: | 2266 | err: |
| 2239 | BN_CTX_free(bn_ctx); | ||
| 2240 | free(encodedPoint); | ||
| 2241 | EC_KEY_free(clnt_ecdh); | ||
| 2242 | EVP_PKEY_free(srvr_pub_pkey); | ||
| 2243 | return (-1); | 2267 | return (-1); |
| 2244 | } | 2268 | } |
| 2245 | 2269 | ||
