Implement ECDHE-PSK-WITH-AES-128-GCM-SHA256.
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index af664de..48d4a55 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -344,9 +344,10 @@
 				}
 #endif
 			/* Check if it is anon DH/ECDH */
-			/* or PSK */
+			/* or non-RSA PSK */
 			if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) &&
-			    !(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;
@@ -1404,7 +1405,7 @@
 		   omitted if no identity hint is sent. Set
 		   session->sess_cert anyway to avoid problems
 		   later.*/
-		if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)
+		if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_aPSK)
 			{
 			s->session->sess_cert=ssl_sess_cert_new();
 			if (s->ctx->psk_identity_hint)
@@ -1452,50 +1453,55 @@
 	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];
 
 		al=SSL_AD_HANDSHAKE_FAILURE;
 		n2s(p,i);
 		param_len=i+2;
-		/* 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)
-			{
-			OPENSSL_PUT_ERROR(SSL, ssl3_get_key_exchange, SSL_R_DATA_LENGTH_TOO_LONG);
-			goto f_err;
-			}
-		if (param_len > n)
-			{
-			al=SSL_AD_DECODE_ERROR;
-			OPENSSL_PUT_ERROR(SSL, ssl3_get_key_exchange, SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH);
-			goto f_err;
-			}
-		/* 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)
+		if (s->ctx->psk_identity_hint)
 			OPENSSL_free(s->ctx->psk_identity_hint);
-		s->ctx->psk_identity_hint = BUF_strdup(tmp_id_hint);
-		if (s->ctx->psk_identity_hint == NULL)
+		s->ctx->psk_identity_hint = NULL;
+		if (i != 0)
 			{
-			OPENSSL_PUT_ERROR(SSL, ssl3_get_key_exchange, ERR_R_MALLOC_FAILURE);
-			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)
+				{
+				OPENSSL_PUT_ERROR(SSL, ssl3_get_key_exchange, SSL_R_DATA_LENGTH_TOO_LONG);
+				goto f_err;
+				}
+			if (param_len > n)
+				{
+				al=SSL_AD_DECODE_ERROR;
+				OPENSSL_PUT_ERROR(SSL, ssl3_get_key_exchange, SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH);
+				goto f_err;
+				}
+			/* 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);
+			s->ctx->psk_identity_hint = BUF_strdup(tmp_id_hint);
+			if (s->ctx->psk_identity_hint == NULL)
+				{
+				OPENSSL_PUT_ERROR(SSL, 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_RSA
-	if (alg_k & SSL_kRSA)
+	else if (alg_k & SSL_kRSA)
 		{
 		if ((rsa=RSA_new()) == NULL)
 			{
@@ -1544,9 +1550,6 @@
 		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)
@@ -1735,14 +1738,14 @@
 		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;
 		OPENSSL_PUT_ERROR(SSL, 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 */
 
@@ -1832,8 +1835,9 @@
 		}
 	else
 		{
-		/* aNULL or kPSK do not need public keys */
-		if (!(alg_a & SSL_aNULL) && !(alg_k & SSL_kPSK))
+		if (!(alg_a & SSL_aNULL) &&
+			/* Among PSK ciphers only RSA_PSK needs a public key */
+			!((alg_a & SSL_aPSK) && !(alg_k & SSL_kRSA)))
 			{
 			/* Might be wrong key type, check it */
 			if (ssl3_check_cert_and_algorithm(s))
@@ -2254,8 +2258,9 @@
 int ssl3_send_client_key_exchange(SSL *s)
 	{
 	unsigned char *p;
-	int n;
+	int n = 0;
 	unsigned long alg_k;
+	unsigned long alg_a;
 #ifndef OPENSSL_NO_RSA
 	unsigned char *q;
 	EVP_PKEY *pkey=NULL;
@@ -2267,13 +2272,102 @@
 	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)
 		{
 		p = ssl_handshake_start(s);
 
 		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)
+			{
+			char identity[PSK_MAX_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)
+				{
+				OPENSSL_PUT_ERROR(SSL, 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, PSK_MAX_IDENTITY_LEN, psk, sizeof(psk));
+			if (psk_len > PSK_MAX_PSK_LEN)
+				{
+				OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_INTERNAL_ERROR);
+				goto psk_err;
+				}
+			else if (psk_len == 0)
+				{
+				OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, SSL_R_PSK_IDENTITY_NOT_FOUND);
+				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);
+				n = strlen(identity);
+				s2n(n, p);
+				memcpy(p, identity, n);
+				n += 2;
+				}
+
+			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)
+					{
+					OPENSSL_PUT_ERROR(SSL, 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)
+				{
+				OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_MALLOC_FAILURE);
+				goto psk_err;
+				}
+			psk_err = 0;
+		psk_err:
+			OPENSSL_cleanse(identity, PSK_MAX_IDENTITY_LEN);
+			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) {}
@@ -2438,13 +2532,19 @@
 			}
 #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
 
 			/* Did we send out the client's
 			 * ECDH share for use in premaster
@@ -2561,15 +2661,41 @@
 				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+psk_len+2+n;
+				pre_ms = OPENSSL_malloc(pre_ms_len);
+				if (pre_ms == NULL)
+					{
+					OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_MALLOC_FAILURE);
+					goto err;
+					}
+				memset(pre_ms, 0, pre_ms_len);
+				t = pre_ms;
+				s2n(psk_len, t);
+				memcpy(t, psk, psk_len);
+				t += psk_len;
+				s2n(n, t);
+				memcpy(t, p, n);
+				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;
@@ -2597,111 +2723,47 @@
 					}
 
 				/* 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);
 
-				*p = n; /* length of encoded point */
+				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 = 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)
 			{
 			OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, SSL_R_GOST_NOT_SUPPORTED);
 			goto err;
 			}
-#ifndef OPENSSL_NO_PSK
-		else if (alg_k & SSL_kPSK)
-			{
-			char identity[PSK_MAX_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)
-				{
-				OPENSSL_PUT_ERROR(SSL, 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, PSK_MAX_IDENTITY_LEN,
-				psk_or_pre_ms, sizeof(psk_or_pre_ms));
-			if (psk_len > PSK_MAX_PSK_LEN)
-				{
-				OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_INTERNAL_ERROR);
-				goto psk_err;
-				}
-			else if (psk_len == 0)
-				{
-				OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, SSL_R_PSK_IDENTITY_NOT_FOUND);
-				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)
-				{
-				OPENSSL_PUT_ERROR(SSL, 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)
-				{
-				OPENSSL_PUT_ERROR(SSL, 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); 
-			n = strlen(identity);
-			s2n(n, p);
-			memcpy(p, identity, n);
-			n+=2;
-			psk_err = 0;
-		psk_err:
-			OPENSSL_cleanse(identity, PSK_MAX_IDENTITY_LEN);
-			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);
@@ -3028,7 +3090,7 @@
 	alg_a=s->s3->tmp.new_cipher->algorithm_auth;
 
 	/* we don't have a certificate */
-	if ((alg_a & (SSL_aNULL|SSL_aKRB5)) || (alg_k & SSL_kPSK))
+	if ((alg_a & (SSL_aNULL|SSL_aKRB5)) || ((alg_a & SSL_aPSK) && !(alg_k & SSL_kRSA)))
 		return(1);
 
 	sc=s->session->sess_cert;