aboutsummaryrefslogtreecommitdiff
path: root/patches/0011-ecdhe_psk.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patches/0011-ecdhe_psk.patch')
-rw-r--r--patches/0011-ecdhe_psk.patch1435
1 files changed, 0 insertions, 1435 deletions
diff --git a/patches/0011-ecdhe_psk.patch b/patches/0011-ecdhe_psk.patch
deleted file mode 100644
index a3ab573107..0000000000
--- a/patches/0011-ecdhe_psk.patch
+++ /dev/null
@@ -1,1435 +0,0 @@
-From 1d43b892d27915843e5714d96de269672b5b35db Mon Sep 17 00:00:00 2001
-From: Adam Langley <agl@chromium.org>
-Date: Thu, 14 Nov 2013 16:12:01 -0500
-Subject: Implement ECDHE-PSK-WITH-AES.
-
-Add support for TLS-ECDHE-PSK cipher suites:
-* TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256, and
-* TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA384.
----
- ssl/s3_clnt.c | 360 ++++++++++++++++++++++----------------
- ssl/s3_enc.c | 2 +-
- ssl/s3_lib.c | 38 +++++-
- ssl/s3_srvr.c | 541 ++++++++++++++++++++++++++++++++--------------------------
- ssl/ssl_lib.c | 2 +-
- ssl/tls1.h | 8 +
- 6 files changed, 555 insertions(+), 396 deletions(-)
-
-diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
-index 8f3740f..3672cce 100644
---- a/ssl/s3_clnt.c
-+++ b/ssl/s3_clnt.c
-@@ -333,9 +333,10 @@ int ssl3_connect(SSL *s)
- }
- #endif
- /* Check if it is anon DH/ECDH, SRP auth */
-- /* or PSK */
-+ /* or non-RSA PSK */
- if (!(s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL|SSL_aSRP)) &&
-- !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
-+ !((s->s3->tmp.new_cipher->algorithm_auth & SSL_aPSK) &&
-+ !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kRSA)))
- {
- ret=ssl3_get_server_certificate(s);
- if (ret <= 0) goto end;
-@@ -1368,7 +1369,7 @@ int ssl3_get_key_exchange(SSL *s)
- omitted if no identity hint is sent. Set
- session->sess_cert anyway to avoid problems
- later.*/
-- if (alg_k & SSL_kPSK)
-+ if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aPSK)
- {
- s->session->sess_cert=ssl_sess_cert_new();
- if (s->ctx->psk_identity_hint)
-@@ -1416,61 +1417,65 @@ int ssl3_get_key_exchange(SSL *s)
- EVP_MD_CTX_init(&md_ctx);
-
- #ifndef OPENSSL_NO_PSK
-- if (alg_k & SSL_kPSK)
-+ if (alg_a & SSL_aPSK)
- {
- char tmp_id_hint[PSK_MAX_IDENTITY_LEN+1];
-
- param_len = 2;
- if (param_len > n)
- {
- SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
- SSL_R_LENGTH_TOO_SHORT);
- goto f_err;
- }
- n2s(p,i);
-
-- /* Store PSK identity hint for later use, hint is used
-- * in ssl3_send_client_key_exchange. Assume that the
-- * maximum length of a PSK identity hint can be as
-- * long as the maximum length of a PSK identity. */
-- if (i > PSK_MAX_IDENTITY_LEN)
-- {
-- al=SSL_AD_HANDSHAKE_FAILURE;
-- SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
-- SSL_R_DATA_LENGTH_TOO_LONG);
-- goto f_err;
-- }
-- if (i > n - param_len)
-+ s->ctx->psk_identity_hint = NULL;
-+ if (i != 0)
- {
-- SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
-- SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH);
-- goto f_err;
-+ /* Store PSK identity hint for later use, hint is used
-+ * in ssl3_send_client_key_exchange. Assume that the
-+ * maximum length of a PSK identity hint can be as
-+ * long as the maximum length of a PSK identity. */
-+ if (i > PSK_MAX_IDENTITY_LEN)
-+ {
-+ al=SSL_AD_HANDSHAKE_FAILURE;
-+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
-+ SSL_R_DATA_LENGTH_TOO_LONG);
-+ goto f_err;
-+ }
-+ if (i > n - param_len)
-+ {
-+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
-+ SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH);
-+ goto f_err;
-+ }
-+ param_len += i;
-+
-+ /* If received PSK identity hint contains NULL
-+ * characters, the hint is truncated from the first
-+ * NULL. p may not be ending with NULL, so create a
-+ * NULL-terminated string. */
-+ memcpy(tmp_id_hint, p, i);
-+ memset(tmp_id_hint+i, 0, PSK_MAX_IDENTITY_LEN+1-i);
-+ if (s->ctx->psk_identity_hint != NULL)
-+ OPENSSL_free(s->ctx->psk_identity_hint);
-+ s->ctx->psk_identity_hint = BUF_strdup(tmp_id_hint);
-+ if (s->ctx->psk_identity_hint == NULL)
-+ {
-+ al=SSL_AD_HANDSHAKE_FAILURE;
-+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
-+ goto f_err;
-+ }
- }
-- param_len += i;
--
-- /* If received PSK identity hint contains NULL
-- * characters, the hint is truncated from the first
-- * NULL. p may not be ending with NULL, so create a
-- * NULL-terminated string. */
-- memcpy(tmp_id_hint, p, i);
-- memset(tmp_id_hint+i, 0, PSK_MAX_IDENTITY_LEN+1-i);
-- if (s->ctx->psk_identity_hint != NULL)
-- OPENSSL_free(s->ctx->psk_identity_hint);
-- s->ctx->psk_identity_hint = BUF_strdup(tmp_id_hint);
-- if (s->ctx->psk_identity_hint == NULL)
-- {
-- al=SSL_AD_HANDSHAKE_FAILURE;
-- SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
-- goto f_err;
-- }
--
- p+=i;
- n-=param_len;
- }
-- else
- #endif /* !OPENSSL_NO_PSK */
-+
-+ if (0) {}
- #ifndef OPENSSL_NO_SRP
-- if (alg_k & SSL_kSRP)
-+ else if (alg_k & SSL_kSRP)
- {
- n2s(p,i);
- param_len=i+2;
-@@ -1538,10 +1543,9 @@ int ssl3_get_key_exchange(SSL *s)
- pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_DSA_SIGN].x509);
- #endif
- }
-- else
- #endif /* !OPENSSL_NO_SRP */
- #ifndef OPENSSL_NO_RSA
-- if (alg_k & SSL_kRSA)
-+ else if (alg_k & SSL_kRSA)
- {
- if ((rsa=RSA_new()) == NULL)
- {
-@@ -1590,9 +1594,6 @@ int ssl3_get_key_exchange(SSL *s)
- s->session->sess_cert->peer_rsa_tmp=rsa;
- rsa=NULL;
- }
--#else /* OPENSSL_NO_RSA */
-- if (0)
-- ;
- #endif
- #ifndef OPENSSL_NO_DH
- else if (alg_k & SSL_kEDH)
-@@ -1773,14 +1774,14 @@ int ssl3_get_key_exchange(SSL *s)
- EC_POINT_free(srvr_ecpoint);
- srvr_ecpoint = NULL;
- }
-- else if (alg_k)
-+#endif /* !OPENSSL_NO_ECDH */
-+
-+ else if (!(alg_k & SSL_kPSK))
- {
- al=SSL_AD_UNEXPECTED_MESSAGE;
- SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE);
- goto f_err;
- }
--#endif /* !OPENSSL_NO_ECDH */
--
-
- /* p points to the next byte, there are 'n' bytes left */
-
-@@ -1885,8 +1886,9 @@ fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md));
- }
- else
- {
-- /* aNULL, aSRP or kPSK do not need public keys */
-- if (!(alg_a & (SSL_aNULL|SSL_aSRP)) && !(alg_k & SSL_kPSK))
-+ if (!(alg_a & (SSL_aNULL|SSL_aSRP)) &&
-+ /* Among PSK ciphers only RSA_PSK needs a public key */
-+ !((alg_a & SSL_aPSK) && !(alg_k & SSL_kRSA)))
- {
- SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
- goto err;
-@@ -2286,8 +2288,9 @@ int ssl3_get_server_done(SSL *s)
- int ssl3_send_client_key_exchange(SSL *s)
- {
- unsigned char *p,*d;
-- int n;
-+ int n = 0;
- unsigned long alg_k;
-+ unsigned long alg_a;
- #ifndef OPENSSL_NO_RSA
- unsigned char *q;
- EVP_PKEY *pkey=NULL;
-@@ -2302,7 +2305,11 @@ int ssl3_send_client_key_exchange(SSL *s)
- unsigned char *encodedPoint = NULL;
- int encoded_pt_len = 0;
- BN_CTX * bn_ctx = NULL;
--#endif
-+#ifndef OPENSSL_NO_PSK
-+ unsigned int psk_len = 0;
-+ unsigned char psk[PSK_MAX_PSK_LEN];
-+#endif /* OPENSSL_NO_PSK */
-+#endif /* OPENSSL_NO_ECDH */
-
- if (s->state == SSL3_ST_CW_KEY_EXCH_A)
- {
-@@ -2310,7 +2317,106 @@ int ssl3_send_client_key_exchange(SSL *s)
- p= &(d[4]);
-
- alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
-+ alg_a=s->s3->tmp.new_cipher->algorithm_auth;
-+
-+#ifndef OPENSSL_NO_PSK
-+ if (alg_a & SSL_aPSK)
-+ {
-+ /* The callback needs PSK_MAX_IDENTITY_LEN + 1 bytes
-+ * to return a \0-terminated identity. The last byte
-+ * is for us for simulating strnlen. */
-+ char identity[PSK_MAX_IDENTITY_LEN + 2];
-+ size_t identity_len;
-+ unsigned char *t = NULL;
-+ unsigned char pre_ms[PSK_MAX_PSK_LEN*2+4];
-+ unsigned int pre_ms_len = 0;
-+ int psk_err = 1;
-+
-+ n = 0;
-+ if (s->psk_client_callback == NULL)
-+ {
-+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
-+ SSL_R_PSK_NO_CLIENT_CB);
-+ goto err;
-+ }
-
-+ psk_len = s->psk_client_callback(s, s->ctx->psk_identity_hint,
-+ identity, sizeof(identity) - 1, psk, sizeof(psk));
-+ if (psk_len > PSK_MAX_PSK_LEN)
-+ {
-+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
-+ ERR_R_INTERNAL_ERROR);
-+ goto psk_err;
-+ }
-+ else if (psk_len == 0)
-+ {
-+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
-+ SSL_R_PSK_IDENTITY_NOT_FOUND);
-+ goto psk_err;
-+ }
-+ identity[PSK_MAX_IDENTITY_LEN + 1] = '\0';
-+ identity_len = strlen(identity);
-+ if (identity_len > PSK_MAX_IDENTITY_LEN)
-+ {
-+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
-+ ERR_R_INTERNAL_ERROR);
-+ goto psk_err;
-+ }
-+ if (!(alg_k & SSL_kEECDH))
-+ {
-+ /* Create the shared secret now if we're not using ECDHE-PSK.*/
-+ pre_ms_len = 2+psk_len+2+psk_len;
-+ t = pre_ms;
-+ s2n(psk_len, t);
-+ memset(t, 0, psk_len);
-+ t+=psk_len;
-+ s2n(psk_len, t);
-+ memcpy(t, psk, psk_len);
-+
-+ s->session->master_key_length =
-+ s->method->ssl3_enc->generate_master_secret(s,
-+ s->session->master_key,
-+ pre_ms, pre_ms_len);
-+ s2n(identity_len, p);
-+ memcpy(p, identity, identity_len);
-+ n = 2 + identity_len;
-+ }
-+
-+ if (s->session->psk_identity_hint != NULL)
-+ OPENSSL_free(s->session->psk_identity_hint);
-+ s->session->psk_identity_hint = NULL;
-+ if (s->ctx->psk_identity_hint)
-+ {
-+ s->session->psk_identity_hint = BUF_strdup(s->ctx->psk_identity_hint);
-+ if (s->ctx->psk_identity_hint != NULL &&
-+ s->session->psk_identity_hint == NULL)
-+ {
-+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
-+ ERR_R_MALLOC_FAILURE);
-+ goto psk_err;
-+ }
-+ }
-+
-+ if (s->session->psk_identity != NULL)
-+ OPENSSL_free(s->session->psk_identity);
-+ s->session->psk_identity = BUF_strdup(identity);
-+ if (s->session->psk_identity == NULL)
-+ {
-+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
-+ ERR_R_MALLOC_FAILURE);
-+ goto psk_err;
-+ }
-+ psk_err = 0;
-+ psk_err:
-+ OPENSSL_cleanse(identity, sizeof(identity));
-+ OPENSSL_cleanse(pre_ms, sizeof(pre_ms));
-+ if (psk_err != 0)
-+ {
-+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
-+ goto err;
-+ }
-+ }
-+#endif
- /* Fool emacs indentation */
- if (0) {}
- #ifndef OPENSSL_NO_RSA
-@@ -2571,14 +2667,19 @@ int ssl3_send_client_key_exchange(SSL *s)
- /* perhaps clean things up a bit EAY EAY EAY EAY*/
- }
- #endif
--
--#ifndef OPENSSL_NO_ECDH
-+#ifndef OPENSSL_NO_ECDH
- else if (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe))
- {
- const EC_GROUP *srvr_group = NULL;
- EC_KEY *tkey;
- int ecdh_clnt_cert = 0;
- int field_size = 0;
-+#ifndef OPENSSL_NO_PSK
-+ unsigned char *pre_ms;
-+ unsigned char *t;
-+ unsigned int pre_ms_len;
-+ unsigned int i;
-+#endif
-
- if (s->session->sess_cert == NULL)
- {
-@@ -2706,15 +2807,41 @@ int ssl3_send_client_key_exchange(SSL *s)
- goto err;
- }
-
-- /* generate master key from the result */
-- s->session->master_key_length = s->method->ssl3_enc \
-- -> generate_master_secret(s,
-- s->session->master_key,
-- p, n);
--
-+#ifndef OPENSSL_NO_PSK
-+ /* ECDHE PSK ciphersuites from RFC 5489 */
-+ if ((alg_a & SSL_aPSK) && psk_len != 0)
-+ {
-+ pre_ms_len = 2+n+2+psk_len;
-+ pre_ms = OPENSSL_malloc(pre_ms_len);
-+ if (pre_ms == NULL)
-+ {
-+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
-+ ERR_R_MALLOC_FAILURE);
-+ goto err;
-+ }
-+ memset(pre_ms, 0, pre_ms_len);
-+ t = pre_ms;
-+ s2n(n, t);
-+ memcpy(t, p, n);
-+ t += n;
-+ s2n(psk_len, t);
-+ memcpy(t, psk, psk_len);
-+ s->session->master_key_length = s->method->ssl3_enc \
-+ -> generate_master_secret(s,
-+ s->session->master_key, pre_ms, pre_ms_len);
-+ OPENSSL_cleanse(pre_ms, pre_ms_len);
-+ OPENSSL_free(pre_ms);
-+ }
-+#endif /* OPENSSL_NO_PSK */
-+ if (!(alg_a & SSL_aPSK))
-+ {
-+ /* generate master key from the result */
-+ s->session->master_key_length = s->method->ssl3_enc \
-+ -> generate_master_secret(s,
-+ s->session->master_key, p, n);
-+ }
- memset(p, 0, n); /* clean up */
--
-- if (ecdh_clnt_cert)
-+ if (ecdh_clnt_cert)
- {
- /* Send empty client key exch message */
- n = 0;
-@@ -2742,29 +2869,42 @@ int ssl3_send_client_key_exchange(SSL *s)
- }
-
- /* Encode the public key */
-- n = EC_POINT_point2oct(srvr_group,
-- EC_KEY_get0_public_key(clnt_ecdh),
-- POINT_CONVERSION_UNCOMPRESSED,
-+ encoded_pt_len = EC_POINT_point2oct(srvr_group,
-+ EC_KEY_get0_public_key(clnt_ecdh),
-+ POINT_CONVERSION_UNCOMPRESSED,
- encodedPoint, encoded_pt_len, bn_ctx);
-+
-+ n = 0;
-+#ifndef OPENSSL_NO_PSK
-+ if ((alg_a & SSL_aPSK) && psk_len != 0)
-+ {
-+ i = strlen(s->session->psk_identity);
-+ s2n(i, p);
-+ memcpy(p, s->session->psk_identity, i);
-+ p += i;
-+ n = i + 2;
-+ }
-+#endif
-
-- *p = n; /* length of encoded point */
-+ *p = encoded_pt_len; /* length of encoded point */
- /* Encoded point will be copied here */
-- p += 1;
-+ p += 1;
-+ n += 1;
- /* copy the point */
-- memcpy((unsigned char *)p, encodedPoint, n);
-+ memcpy((unsigned char *)p, encodedPoint, encoded_pt_len);
- /* increment n to account for length field */
-- n += 1;
-+ n += encoded_pt_len;
- }
-
- /* Free allocated memory */
- BN_CTX_free(bn_ctx);
- if (encodedPoint != NULL) OPENSSL_free(encodedPoint);
-- if (clnt_ecdh != NULL)
-+ if (clnt_ecdh != NULL)
- EC_KEY_free(clnt_ecdh);
- EVP_PKEY_free(srvr_pub_pkey);
- }
- #endif /* !OPENSSL_NO_ECDH */
-- else if (alg_k & SSL_kGOST)
-+ else if (alg_k & SSL_kGOST)
- {
- /* GOST key exchange message creation */
- EVP_PKEY_CTX *pkey_ctx;
-@@ -2887,100 +3027,7 @@ int ssl3_send_client_key_exchange(SSL *s)
- }
- }
- #endif
--#ifndef OPENSSL_NO_PSK
-- else if (alg_k & SSL_kPSK)
-- {
-- /* The callback needs PSK_MAX_IDENTITY_LEN + 1 bytes
-- * to return a \0-terminated identity. The last byte
-- * is for us for simulating strnlen. */
-- char identity[PSK_MAX_IDENTITY_LEN + 2];
-- size_t identity_len;
-- unsigned char *t = NULL;
-- unsigned char psk_or_pre_ms[PSK_MAX_PSK_LEN*2+4];
-- unsigned int pre_ms_len = 0, psk_len = 0;
-- int psk_err = 1;
--
-- n = 0;
-- if (s->psk_client_callback == NULL)
-- {
-- SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
-- SSL_R_PSK_NO_CLIENT_CB);
-- goto err;
-- }
--
-- memset(identity, 0, sizeof(identity));
-- psk_len = s->psk_client_callback(s, s->ctx->psk_identity_hint,
-- identity, sizeof(identity) - 1,
-- psk_or_pre_ms, sizeof(psk_or_pre_ms));
-- if (psk_len > PSK_MAX_PSK_LEN)
-- {
-- SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
-- ERR_R_INTERNAL_ERROR);
-- goto psk_err;
-- }
-- else if (psk_len == 0)
-- {
-- SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
-- SSL_R_PSK_IDENTITY_NOT_FOUND);
-- goto psk_err;
-- }
-- identity[PSK_MAX_IDENTITY_LEN + 1] = '\0';
-- identity_len = strlen(identity);
-- if (identity_len > PSK_MAX_IDENTITY_LEN)
-- {
-- SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
-- ERR_R_INTERNAL_ERROR);
-- goto psk_err;
-- }
-- /* create PSK pre_master_secret */
-- pre_ms_len = 2+psk_len+2+psk_len;
-- t = psk_or_pre_ms;
-- memmove(psk_or_pre_ms+psk_len+4, psk_or_pre_ms, psk_len);
-- s2n(psk_len, t);
-- memset(t, 0, psk_len);
-- t+=psk_len;
-- s2n(psk_len, t);
--
-- if (s->session->psk_identity_hint != NULL)
-- OPENSSL_free(s->session->psk_identity_hint);
-- s->session->psk_identity_hint = BUF_strdup(s->ctx->psk_identity_hint);
-- if (s->ctx->psk_identity_hint != NULL &&
-- s->session->psk_identity_hint == NULL)
-- {
-- SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
-- ERR_R_MALLOC_FAILURE);
-- goto psk_err;
-- }
--
-- if (s->session->psk_identity != NULL)
-- OPENSSL_free(s->session->psk_identity);
-- s->session->psk_identity = BUF_strdup(identity);
-- if (s->session->psk_identity == NULL)
-- {
-- SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
-- ERR_R_MALLOC_FAILURE);
-- goto psk_err;
-- }
--
-- s->session->master_key_length =
-- s->method->ssl3_enc->generate_master_secret(s,
-- s->session->master_key,
-- psk_or_pre_ms, pre_ms_len);
-- s2n(identity_len, p);
-- memcpy(p, identity, identity_len);
-- n = 2 + identity_len;
-- psk_err = 0;
-- psk_err:
-- OPENSSL_cleanse(identity, sizeof(identity));
-- OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms));
-- if (psk_err != 0)
-- {
-- ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
-- goto err;
-- }
-- }
--#endif
-- else
-+ else if (!(alg_k & SSL_kPSK) || ((alg_k & SSL_kPSK) && !(alg_a & SSL_aPSK)))
- {
- ssl3_send_alert(s, SSL3_AL_FATAL,
- SSL_AD_HANDSHAKE_FAILURE);
-diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c
-index 6358e1b..0dac7e7 100644
---- a/ssl/s3_enc.c
-+++ b/ssl/s3_enc.c
-@@ -734,7 +734,7 @@ int n_ssl3_mac(SSL *ssl, unsigned char *md, int send)
- }
-
- t=EVP_MD_CTX_size(hash);
-- if (t < 0)
-+ if (t < 0 || t > 20)
- return -1;
- md_size=t;
- npad=(48/md_size)*md_size;
-diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
-index 1d87ac5..77244d3 100644
---- a/ssl/s3_lib.c
-+++ b/ssl/s3_lib.c
-@@ -2827,6 +2827,42 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
- 256,
- },
-
-+#ifndef OPENSSL_NO_PSK
-+ /* ECDH PSK ciphersuites from RFC 5489 */
-+
-+ /* Cipher C037 */
-+ {
-+ 1,
-+ TLS1_TXT_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
-+ TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
-+ SSL_kEECDH,
-+ SSL_aPSK,
-+ SSL_AES128,
-+ SSL_SHA256,
-+ SSL_TLSV1,
-+ SSL_NOT_EXP|SSL_HIGH,
-+ SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF_SHA256,
-+ 128,
-+ 128,
-+ },
-+
-+ /* Cipher C038 */
-+ {
-+ 1,
-+ TLS1_TXT_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
-+ TLS1_CK_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
-+ SSL_kEECDH,
-+ SSL_aPSK,
-+ SSL_AES256,
-+ SSL_SHA384,
-+ SSL_TLSV1,
-+ SSL_NOT_EXP|SSL_HIGH,
-+ SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF_SHA384,
-+ 256,
-+ 256,
-+ },
-+#endif /* OPENSSL_NO_PSK */
-+
- #endif /* OPENSSL_NO_ECDH */
-
-
-@@ -3979,7 +3999,7 @@ SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
- #endif /* OPENSSL_NO_KRB5 */
- #ifndef OPENSSL_NO_PSK
- /* with PSK there must be server callback set */
-- if ((alg_k & SSL_kPSK) && s->psk_server_callback == NULL)
-+ if ((alg_a & SSL_aPSK) && s->psk_server_callback == NULL)
- continue;
- #endif /* OPENSSL_NO_PSK */
-
-diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
-index 9335eda..fe70124 100644
---- a/ssl/s3_srvr.c
-+++ b/ssl/s3_srvr.c
-@@ -217,6 +217,7 @@ int ssl3_accept(SSL *s)
- {
- BUF_MEM *buf;
- unsigned long alg_k,Time=(unsigned long)time(NULL);
-+ unsigned long alg_a;
- void (*cb)(const SSL *ssl,int type,int val)=NULL;
- int ret= -1;
- int new_state,state,skip=0;
-@@ -418,8 +419,10 @@ int ssl3_accept(SSL *s)
- case SSL3_ST_SW_CERT_A:
- case SSL3_ST_SW_CERT_B:
- /* Check if it is anon DH or anon ECDH, */
-- /* normal PSK or KRB5 or SRP */
-+ /* non-RSA PSK or KRB5 or SRP */
- if (!(s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL|SSL_aKRB5|SSL_aSRP))
-- && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
-+ /* Among PSK ciphersuites only RSA_PSK uses server certificate */
-+ && !(s->s3->tmp.new_cipher->algorithm_auth & SSL_aPSK &&
-+ !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kRSA)))
- {
- ret=ssl3_send_server_certificate(s);
-@@ -449,6 +452,7 @@ int ssl3_accept(SSL *s)
- case SSL3_ST_SW_KEY_EXCH_A:
- case SSL3_ST_SW_KEY_EXCH_B:
- alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
-+ alg_a = s->s3->tmp.new_cipher->algorithm_auth;
-
- /* clear this, it may get reset by
- * send_server_key_exchange */
-@@ -478,10 +482,12 @@ int ssl3_accept(SSL *s)
- * public key for key exchange.
- */
- if (0
-- /* PSK: send ServerKeyExchange if PSK identity
-- * hint if provided */
-+ /* PSK: send ServerKeyExchange if either:
-+ * - PSK identity hint is provided, or
-+ * - the key exchange is kEECDH.
-+ */
- #ifndef OPENSSL_NO_PSK
-- || ((alg_k & SSL_kPSK) && s->ctx->psk_identity_hint)
-+ || ((alg_a & SSL_aPSK) && ((alg_k & SSL_kEECDH) || s->ctx->psk_identity_hint))
- #endif
- #ifndef OPENSSL_NO_SRP
- /* SRP: send ServerKeyExchange */
-@@ -1658,7 +1664,8 @@ int ssl3_send_server_key_exchange(SSL *s)
- const EVP_MD *md = NULL;
- unsigned char *p,*d;
- int al,i;
-- unsigned long type;
-+ unsigned long alg_k;
-+ unsigned long alg_a;
- int n;
- CERT *cert;
- BIGNUM *r[4];
-@@ -1669,15 +1676,25 @@ int ssl3_send_server_key_exchange(SSL *s)
- EVP_MD_CTX_init(&md_ctx);
- if (s->state == SSL3_ST_SW_KEY_EXCH_A)
- {
-- type=s->s3->tmp.new_cipher->algorithm_mkey;
-+ alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
-+ alg_a=s->s3->tmp.new_cipher->algorithm_auth;
- cert=s->cert;
-
- buf=s->init_buf;
-
- r[0]=r[1]=r[2]=r[3]=NULL;
- n=0;
-+#ifndef OPENSSL_NO_PSK
-+ if (alg_a & SSL_aPSK)
-+ {
-+ /* size for PSK identity hint */
-+ n+=2;
-+ if (s->ctx->psk_identity_hint)
-+ n+=strlen(s->ctx->psk_identity_hint);
-+ }
-+#endif /* !OPENSSL_NO_PSK */
- #ifndef OPENSSL_NO_RSA
-- if (type & SSL_kRSA)
-+ if (alg_k & SSL_kRSA)
- {
- rsa=cert->rsa_tmp;
- if ((rsa == NULL) && (s->cert->rsa_tmp_cb != NULL))
-@@ -1704,10 +1721,9 @@ int ssl3_send_server_key_exchange(SSL *s)
- r[1]=rsa->e;
- s->s3->tmp.use_rsa_tmp=1;
- }
-- else
- #endif
- #ifndef OPENSSL_NO_DH
-- if (type & SSL_kEDH)
-+ else if (alg_k & SSL_kEDH)
- {
- dhp=cert->dh_tmp;
- if ((dhp == NULL) && (s->cert->dh_tmp_cb != NULL))
-@@ -1760,10 +1776,9 @@ int ssl3_send_server_key_exchange(SSL *s)
- r[1]=dh->g;
- r[2]=dh->pub_key;
- }
-- else
- #endif
- #ifndef OPENSSL_NO_ECDH
-- if (type & SSL_kEECDH)
-+ else if (alg_k & SSL_kEECDH)
- {
- const EC_GROUP *group;
-
-@@ -1876,7 +1891,7 @@ int ssl3_send_server_key_exchange(SSL *s)
- * to encode the entire ServerECDHParams
- * structure.
- */
-- n = 4 + encodedlen;
-+ n += 4 + encodedlen;
-
- /* We'll generate the serverKeyExchange message
- * explicitly so we can set these to NULLs
-@@ -1886,18 +1901,9 @@ int ssl3_send_server_key_exchange(SSL *s)
- r[2]=NULL;
- r[3]=NULL;
- }
-- else
- #endif /* !OPENSSL_NO_ECDH */
--#ifndef OPENSSL_NO_PSK
-- if (type & SSL_kPSK)
-- {
-- /* reserve size for record length and PSK identity hint*/
-- n+=2+strlen(s->ctx->psk_identity_hint);
-- }
-- else
--#endif /* !OPENSSL_NO_PSK */
- #ifndef OPENSSL_NO_SRP
-- if (type & SSL_kSRP)
-+ else if (alg_k & SSL_kSRP)
- {
- if ((s->srp_ctx.N == NULL) ||
- (s->srp_ctx.g == NULL) ||
-@@ -1912,8 +1918,8 @@ int ssl3_send_server_key_exchange(SSL *s)
- r[2]=s->srp_ctx.s;
- r[3]=s->srp_ctx.B;
- }
-- else
- #endif
-+ else if (!(alg_k & SSL_kPSK))
- {
- al=SSL_AD_HANDSHAKE_FAILURE;
- SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
-@@ -1923,15 +1929,16 @@ int ssl3_send_server_key_exchange(SSL *s)
- {
- nr[i]=BN_num_bytes(r[i]);
- #ifndef OPENSSL_NO_SRP
-- if ((i == 2) && (type & SSL_kSRP))
-+ if ((i == 2) && (alg_k & SSL_kSRP))
- n+=1+nr[i];
- else
- #endif
- n+=2+nr[i];
- }
-
-- if (!(s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL|SSL_aSRP))
-- && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
-+ if (!(alg_a & (SSL_aNULL|SSL_aSRP))
-+ /* Among PSK ciphersuites only RSA uses a certificate */
-+ && !((alg_a & SSL_aPSK) && !(alg_k & SSL_kRSA)))
- {
- if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher,&md))
- == NULL)
-@@ -1958,7 +1965,7 @@ int ssl3_send_server_key_exchange(SSL *s)
- for (i=0; i < 4 && r[i] != NULL; i++)
- {
- #ifndef OPENSSL_NO_SRP
-- if ((i == 2) && (type & SSL_kSRP))
-+ if ((i == 2) && (alg_k & SSL_kSRP))
- {
- *p = nr[i];
- p++;
-@@ -1970,8 +1977,32 @@ int ssl3_send_server_key_exchange(SSL *s)
- p+=nr[i];
- }
-
-+/* Note: ECDHE PSK ciphersuites use SSL_kEECDH and SSL_aPSK.
-+ * When one of them is used, the server key exchange record needs to have both
-+ * the psk_identity_hint and the ServerECDHParams. */
-+#ifndef OPENSSL_NO_PSK
-+ if (alg_a & SSL_aPSK)
-+ {
-+ if (s->ctx->psk_identity_hint)
-+ {
-+ /* copy PSK identity hint */
-+ s2n(strlen(s->ctx->psk_identity_hint), p);
-+ strncpy((char *)p, s->ctx->psk_identity_hint, strlen(s->ctx->psk_identity_hint));
-+ p+=strlen(s->ctx->psk_identity_hint);
-+ }
-+ else
-+ {
-+ /* No identity hint is provided. */
-+ *p = 0;
-+ p += 1;
-+ *p = 0;
-+ p += 1;
-+ }
-+ }
-+#endif /* OPENSSL_NO_PSK */
-+
- #ifndef OPENSSL_NO_ECDH
-- if (type & SSL_kEECDH)
-+ if (alg_k & SSL_kEECDH)
- {
- /* XXX: For now, we only support named (not generic) curves.
- * In this situation, the serverKeyExchange message has:
-@@ -1994,17 +2025,7 @@ int ssl3_send_server_key_exchange(SSL *s)
- encodedPoint = NULL;
- p += encodedlen;
- }
--#endif
--
--#ifndef OPENSSL_NO_PSK
-- if (type & SSL_kPSK)
-- {
-- /* copy PSK identity hint */
-- s2n(strlen(s->ctx->psk_identity_hint), p);
-- strncpy((char *)p, s->ctx->psk_identity_hint, strlen(s->ctx->psk_identity_hint));
-- p+=strlen(s->ctx->psk_identity_hint);
-- }
--#endif
-+#endif /* OPENSSL_NO_ECDH */
-
- /* not anonymous */
- if (pkey != NULL)
-@@ -2041,7 +2062,7 @@ int ssl3_send_server_key_exchange(SSL *s)
- n+=u+2;
- }
- else
--#endif
-+#endif /* OPENSSL_NO_RSA */
- if (md)
- {
- /* For TLS1.2 and later send signature
-@@ -2215,6 +2236,7 @@ int ssl3_get_client_key_exchange(SSL *s)
- int i,al,ok;
- long n;
- unsigned long alg_k;
-+ unsigned long alg_a;
- unsigned char *p;
- #ifndef OPENSSL_NO_RSA
- RSA *rsa=NULL;
-@@ -2232,7 +2254,11 @@ int ssl3_get_client_key_exchange(SSL *s)
- EC_KEY *srvr_ecdh = NULL;
- EVP_PKEY *clnt_pub_pkey = NULL;
- EC_POINT *clnt_ecpoint = NULL;
-- BN_CTX *bn_ctx = NULL;
-+ BN_CTX *bn_ctx = NULL;
-+#ifndef OPENSSL_NO_PSK
-+ unsigned int psk_len = 0;
-+ unsigned char psk[PSK_MAX_PSK_LEN];
-+#endif /* OPENSSL_NO_PSK */
- #endif
-
- n=s->method->ssl_get_message(s,
-@@ -2246,7 +2272,106 @@ int ssl3_get_client_key_exchange(SSL *s)
- p=(unsigned char *)s->init_msg;
-
- alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
-+ alg_a=s->s3->tmp.new_cipher->algorithm_auth;
-+
-+#ifndef OPENSSL_NO_PSK
-+ if (alg_a & SSL_aPSK)
-+ {
-+ unsigned char *t = NULL;
-+ unsigned char pre_ms[PSK_MAX_PSK_LEN*2+4];
-+ unsigned int pre_ms_len = 0;
-+ int psk_err = 1;
-+ char tmp_id[PSK_MAX_IDENTITY_LEN+1];
-+
-+ al=SSL_AD_HANDSHAKE_FAILURE;
-+
-+ n2s(p, i);
-+ if (n != i+2 && !(alg_k & SSL_kEECDH))
-+ {
-+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
-+ SSL_R_LENGTH_MISMATCH);
-+ goto psk_err;
-+ }
-+ if (i > PSK_MAX_IDENTITY_LEN)
-+ {
-+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
-+ SSL_R_DATA_LENGTH_TOO_LONG);
-+ goto psk_err;
-+ }
-+ if (s->psk_server_callback == NULL)
-+ {
-+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
-+ SSL_R_PSK_NO_SERVER_CB);
-+ goto psk_err;
-+ }
-+
-+ /* Create guaranteed NUL-terminated identity
-+ * string for the callback */
-+ memcpy(tmp_id, p, i);
-+ memset(tmp_id+i, 0, PSK_MAX_IDENTITY_LEN+1-i);
-+ psk_len = s->psk_server_callback(s, tmp_id, psk, sizeof(psk));
-
-+ if (psk_len > PSK_MAX_PSK_LEN)
-+ {
-+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
-+ ERR_R_INTERNAL_ERROR);
-+ goto psk_err;
-+ }
-+ else if (psk_len == 0)
-+ {
-+ /* PSK related to the given identity not found */
-+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
-+ SSL_R_PSK_IDENTITY_NOT_FOUND);
-+ al=SSL_AD_UNKNOWN_PSK_IDENTITY;
-+ goto psk_err;
-+ }
-+ if (!(alg_k & SSL_kEECDH))
-+ {
-+ /* Create the shared secret now if we're not using ECDHE-PSK.*/
-+ pre_ms_len=2+psk_len+2+psk_len;
-+ t = pre_ms;
-+ s2n(psk_len, t);
-+ memset(t, 0, psk_len);
-+ t+=psk_len;
-+ s2n(psk_len, t);
-+ memcpy(t, psk, psk_len);
-+
-+ s->session->master_key_length=
-+ s->method->ssl3_enc->generate_master_secret(s,
-+ s->session->master_key, pre_ms, pre_ms_len);
-+ }
-+ if (s->session->psk_identity != NULL)
-+ OPENSSL_free(s->session->psk_identity);
-+ s->session->psk_identity = BUF_strdup(tmp_id);
-+ OPENSSL_cleanse(tmp_id, PSK_MAX_IDENTITY_LEN+1);
-+ if (s->session->psk_identity == NULL)
-+ {
-+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
-+ ERR_R_MALLOC_FAILURE);
-+ goto psk_err;
-+ }
-+
-+ if (s->session->psk_identity_hint != NULL)
-+ OPENSSL_free(s->session->psk_identity_hint);
-+ s->session->psk_identity_hint = BUF_strdup(s->ctx->psk_identity_hint);
-+ if (s->ctx->psk_identity_hint != NULL &&
-+ s->session->psk_identity_hint == NULL)
-+ {
-+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
-+ ERR_R_MALLOC_FAILURE);
-+ goto psk_err;
-+ }
-+
-+ p += i;
-+ n -= (i + 2);
-+ psk_err = 0;
-+ psk_err:
-+ OPENSSL_cleanse(pre_ms, sizeof(pre_ms));
-+ if (psk_err != 0)
-+ goto f_err;
-+ }
-+#endif /* OPENSSL_NO_PSK */
-+ if (0) {}
- #ifndef OPENSSL_NO_RSA
- if (alg_k & SSL_kRSA)
- {
-@@ -2410,10 +2535,9 @@ int ssl3_get_client_key_exchange(SSL *s)
- p,sizeof(rand_premaster_secret));
- OPENSSL_cleanse(p,sizeof(rand_premaster_secret));
- }
-- else
- #endif
- #ifndef OPENSSL_NO_DH
-- if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
-+ else if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
- {
- n2s(p,i);
- if (n != i+2)
-@@ -2474,10 +2598,9 @@ int ssl3_get_client_key_exchange(SSL *s)
- s->session->master_key,p,i);
- OPENSSL_cleanse(p,i);
- }
-- else
- #endif
- #ifndef OPENSSL_NO_KRB5
-- if (alg_k & SSL_kKRB5)
-+ else if (alg_k & SSL_kKRB5)
- {
- krb5_error_code krb5rc;
- krb5_data enc_ticket;
-@@ -2666,17 +2789,20 @@ int ssl3_get_client_key_exchange(SSL *s)
- ** if (s->kssl_ctx) s->kssl_ctx = NULL;
- */
- }
-- else
- #endif /* OPENSSL_NO_KRB5 */
--
- #ifndef OPENSSL_NO_ECDH
-- if (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe))
-+ else if (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe))
- {
- int ret = 1;
- int field_size = 0;
- const EC_KEY *tkey;
- const EC_GROUP *group;
- const BIGNUM *priv_key;
-+#ifndef OPENSSL_NO_PSK
-+ unsigned char *pre_ms;
-+ unsigned int pre_ms_len;
-+ unsigned char *t;
-+#endif /* OPENSSL_NO_PSK */
-
- /* initialize structures for server's ECDH key pair */
- if ((srvr_ecdh = EC_KEY_new()) == NULL)
-@@ -2772,7 +2898,7 @@ int ssl3_get_client_key_exchange(SSL *s)
- }
-
- /* Get encoded point length */
-- i = *p;
-+ i = *p;
- p += 1;
- if (n != 1 + i)
- {
-@@ -2814,221 +2940,145 @@ int ssl3_get_client_key_exchange(SSL *s)
- EC_KEY_free(srvr_ecdh);
- BN_CTX_free(bn_ctx);
- EC_KEY_free(s->s3->tmp.ecdh);
-- s->s3->tmp.ecdh = NULL;
-+ s->s3->tmp.ecdh = NULL;
-
-- /* Compute the master secret */
-- s->session->master_key_length = s->method->ssl3_enc-> \
-- generate_master_secret(s, s->session->master_key, p, i);
--
-- OPENSSL_cleanse(p, i);
-- return (ret);
-- }
-- else
--#endif
- #ifndef OPENSSL_NO_PSK
-- if (alg_k & SSL_kPSK)
-+ /* ECDHE PSK ciphersuites from RFC 5489 */
-+ if ((alg_a & SSL_aPSK) && psk_len != 0)
- {
-- unsigned char *t = NULL;
-- unsigned char psk_or_pre_ms[PSK_MAX_PSK_LEN*2+4];
-- unsigned int pre_ms_len = 0, psk_len = 0;
-- int psk_err = 1;
-- char tmp_id[PSK_MAX_IDENTITY_LEN+1];
--
-- al=SSL_AD_HANDSHAKE_FAILURE;
--
-- n2s(p,i);
-- if (n != i+2)
-- {
-- SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
-- SSL_R_LENGTH_MISMATCH);
-- goto psk_err;
-- }
-- if (i > PSK_MAX_IDENTITY_LEN)
-- {
-- SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
-- SSL_R_DATA_LENGTH_TOO_LONG);
-- goto psk_err;
-- }
-- if (s->psk_server_callback == NULL)
-- {
-- SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
-- SSL_R_PSK_NO_SERVER_CB);
-- goto psk_err;
-- }
--
-- /* Create guaranteed NULL-terminated identity
-- * string for the callback */
-- memcpy(tmp_id, p, i);
-- memset(tmp_id+i, 0, PSK_MAX_IDENTITY_LEN+1-i);
-- psk_len = s->psk_server_callback(s, tmp_id,
-- psk_or_pre_ms, sizeof(psk_or_pre_ms));
-- OPENSSL_cleanse(tmp_id, PSK_MAX_IDENTITY_LEN+1);
--
-- if (psk_len > PSK_MAX_PSK_LEN)
-- {
-- SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
-- ERR_R_INTERNAL_ERROR);
-- goto psk_err;
-- }
-- else if (psk_len == 0)
-- {
-- /* PSK related to the given identity not found */
-- SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
-- SSL_R_PSK_IDENTITY_NOT_FOUND);
-- al=SSL_AD_UNKNOWN_PSK_IDENTITY;
-- goto psk_err;
-- }
--
-- /* create PSK pre_master_secret */
-- pre_ms_len=2+psk_len+2+psk_len;
-- t = psk_or_pre_ms;
-- memmove(psk_or_pre_ms+psk_len+4, psk_or_pre_ms, psk_len);
-- s2n(psk_len, t);
-- memset(t, 0, psk_len);
-- t+=psk_len;
-- s2n(psk_len, t);
--
-- if (s->session->psk_identity != NULL)
-- OPENSSL_free(s->session->psk_identity);
-- s->session->psk_identity = BUF_strdup((char *)p);
-- if (s->session->psk_identity == NULL)
-- {
-- SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
-- ERR_R_MALLOC_FAILURE);
-- goto psk_err;
-- }
--
-- if (s->session->psk_identity_hint != NULL)
-- OPENSSL_free(s->session->psk_identity_hint);
-- s->session->psk_identity_hint = BUF_strdup(s->ctx->psk_identity_hint);
-- if (s->ctx->psk_identity_hint != NULL &&
-- s->session->psk_identity_hint == NULL)
-+ pre_ms_len = 2+i+2+psk_len;
-+ pre_ms = OPENSSL_malloc(pre_ms_len);
-+ if (pre_ms == NULL)
- {
- SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
- ERR_R_MALLOC_FAILURE);
-- goto psk_err;
-+ goto err;
- }
--
-- s->session->master_key_length=
-- s->method->ssl3_enc->generate_master_secret(s,
-- s->session->master_key, psk_or_pre_ms, pre_ms_len);
-- psk_err = 0;
-- psk_err:
-- OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms));
-- if (psk_err != 0)
-- goto f_err;
-+ memset(pre_ms, 0, pre_ms_len);
-+ t = pre_ms;
-+ s2n(i, t);
-+ memcpy(t, p, i);
-+ t += i;
-+ s2n(psk_len, t);
-+ memcpy(t, psk, psk_len);
-+ s->session->master_key_length = s->method->ssl3_enc \
-+ -> generate_master_secret(s,
-+ s->session->master_key, pre_ms, pre_ms_len);
-+ OPENSSL_cleanse(pre_ms, pre_ms_len);
-+ OPENSSL_free(pre_ms);
- }
-- else
--#endif
--#ifndef OPENSSL_NO_SRP
-- if (alg_k & SSL_kSRP)
-+#endif /* OPENSSL_NO_PSK */
-+ if (!(alg_a & SSL_aPSK))
- {
-- int param_len;
--
-- n2s(p,i);
-- param_len=i+2;
-- if (param_len > n)
-- {
-- al=SSL_AD_DECODE_ERROR;
-- SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_SRP_A_LENGTH);
-- goto f_err;
-- }
-- if (!(s->srp_ctx.A=BN_bin2bn(p,i,NULL)))
-- {
-- SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,ERR_R_BN_LIB);
-- goto err;
-- }
-- if (BN_ucmp(s->srp_ctx.A, s->srp_ctx.N) >= 0
-- || BN_is_zero(s->srp_ctx.A))
-- {
-- al=SSL_AD_ILLEGAL_PARAMETER;
-- SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_SRP_PARAMETERS);
-- goto f_err;
-- }
-- if (s->session->srp_username != NULL)
-- OPENSSL_free(s->session->srp_username);
-- s->session->srp_username = BUF_strdup(s->srp_ctx.login);
-- if (s->session->srp_username == NULL)
-- {
-- SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
-- ERR_R_MALLOC_FAILURE);
-- goto err;
-- }
-+ /* Compute the master secret */
-+ s->session->master_key_length = s->method->ssl3_enc \
-+ -> generate_master_secret(s,
-+ s->session->master_key, p, i);
-+ }
-
-- if ((s->session->master_key_length = SRP_generate_server_master_secret(s,s->session->master_key))<0)
-- {
-- SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
-- goto err;
-- }
-+ OPENSSL_cleanse(p, i);
-+ }
-+#endif
-+#ifndef OPENSSL_NO_SRP
-+ else if (alg_k & SSL_kSRP)
-+ {
-+ int param_len;
-
-- p+=i;
-+ n2s(p,i);
-+ param_len=i+2;
-+ if (param_len > n)
-+ {
-+ al=SSL_AD_DECODE_ERROR;
-+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_SRP_A_LENGTH);
-+ goto f_err;
-+ }
-+ if (!(s->srp_ctx.A=BN_bin2bn(p,i,NULL)))
-+ {
-+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,ERR_R_BN_LIB);
-+ goto err;
-+ }
-+ if (s->session->srp_username != NULL)
-+ OPENSSL_free(s->session->srp_username);
-+ s->session->srp_username = BUF_strdup(s->srp_ctx.login);
-+ if (s->session->srp_username == NULL)
-+ {
-+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
-+ ERR_R_MALLOC_FAILURE);
-+ goto err;
- }
-- else
--#endif /* OPENSSL_NO_SRP */
-- if (alg_k & SSL_kGOST)
-- {
-- int ret = 0;
-- EVP_PKEY_CTX *pkey_ctx;
-- EVP_PKEY *client_pub_pkey = NULL, *pk = NULL;
-- unsigned char premaster_secret[32], *start;
-- size_t outlen=32, inlen;
-- unsigned long alg_a;
-- int Ttag, Tclass;
-- long Tlen;
--
-- /* Get our certificate private key*/
-- alg_a = s->s3->tmp.new_cipher->algorithm_auth;
-- if (alg_a & SSL_aGOST94)
-- pk = s->cert->pkeys[SSL_PKEY_GOST94].privatekey;
-- else if (alg_a & SSL_aGOST01)
-- pk = s->cert->pkeys[SSL_PKEY_GOST01].privatekey;
-
-- pkey_ctx = EVP_PKEY_CTX_new(pk,NULL);
-- EVP_PKEY_decrypt_init(pkey_ctx);
-- /* If client certificate is present and is of the same type, maybe
-- * use it for key exchange. Don't mind errors from
-- * EVP_PKEY_derive_set_peer, because it is completely valid to use
-- * a client certificate for authorization only. */
-- client_pub_pkey = X509_get_pubkey(s->session->peer);
-- if (client_pub_pkey)
-- {
-- if (EVP_PKEY_derive_set_peer(pkey_ctx, client_pub_pkey) <= 0)
-- ERR_clear_error();
-- }
-- /* Decrypt session key */
-- if (ASN1_get_object((const unsigned char **)&p, &Tlen, &Ttag, &Tclass, n) != V_ASN1_CONSTRUCTED ||
-- Ttag != V_ASN1_SEQUENCE ||
-- Tclass != V_ASN1_UNIVERSAL)
-- {
-- SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED);
-- goto gerr;
-- }
-- start = p;
-- inlen = Tlen;
-- if (EVP_PKEY_decrypt(pkey_ctx,premaster_secret,&outlen,start,inlen) <=0)
-+ if ((s->session->master_key_length = SRP_generate_server_master_secret(s,s->session->master_key))<0)
-+ {
-+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
-+ goto err;
-+ }
-
-- {
-- SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED);
-- goto gerr;
-- }
-- /* Generate master secret */
-- s->session->master_key_length=
-- s->method->ssl3_enc->generate_master_secret(s,
-- s->session->master_key,premaster_secret,32);
-- /* Check if pubkey from client certificate was used */
-- if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2, NULL) > 0)
-- ret = 2;
-- else
-- ret = 1;
-- gerr:
-- EVP_PKEY_free(client_pub_pkey);
-- EVP_PKEY_CTX_free(pkey_ctx);
-- if (ret)
-- return ret;
-- else
-- goto err;
-+ p+=i;
-+ }
-+#endif /* OPENSSL_NO_SRP */
-+ else if (alg_k & SSL_kGOST)
-+ {
-+ int ret = 0;
-+ EVP_PKEY_CTX *pkey_ctx;
-+ EVP_PKEY *client_pub_pkey = NULL, *pk = NULL;
-+ unsigned char premaster_secret[32], *start;
-+ size_t outlen=32, inlen;
-+ unsigned long alg_a;
-+ int Ttag, Tclass;
-+ long Tlen;
-+
-+ /* Get our certificate private key*/
-+ alg_a = s->s3->tmp.new_cipher->algorithm_auth;
-+ if (alg_a & SSL_aGOST94)
-+ pk = s->cert->pkeys[SSL_PKEY_GOST94].privatekey;
-+ else if (alg_a & SSL_aGOST01)
-+ pk = s->cert->pkeys[SSL_PKEY_GOST01].privatekey;
-+
-+ pkey_ctx = EVP_PKEY_CTX_new(pk,NULL);
-+ EVP_PKEY_decrypt_init(pkey_ctx);
-+ /* If client certificate is present and is of the same type, maybe
-+ * use it for key exchange. Don't mind errors from
-+ * EVP_PKEY_derive_set_peer, because it is completely valid to use
-+ * a client certificate for authorization only. */
-+ client_pub_pkey = X509_get_pubkey(s->session->peer);
-+ if (client_pub_pkey)
-+ {
-+ if (EVP_PKEY_derive_set_peer(pkey_ctx, client_pub_pkey) <= 0)
-+ ERR_clear_error();
-+ }
-+ /* Decrypt session key */
-+ if (ASN1_get_object((const unsigned char **)&p, &Tlen, &Ttag, &Tclass, n) != V_ASN1_CONSTRUCTED ||
-+ Ttag != V_ASN1_SEQUENCE ||
-+ Tclass != V_ASN1_UNIVERSAL)
-+ {
-+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED);
-+ goto gerr;
-+ }
-+ start = p;
-+ inlen = Tlen;
-+ if (EVP_PKEY_decrypt(pkey_ctx,premaster_secret,&outlen,start,inlen) <=0)
-+ {
-+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED);
-+ goto gerr;
- }
-+ /* Generate master secret */
-+ s->session->master_key_length=
-+ s->method->ssl3_enc->generate_master_secret(s,
-+ s->session->master_key,premaster_secret,32);
-+ /* Check if pubkey from client certificate was used */
-+ if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2, NULL) > 0)
-+ ret = 2;
-+ else
-+ ret = 1;
-+ gerr:
-+ EVP_PKEY_free(client_pub_pkey);
-+ EVP_PKEY_CTX_free(pkey_ctx);
-+ if (ret)
-+ return ret;
- else
-+ goto err;
-+ }
-+ else if (!(alg_k & SSL_kPSK))
- {
- al=SSL_AD_HANDSHAKE_FAILURE;
- SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
-diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
-index 0fda4ca..6c57d2a 100644
---- a/ssl/ssl_lib.c
-+++ b/ssl/ssl_lib.c
-@@ -1424,7 +1424,7 @@ int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p,
- #endif /* OPENSSL_NO_KRB5 */
- #ifndef OPENSSL_NO_PSK
- /* with PSK there must be client callback set */
-- if (((c->algorithm_mkey & SSL_kPSK) || (c->algorithm_auth & SSL_aPSK)) &&
-+ if ((c->algorithm_auth & SSL_aPSK) &&
- s->psk_client_callback == NULL)
- continue;
- #endif /* OPENSSL_NO_PSK */
-diff --git a/ssl/tls1.h b/ssl/tls1.h
-index 9e035fb..3e6b7c7 100644
---- a/ssl/tls1.h
-+++ b/ssl/tls1.h
-@@ -536,6 +536,10 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
- #define TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305 0x0300CC14
- #define TLS1_CK_DHE_RSA_CHACHA20_POLY1305 0x0300CC15
-
-+/* ECDHE PSK ciphersuites from RFC 5489 */
-+#define TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA256 0x0300C037
-+#define TLS1_CK_ECDHE_PSK_WITH_AES_256_CBC_SHA384 0x0300C038
-+
- /* XXX
- * Inconsistency alert:
- * The OpenSSL names of ciphers with ephemeral DH here include the string
-@@ -691,6 +698,10 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
- #define TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 "ECDHE-ECDSA-CHACHA20-POLY1305"
- #define TLS1_TXT_DHE_RSA_WITH_CHACHA20_POLY1305 "DHE-RSA-CHACHA20-POLY1305"
-
-+/* ECDHE PSK ciphersuites from RFC 5489 */
-+#define TLS1_TXT_ECDHE_PSK_WITH_AES_128_CBC_SHA256 "ECDHE-PSK-WITH-AES-128-CBC-SHA256"
-+#define TLS1_TXT_ECDHE_PSK_WITH_AES_256_CBC_SHA384 "ECDHE-PSK-WITH-AES-256-CBC-SHA384"
-+
- #define TLS_CT_RSA_SIGN 1
- #define TLS_CT_DSS_SIGN 2
- #define TLS_CT_RSA_FIXED_DH 3
-2.0.0.526.g5318336
-