Hi,

new version of the patch, adding also the PSK variants defined in RFC 
5487 (basically, SHA256 and SHA384 support for both plain PSK and RSA-PSK).

I also sketched up the support for the AES-GCM variants, but using them 
results in a crash inside s3_pkt.c. I'm still not sure what I'm doing 
wrong, but I've disabled the corresponding code...

Lastly: does it make sense for this patch to target master? Should it be 
targeting 1.0.2 instead?

Thanks,
-- 
Giuseppe D'Angelo | giuseppe.dang...@kdab.com | Software Engineer
KDAB (UK) Ltd., a KDAB Group company
Tel. UK +44-1738-450410, Sweden (HQ) +46-563-540090
KDAB - Qt Experts - Platform-independent software solutions

>From b3f71ae0386f8bbaba23e6263d752da6c7ef030a Mon Sep 17 00:00:00 2001
From: Giuseppe D'Angelo <giuseppe.dang...@kdab.com>
Date: Sat, 8 Nov 2014 20:44:23 +0100
Subject: [PATCH] Introduce TLS-RSA-PSK support

Build on the existing PSK support and introduce RSA-PSK
(cf. RFC 4279, 5487).
Based on the original patch by Christian J. Dietrich.

This work has been sponsored by Governikus GmbH & Co. KG.

PR: 2464
---
 CHANGES              |    3 +
 doc/apps/ciphers.pod |   12 +++
 ssl/s3_clnt.c        |  130 +++++++++++++++++++++++-----
 ssl/s3_lib.c         |  207 +++++++++++++++++++++++++++++++++++++++++++-
 ssl/s3_srvr.c        |  232 +++++++++++++++++++++++++++++++++++++++++++++++---
 ssl/ssl.h            |    4 +-
 ssl/ssl_ciph.c       |   16 ++--
 ssl/ssl_lib.c        |    6 ++
 ssl/ssl_locl.h       |    1 +
 ssl/tls1.h           |   36 ++++++++
 10 files changed, 610 insertions(+), 37 deletions(-)

diff --git a/CHANGES b/CHANGES
index d90febc..8b48914 100644
--- a/CHANGES
+++ b/CHANGES
@@ -303,6 +303,9 @@
      whose return value is often ignored. 
      [Steve Henson]
 
+  *) Support for TLS-RSA-PSK ciphersuites has been added.
+     [Giuseppe D'Angelo, Christian J. Dietrich]
+
  Changes between 1.0.1j and 1.0.2 [xx XXX xxxx]
 
    *) Tighten client-side session ticket handling during renegotiation:
diff --git a/doc/apps/ciphers.pod b/doc/apps/ciphers.pod
index c41a297..b1f4517 100644
--- a/doc/apps/ciphers.pod
+++ b/doc/apps/ciphers.pod
@@ -600,10 +600,22 @@ Note: these ciphers can also be used in SSL v3.
 
 =head2 Pre shared keying (PSK) cipheruites
 
+ TLS_RSA_PSK_WITH_RC4_128_SHA              RSA-PSK-RC4-SHA
+ TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA         RSA-PSK-3DES-EDE-CBC-SHA
+ TLS_RSA_PSK_WITH_AES_128_CBC_SHA          RSA-PSK-AES128-CBC-SHA
+ TLS_RSA_PSK_WITH_AES_256_CBC_SHA          RSA-PSK-AES256-CBC-SHA
+ TLS_RSA_PSK_WITH_AES_128_CBC_SHA256       RSA-PSK-AES128-CBC-SHA256
+ TLS_RSA_PSK_WITH_AES_256_CBC_SHA384       RSA-PSK-AES256-CBC-SHA384
+ TLS_RSA_PSK_WITH_AES_128_GCM_SHA256       RSA-PSK-AES128-GCM-SHA256
+ TLS_RSA_PSK_WITH_AES_256_GCM_SHA384       RSA-PSK-AES256-GCM-SHA384
  TLS_PSK_WITH_RC4_128_SHA                  PSK-RC4-SHA
  TLS_PSK_WITH_3DES_EDE_CBC_SHA             PSK-3DES-EDE-CBC-SHA
  TLS_PSK_WITH_AES_128_CBC_SHA              PSK-AES128-CBC-SHA
  TLS_PSK_WITH_AES_256_CBC_SHA              PSK-AES256-CBC-SHA
+ TLS_PSK_WITH_AES_128_CBC_SHA256           PSK-AES128-CBC-SHA256
+ TLS_PSK_WITH_AES_256_CBC_SHA384           PSK-AES256-CBC-SHA384
+ TLS_PSK_WITH_AES_128_GCM_SHA256           PSK-AES128-GCM-SHA256
+ TLS_PSK_WITH_AES_256_GCM_SHA384           PSK-AES256-GCM-SHA384
 
 =head2 Deprecated SSL v2.0 cipher suites.
 
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 68c00c5..bbcebcb 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -343,7 +343,7 @@ int ssl3_connect(SSL *s)
 				}
 #endif
 			/* Check if it is anon DH/ECDH, SRP auth */
-			/* or PSK */
+			/* or plain PSK */
 			if (!(s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL|SSL_aSRP)) &&
 			    !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
 				{
@@ -1417,9 +1417,9 @@ int ssl3_get_key_exchange(SSL *s)
 	if (s->s3->tmp.message_type != SSL3_MT_SERVER_KEY_EXCHANGE)
 		{
 #ifndef OPENSSL_NO_PSK
-		/* In plain PSK ciphersuite, ServerKeyExchange can be
+		/* In PSK ciphersuites, ServerKeyExchange can be
 		   omitted if no identity hint is sent. Set
-		   session->sess_cert anyway to avoid problems
+		   session->sess_cert for plain PSK anyway to avoid problems
 		   later.*/
 		if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)
 			{
@@ -1473,7 +1473,12 @@ int ssl3_get_key_exchange(SSL *s)
 	al=SSL_AD_DECODE_ERROR;
 
 #ifndef OPENSSL_NO_PSK
-	if (alg_k & SSL_kPSK)
+	/* handle PSK identity hint */
+	if (alg_k & (SSL_kPSK
+#ifndef OPENSSL_NO_RSA
+		     |SSL_kRSAPSK
+#endif
+		     ))
 		{
 		char tmp_id_hint[PSK_MAX_IDENTITY_LEN+1];
 
@@ -1650,7 +1655,11 @@ int ssl3_get_key_exchange(SSL *s)
 	else
 #endif /* !OPENSSL_NO_SRP */
 #ifndef OPENSSL_NO_RSA
-	if (alg_k & SSL_kRSA)
+	if (alg_k & (SSL_kRSA
+#ifndef OPENSSL_NO_PSK
+		     |SSL_kRSAPSK
+#endif
+		     ))
 		{
 		if ((rsa=RSA_new()) == NULL)
 			{
@@ -2061,8 +2070,16 @@ 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))
+		/* aNULL, aSRP, kPSK or kRSAPSK do not need public keys */
+		if (!(alg_a & (SSL_aNULL|SSL_aSRP))
+#ifndef OPENSSL_NO_PSK
+				&& !(alg_k & (SSL_kPSK
+#ifndef OPENSSL_NO_RSA
+					      |SSL_kRSAPSK
+#endif
+					      ))
+#endif
+				)
 			{
 			/* Might be wrong key type, check it */
 			if (ssl3_check_cert_and_algorithm(s))
@@ -3132,15 +3149,19 @@ int ssl3_send_client_key_exchange(SSL *s)
 			}
 #endif
 #ifndef OPENSSL_NO_PSK
-		else if (alg_k & SSL_kPSK)
+		else if (alg_k & SSL_kPSK
+#ifndef OPENSSL_NO_RSA
+			|| alg_k & SSL_kRSAPSK
+#endif
+			 )
 			{
 			/* 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 char *t = psk_or_pre_ms;
 			unsigned int pre_ms_len = 0, psk_len = 0;
 			int psk_err = 1;
 
@@ -3176,14 +3197,36 @@ int ssl3_send_client_key_exchange(SSL *s)
 					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 (alg_k & SSL_kPSK)
+				{
+				/* create PSK pre_master_secret */
+				pre_ms_len = 2+psk_len+2+psk_len;
+				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);
+				}
+#ifndef OPENSSL_NO_RSA
+			else if (alg_k & SSL_kRSAPSK)
+				{
+				const unsigned int pre_ms_prefix = 48;
+
+				pre_ms_len = 2 + 2 + 46 + 2 + psk_len;
+				memmove(psk_or_pre_ms + 52, psk_or_pre_ms, psk_len);
+				s2n(pre_ms_prefix, t);
+
+				psk_or_pre_ms[2] = s->client_version >> 8;
+				psk_or_pre_ms[3] = s->client_version & 0xff;
+				t += 2;
+
+				if (RAND_bytes(psk_or_pre_ms + 4, 46) <= 0)
+					goto psk_err;
+				t += 46;
+				s2n(psk_len, t);
+				}
+#endif
 
 			if (s->session->psk_identity_hint != NULL)
 				OPENSSL_free(s->session->psk_identity_hint);
@@ -3210,10 +3253,51 @@ int ssl3_send_client_key_exchange(SSL *s)
 				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);
+			p += identity_len;
+
 			n = 2 + identity_len;
+
+#ifndef OPENSSL_NO_RSA
+			if (alg_k & SSL_kRSAPSK)
+				{
+				RSA *rsa;
+				int enc_n;
+
+				if (s->session->sess_cert->peer_rsa_tmp != NULL)
+					{
+					rsa = s->session->sess_cert->peer_rsa_tmp;
+					}
+				else
+					{
+					pkey = X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
+					if ((pkey == NULL) ||
+							(pkey->type != EVP_PKEY_RSA) ||
+							(pkey->pkey.rsa == NULL))
+						{
+							SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+							goto psk_err;
+						}
+					rsa = pkey->pkey.rsa;
+					EVP_PKEY_free(pkey);
+					}
+
+				enc_n = RSA_public_encrypt(48, psk_or_pre_ms + 2, p + 2, rsa, RSA_PKCS1_PADDING);
+				if (enc_n <= 0)
+					{
+						SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, SSL_R_BAD_RSA_ENCRYPT);
+						goto psk_err;
+					}
+				n += enc_n;
+
+				s2n(enc_n, p);
+				n += 2;
+				}
+#endif
 			psk_err = 0;
+
 		psk_err:
 			OPENSSL_cleanse(identity, sizeof(identity));
 			OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms));
@@ -3625,7 +3709,11 @@ int ssl3_check_cert_and_algorithm(SSL *s)
 		}
 #endif
 #ifndef OPENSSL_NO_RSA
-	if ((alg_k & SSL_kRSA) &&
+	if ((alg_k & (SSL_kRSA
+#ifndef OPENSSL_NO_PSK
+	     |SSL_kRSAPSK
+#endif
+	     )) &&
 		!(has_bits(i,EVP_PK_RSA|EVP_PKT_ENC) || (rsa != NULL)))
 		{
 		SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_RSA_ENCRYPTING_CERT);
@@ -3658,7 +3746,11 @@ int ssl3_check_cert_and_algorithm(SSL *s)
 	if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && !has_bits(i,EVP_PKT_EXP))
 		{
 #ifndef OPENSSL_NO_RSA
-		if (alg_k & SSL_kRSA)
+		if (alg_k & (SSL_kRSA
+#ifndef OPENSSL_NO_PSK
+			     |SSL_kRSAPSK
+#endif
+			     ))
 			{
 			if (rsa == NULL
 			    || RSA_size(rsa)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher))
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index d670ff0..fb0f683 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -1715,6 +1715,73 @@ OPENSSL_GLOBAL const SSL_CIPHER ssl3_ciphers[]={
 	256,
 	256,
 	},
+
+#ifndef OPENSSL_NO_RSA
+	/* RSA-PSK ciphersuites from RFC4279 */
+	/* Cipher 92 */
+	{
+	1,
+	TLS1_TXT_RSA_PSK_WITH_RC4_128_SHA,
+	TLS1_CK_RSA_PSK_WITH_RC4_128_SHA,
+	SSL_kRSAPSK,
+	SSL_aRSA,
+	SSL_RC4,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_MEDIUM,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+
+	/* Cipher 93 */
+	{
+	1,
+	TLS1_TXT_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
+	TLS1_CK_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
+	SSL_kRSAPSK,
+	SSL_aRSA,
+	SSL_3DES,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	112,
+	168,
+	},
+
+	/* Cipher 94 */
+	{
+	1,
+	TLS1_TXT_RSA_PSK_WITH_AES_128_CBC_SHA,
+	TLS1_CK_RSA_PSK_WITH_AES_128_CBC_SHA,
+	SSL_kRSAPSK,
+	SSL_aRSA,
+	SSL_AES128,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	128,
+	128,
+	},
+
+	/* Cipher 95 */
+	{
+	1,
+	TLS1_TXT_RSA_PSK_WITH_AES_256_CBC_SHA,
+	TLS1_CK_RSA_PSK_WITH_AES_256_CBC_SHA,
+	SSL_kRSAPSK,
+	SSL_aRSA,
+	SSL_AES256,
+	SSL_SHA1,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+	256,
+	256,
+	},
+#endif  /* OPENSSL_NO_RSA */
 #endif  /* OPENSSL_NO_PSK */
 
 #ifndef OPENSSL_NO_SEED
@@ -2028,6 +2095,144 @@ OPENSSL_GLOBAL const SSL_CIPHER ssl3_ciphers[]={
 	},
 #endif
 
+#ifndef OPENSSL_NO_PSK
+	/* PSK ciphersuites from RFC5487 */
+
+#if 0 /* The GCM variants will crash into s3_pkt.c, need to debug that */
+	/* Cipher A8 */
+	{
+	1,
+	TLS1_TXT_PSK_WITH_AES_128_GCM_SHA256,
+	TLS1_CK_PSK_WITH_AES_128_GCM_SHA256,
+	SSL_kPSK,
+	SSL_aPSK,
+	SSL_AES128GCM,
+	SSL_SHA256,
+	SSL_TLSV1_2,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256,
+	128,
+	128,
+	},
+
+	/* Cipher A9 */
+	{
+	1,
+	TLS1_TXT_PSK_WITH_AES_256_GCM_SHA384,
+	TLS1_CK_PSK_WITH_AES_256_GCM_SHA384,
+	SSL_kPSK,
+	SSL_aPSK,
+	SSL_AES256GCM,
+	SSL_SHA384,
+	SSL_TLSV1_2,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384,
+	256,
+	256,
+	},
+
+#ifndef OPENSSL_NO_RSA
+	/* Cipher AC */
+	{
+	1,
+	TLS1_TXT_RSA_PSK_WITH_AES_128_GCM_SHA256,
+	TLS1_CK_RSA_PSK_WITH_AES_128_GCM_SHA256,
+	SSL_kRSAPSK,
+	SSL_aRSA,
+	SSL_AES128GCM,
+	SSL_SHA256,
+	SSL_TLSV1_2,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256,
+	128,
+	128,
+	},
+
+	/* Cipher AD */
+	{
+	1,
+	TLS1_TXT_RSA_PSK_WITH_AES_256_GCM_SHA384,
+	TLS1_CK_RSA_PSK_WITH_AES_256_GCM_SHA384,
+	SSL_kRSAPSK,
+	SSL_aRSA,
+	SSL_AES256GCM,
+	SSL_SHA384,
+	SSL_TLSV1_2,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384,
+	256,
+	256,
+	},
+#endif  /* OPENSSL_NO_RSA */
+#endif /* 0 */
+
+	/* Cipher AE */
+	{
+	1,
+	TLS1_TXT_PSK_WITH_AES_128_CBC_SHA256,
+	TLS1_CK_PSK_WITH_AES_128_CBC_SHA256,
+	SSL_kPSK,
+	SSL_aPSK,
+	SSL_AES128,
+	SSL_SHA256,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256,
+	128,
+	128,
+	},
+
+	/* Cipher AF */
+	{
+	1,
+	TLS1_TXT_PSK_WITH_AES_256_CBC_SHA384,
+	TLS1_CK_PSK_WITH_AES_256_CBC_SHA384,
+	SSL_kPSK,
+	SSL_aPSK,
+	SSL_AES256,
+	SSL_SHA384,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384,
+	256,
+	256,
+	},
+
+#ifndef OPENSSL_NO_RSA
+	/* Cipher B6 */
+	{
+	1,
+	TLS1_TXT_RSA_PSK_WITH_AES_128_CBC_SHA256,
+	TLS1_CK_RSA_PSK_WITH_AES_128_CBC_SHA256,
+	SSL_kRSAPSK,
+	SSL_aRSA,
+	SSL_AES128,
+	SSL_SHA256,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256,
+	128,
+	128,
+	},
+
+	/* Cipher B7 */
+	{
+	1,
+	TLS1_TXT_RSA_PSK_WITH_AES_256_CBC_SHA384,
+	TLS1_CK_RSA_PSK_WITH_AES_256_CBC_SHA384,
+	SSL_kRSAPSK,
+	SSL_aRSA,
+	SSL_AES256,
+	SSL_SHA384,
+	SSL_TLSV1,
+	SSL_NOT_EXP|SSL_HIGH,
+	SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384,
+	256,
+	256,
+	},
+#endif  /* OPENSSL_NO_RSA */
+#endif  /* OPENSSL_NO_PSK */
+
 #ifndef OPENSSL_NO_CAMELLIA
 	/* TLS 1.2 Camellia SHA-256 ciphersuites from RFC5932 */
 
@@ -4522,7 +4727,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_k & (SSL_kPSK|SSL_kRSAPSK)) && s->psk_server_callback == NULL)
 			continue;
 #endif /* OPENSSL_NO_PSK */
 
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
index bef055a..55d426a 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -467,7 +467,8 @@ int ssl3_accept(SSL *s)
 			/* only send if a DH key exchange, fortezza or
 			 * RSA but we have a sign only certificate
 			 *
-			 * PSK: may send PSK identity hints
+			 * PSK|RSAPSK: may send PSK identity hints.
+			 * Send ServerKeyExchange if PSK identity hint is provided.
 			 *
 			 * For ECC ciphersuites, we send a serverKeyExchange
 			 * message only if the cipher suite is either
@@ -476,10 +477,12 @@ int ssl3_accept(SSL *s)
 			 * public key for key exchange.
 			 */
 			if (s->s3->tmp.use_rsa_tmp
-			/* PSK: send ServerKeyExchange if PSK identity
-			 * hint if provided */
 #ifndef OPENSSL_NO_PSK
-			    || ((alg_k & SSL_kPSK) && s->ctx->psk_identity_hint)
+			    || ((alg_k & (SSL_kPSK
+#ifndef OPENSSL_NO_RSA
+					  |SSL_kRSAPSK
+#endif
+					  )) && s->ctx->psk_identity_hint)
 #endif
 #ifndef OPENSSL_NO_SRP
 			    /* SRP: send ServerKeyExchange */
@@ -525,9 +528,11 @@ int ssl3_accept(SSL *s)
 				(s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5) ||
 				/* don't request certificate for SRP auth */
 				(s->s3->tmp.new_cipher->algorithm_auth & SSL_aSRP)
-				/* With normal PSK Certificates and
+#ifndef OPENSSL_NO_PSK
+				/* With normal PSK, Certificates and
 				 * Certificate Requests are omitted */
 				|| (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
+#endif
 				{
 				/* no cert request */
 				skip=1;
@@ -1870,7 +1875,11 @@ int ssl3_send_server_key_exchange(SSL *s)
 		else 
 #endif /* !OPENSSL_NO_ECDH */
 #ifndef OPENSSL_NO_PSK
-			if (type & SSL_kPSK)
+			if (type & (SSL_kPSK
+#ifndef OPENSSL_NO_RSA
+				|SSL_kRSAPSK
+#endif
+				    ))
 				{
 				/* reserve size for record length and PSK identity hint*/
 				n+=2+strlen(s->ctx->psk_identity_hint);
@@ -1894,7 +1903,7 @@ int ssl3_send_server_key_exchange(SSL *s)
 			r[3]=s->srp_ctx.B;
 			}
 		else 
-#endif
+#endif /*! OPENSSL_NO_SRP */
 			{
 			al=SSL_AD_HANDSHAKE_FAILURE;
 			SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
@@ -1912,7 +1921,13 @@ int ssl3_send_server_key_exchange(SSL *s)
 			}
 
 		if (!(s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL|SSL_aSRP))
-			&& !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
+#ifndef OPENSSL_NO_PSK
+			&& !(s->s3->tmp.new_cipher->algorithm_mkey & (SSL_kPSK
+#ifndef OPENSSL_NO_RSA
+								      |SSL_kRSAPSK
+#endif
+								      )))
+#endif
 			{
 			if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher,&md))
 				== NULL)
@@ -1977,7 +1992,11 @@ int ssl3_send_server_key_exchange(SSL *s)
 #endif
 
 #ifndef OPENSSL_NO_PSK
-		if (type & SSL_kPSK)
+		if (type & (SSL_kPSK
+#ifndef OPENSSL_NO_RSA
+			    |SSL_kRSAPSK
+#endif
+			    ))
 			{
 			/* copy PSK identity hint */
 			s2n(strlen(s->ctx->psk_identity_hint), p); 
@@ -1992,7 +2011,11 @@ int ssl3_send_server_key_exchange(SSL *s)
 			/* n is the length of the params, they start at &(d[4])
 			 * and p points to the space at the end. */
 #ifndef OPENSSL_NO_RSA
-			if (pkey->type == EVP_PKEY_RSA && !SSL_USE_SIGALGS(s))
+			if (pkey->type == EVP_PKEY_RSA && !SSL_USE_SIGALGS(s)
+#ifndef OPENSSL_NO_PSK
+					&& !(type & SSL_kRSAPSK)
+#endif
+					)
 				{
 				q=md_buf;
 				j=0;
@@ -2878,8 +2901,195 @@ int ssl3_get_client_key_exchange(SSL *s)
 			if (psk_err != 0)
 				goto f_err;
 			}
-		else
+	else
 #endif
+#ifndef OPENSSL_NO_RSA
+#ifndef OPENSSL_NO_PSK
+		if (alg_k & SSL_kRSAPSK)
+			{
+			unsigned char rand_premaster_secret[SSL_MAX_MASTER_KEY_LENGTH];
+			int decrypt_len;
+			unsigned char decrypt_good, version_good;
+			unsigned char *orig_p = p;
+
+			unsigned int psk_len;
+
+			const unsigned int pre_master_secret_prefix = 48;
+			unsigned char psk_or_pre_ms[PSK_MAX_PSK_LEN * 2 + 4];
+			unsigned int pre_ms_len;
+			unsigned char *t = psk_or_pre_ms;
+
+			char identity[PSK_MAX_IDENTITY_LEN + 1];
+			int identity_len;
+
+			int epms_len;
+
+			int psk_err = 1;
+
+			/* No server callback? Bail out */
+			if (s->psk_server_callback == NULL)
+				{
+				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_PSK_NO_SERVER_CB);
+				goto f_err;
+				}
+
+			/* FIX THIS UP EAY EAY EAY EAY */
+			if (s->s3->tmp.use_rsa_tmp)
+				{
+				if ((s->cert != NULL) && (s->cert->rsa_tmp != NULL))
+					rsa=s->cert->rsa_tmp;
+				/* Don't do a callback because rsa_tmp should
+				 * be sent already */
+				if (rsa == NULL)
+					{
+					al=SSL_AD_HANDSHAKE_FAILURE;
+					SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_MISSING_TMP_RSA_PKEY);
+					goto f_err;
+					}
+				}
+			else
+				{
+				pkey=s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey;
+				if ((pkey == NULL) ||
+				    (pkey->type != EVP_PKEY_RSA) ||
+				    (pkey->pkey.rsa == NULL))
+					{
+					al=SSL_AD_HANDSHAKE_FAILURE;
+					SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_MISSING_RSA_CERTIFICATE);
+					goto f_err;
+					}
+				rsa=pkey->pkey.rsa;
+				}
+
+
+			/* Extract the PSK identity */
+			if (n < (2 + 2)) /* 2 bytes for the identity len, 2 bytes for the epms len */
+				{
+				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
+				goto f_err;
+				}
+
+			n2s(p, identity_len);
+			if (identity_len > PSK_MAX_IDENTITY_LEN)
+				{
+				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_DATA_LENGTH_TOO_LONG);
+				goto f_err;
+				}
+
+			if (n < (2 + identity_len + 2)) /* as above, plus the identity len */
+				{
+				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
+				goto f_err;
+				}
+
+			memset(identity, 0, sizeof(identity));
+			memcpy(identity, p, identity_len);
+			p += identity_len;
+
+			/* fill the pre master secret with random bytes */
+			if (RAND_pseudo_bytes(psk_or_pre_ms, sizeof(psk_or_pre_ms)) <= 0)
+				goto err;
+
+			/* read the psk (into the beginning of the psk_or_pre_ms buffer */
+			psk_len = s->psk_server_callback(s, identity, psk_or_pre_ms, sizeof(psk_or_pre_ms));
+
+			if (psk_len > PSK_MAX_PSK_LEN)
+				{
+				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+				       ERR_R_INTERNAL_ERROR);
+				goto rsapsk_err;
+				}
+			else if (psk_len == 0)
+				{
+				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+				       SSL_R_PSK_IDENTITY_NOT_FOUND);
+				al=SSL_AD_UNKNOWN_PSK_IDENTITY;
+				goto rsapsk_err;
+				}
+
+			/* move on onto decoding the 48 encrypted bytes */
+
+			/* how many bytes to decode? */
+			n2s(p, epms_len);
+
+			if (n != (2 + identity_len + 2 + epms_len)) /* as above */
+				{
+				SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+				       SSL_R_LENGTH_MISMATCH);
+				goto rsapsk_err;
+				}
+
+			/* decode in place into p */
+			decrypt_len = RSA_private_decrypt(epms_len, p, p, rsa, RSA_PKCS1_PADDING);
+			decrypt_good = constant_time_eq_int_8(decrypt_len, 48);
+
+			/* check the version sent by the client */
+			version_good = constant_time_eq_8(p[0], (unsigned)(s->client_version>>8));
+			version_good &= constant_time_eq_8(p[1], (unsigned)(s->client_version&0xff));
+
+			decrypt_good &= version_good;
+
+			for (i = 0; i < (int) sizeof(rand_premaster_secret); i++)
+				p[i] = constant_time_select_8(decrypt_good, p[i], rand_premaster_secret[i]);
+
+			/* build the pre master secret. it should look like this:
+			 * 48 (2b) + version (2b) + random (46b) + psk_len (2b) + psk */
+			pre_ms_len = 2 + 2 + 46 + 2 + psk_len;
+
+			/* the PSK is at the beginning of psk_or_pre_ms, move at the end */
+			memmove(psk_or_pre_ms + 52, psk_or_pre_ms, psk_len);
+
+			/* fill the "48" in */
+			s2n(pre_master_secret_prefix, t);
+
+			/* fill the 2 bytes version + the 46 random bytes (decrypted earlier with RSA) */
+			memcpy(t, p, 48);
+			t += 48;
+
+			/* fill the psk_len */
+			s2n(psk_len, t);
+
+			/* psk_or_pre_ms now contains the pre master secret */
+
+			/* set the identity in the session */
+			if (s->session->psk_identity != NULL)
+				OPENSSL_free(s->session->psk_identity);
+
+			s->session->psk_identity = BUF_strdup(identity);
+			OPENSSL_cleanse(identity, sizeof(identity));
+
+			if (s->session->psk_identity == NULL)
+				{
+					SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
+					goto rsapsk_err;
+				}
+
+			/* set the identity hint in the session */
+			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 rsapsk_err;
+				}
+
+			/* set the premaster key */
+			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;
+	rsapsk_err:
+			OPENSSL_cleanse(orig_p, n); /* clear the whole payload area */
+			if (psk_err != 0)
+				goto f_err;
+			}
+
+	else
+#endif /* !OPENSSL_NO_PSK */
+#endif /* !OPENSSL_NO_RSA */
 #ifndef OPENSSL_NO_SRP
 		if (alg_k & SSL_kSRP)
 			{
diff --git a/ssl/ssl.h b/ssl/ssl.h
index 343247c..0f47f71 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -252,7 +252,8 @@ extern "C" {
 #define SSL_TXT_kECDH		"kECDH"
 #define SSL_TXT_kEECDH		"kEECDH" /* alias for kECDHE */
 #define SSL_TXT_kECDHE		"kECDHE"
-#define SSL_TXT_kPSK            "kPSK"
+#define SSL_TXT_kPSK		"kPSK"
+#define SSL_TXT_kRSAPSK		"kRSAPSK"
 #define SSL_TXT_kGOST		"kGOST"
 #define SSL_TXT_kSRP		"kSRP"
 
@@ -281,6 +282,7 @@ extern "C" {
 #define SSL_TXT_ECDSA		"ECDSA"
 #define SSL_TXT_KRB5      	"KRB5"
 #define SSL_TXT_PSK             "PSK"
+#define SSL_TXT_RSAPSK		"RSAPSK"
 #define SSL_TXT_SRP		"SRP"
 
 #define SSL_TXT_DES		"DES"
diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c
index 3c005f7..72f67f1 100644
--- a/ssl/ssl_ciph.c
+++ b/ssl/ssl_ciph.c
@@ -254,7 +254,8 @@ static const SSL_CIPHER cipher_aliases[]={
 	{0,SSL_TXT_kECDHE,0,  SSL_kECDHE,0,0,0,0,0,0,0,0},
 	{0,SSL_TXT_ECDH,0,    SSL_kECDHr|SSL_kECDHe|SSL_kECDHE,0,0,0,0,0,0,0,0},
 
-        {0,SSL_TXT_kPSK,0,    SSL_kPSK,  0,0,0,0,0,0,0,0},
+	{0,SSL_TXT_kPSK,0,    SSL_kPSK,  0,0,0,0,0,0,0,0},
+	{0,SSL_TXT_kRSAPSK,0, SSL_kRSAPSK,  0,0,0,0,0,0,0,0},
 	{0,SSL_TXT_kSRP,0,    SSL_kSRP,  0,0,0,0,0,0,0,0},
 	{0,SSL_TXT_kGOST,0, SSL_kGOST,0,0,0,0,0,0,0,0},
 
@@ -268,7 +269,7 @@ static const SSL_CIPHER cipher_aliases[]={
 	{0,SSL_TXT_aECDH,0,   0,SSL_aECDH, 0,0,0,0,0,0,0},
 	{0,SSL_TXT_aECDSA,0,  0,SSL_aECDSA,0,0,0,0,0,0,0},
 	{0,SSL_TXT_ECDSA,0,   0,SSL_aECDSA, 0,0,0,0,0,0,0},
-        {0,SSL_TXT_aPSK,0,    0,SSL_aPSK,  0,0,0,0,0,0,0},
+	{0,SSL_TXT_aPSK,0,    0,SSL_aPSK,  0,0,0,0,0,0,0},
 	{0,SSL_TXT_aGOST94,0,0,SSL_aGOST94,0,0,0,0,0,0,0},
 	{0,SSL_TXT_aGOST01,0,0,SSL_aGOST01,0,0,0,0,0,0,0},
 	{0,SSL_TXT_aGOST,0,0,SSL_aGOST94|SSL_aGOST01,0,0,0,0,0,0,0},
@@ -284,7 +285,8 @@ static const SSL_CIPHER cipher_aliases[]={
 	{0,SSL_TXT_RSA,0,     SSL_kRSA,SSL_aRSA,0,0,0,0,0,0,0},
 	{0,SSL_TXT_ADH,0,     SSL_kDHE,SSL_aNULL,0,0,0,0,0,0,0},
 	{0,SSL_TXT_AECDH,0,   SSL_kECDHE,SSL_aNULL,0,0,0,0,0,0,0},
-        {0,SSL_TXT_PSK,0,     SSL_kPSK,SSL_aPSK,0,0,0,0,0,0,0},
+	{0,SSL_TXT_PSK,0,     SSL_kPSK,SSL_aPSK,0,0,0,0,0,0,0},
+	{0,SSL_TXT_RSAPSK,0,  SSL_kRSAPSK,SSL_aRSA,0,0,0,0,0,0,0},
 	{0,SSL_TXT_SRP,0,     SSL_kSRP,0,0,0,0,0,0,0,0},
 
 
@@ -755,7 +757,7 @@ static void ssl_cipher_get_disabled(unsigned long *mkey, unsigned long *auth, un
 	*auth |= SSL_aECDH;
 #endif
 #ifdef OPENSSL_NO_PSK
-	*mkey |= SSL_kPSK;
+	*mkey |= SSL_kPSK|SSL_kRSAPSK;
 	*auth |= SSL_aPSK;
 #endif
 #ifdef OPENSSL_NO_SRP
@@ -1535,7 +1537,8 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
 	ssl_cipher_apply_rule(0, 0, SSL_aECDH, 0, 0, 0, 0, CIPHER_ORD, -1, &head, &tail);
 	/* ssl_cipher_apply_rule(0, 0, SSL_aDH, 0, 0, 0, 0, CIPHER_ORD, -1, &head, &tail); */
 	ssl_cipher_apply_rule(0, SSL_kRSA, 0, 0, 0, 0, 0, CIPHER_ORD, -1, &head, &tail);
-	ssl_cipher_apply_rule(0, SSL_kPSK, 0,0, 0, 0, 0, CIPHER_ORD, -1, &head, &tail);
+	ssl_cipher_apply_rule(0, SSL_kRSAPSK, 0, 0, 0, 0, 0, CIPHER_ORD, -1, &head, &tail);
+	ssl_cipher_apply_rule(0, SSL_kPSK, 0, 0, 0, 0, 0, CIPHER_ORD, -1, &head, &tail);
 	ssl_cipher_apply_rule(0, SSL_kKRB5, 0,0, 0, 0, 0, CIPHER_ORD, -1, &head, &tail);
 
 	/* RC4 is sort-of broken -- move the the end */
@@ -1717,6 +1720,9 @@ char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len)
 	case SSL_kGOST:
 		kx="GOST";
 		break;
+	case SSL_kRSAPSK:
+		kx="RSAPSK";
+		break;
 	default:
 		kx="unknown";
 		}
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 43204de..6969672 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -2460,8 +2460,14 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher)
 
 #ifndef OPENSSL_NO_PSK
 	mask_k |= SSL_kPSK;
+#ifndef OPENSSL_NO_RSA
+	mask_k |= SSL_kRSAPSK;
+#endif
 	mask_a |= SSL_aPSK;
 	emask_k |= SSL_kPSK;
+#ifndef OPENSSL_NO_RSA
+	emask_k |= SSL_kRSAPSK;
+#endif
 	emask_a |= SSL_aPSK;
 #endif
 
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 1fd6bb1..2a5179b 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -301,6 +301,7 @@
 #define SSL_kPSK		0x00000100L /* PSK */
 #define SSL_kGOST       0x00000200L /* GOST key exchange */
 #define SSL_kSRP        0x00000400L /* SRP */
+#define SSL_kRSAPSK     0x00000800L /* RSA-PSK */
 
 /* Bits for algorithm_auth (server authentication) */
 #define SSL_aRSA		0x00000001L /* RSA auth */
diff --git a/ssl/tls1.h b/ssl/tls1.h
index e8188ec..1018c50 100644
--- a/ssl/tls1.h
+++ b/ssl/tls1.h
@@ -416,6 +416,24 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
 #define TLS1_CK_PSK_WITH_AES_128_CBC_SHA                0x0300008C
 #define TLS1_CK_PSK_WITH_AES_256_CBC_SHA                0x0300008D
 
+/* PSK ciphersuites from 5487 */
+#define TLS1_CK_PSK_WITH_AES_128_GCM_SHA256		0x030000A8
+#define TLS1_CK_PSK_WITH_AES_256_GCM_SHA384		0x030000A9
+#define TLS1_CK_PSK_WITH_AES_128_CBC_SHA256		0x030000AE
+#define TLS1_CK_PSK_WITH_AES_256_CBC_SHA384		0x030000AF
+
+/* RSA-PSK ciphersuites from 4279 */
+#define TLS1_CK_RSA_PSK_WITH_RC4_128_SHA		0x03000092
+#define TLS1_CK_RSA_PSK_WITH_3DES_EDE_CBC_SHA		0x03000093
+#define TLS1_CK_RSA_PSK_WITH_AES_128_CBC_SHA		0x03000094
+#define TLS1_CK_RSA_PSK_WITH_AES_256_CBC_SHA		0x03000095
+
+/* RSA-PSK ciphersuites from 5487 */
+#define TLS1_CK_RSA_PSK_WITH_AES_128_GCM_SHA256		0x030000AC
+#define TLS1_CK_RSA_PSK_WITH_AES_256_GCM_SHA384		0x030000AD
+#define TLS1_CK_RSA_PSK_WITH_AES_128_CBC_SHA256		0x030000B6
+#define TLS1_CK_RSA_PSK_WITH_AES_256_CBC_SHA384		0x030000B7
+
 /* Additional TLS ciphersuites from expired Internet Draft
  * draft-ietf-tls-56-bit-ciphersuites-01.txt
  * (available if TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES is defined, see
@@ -655,6 +673,24 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
 #define TLS1_TXT_PSK_WITH_AES_128_CBC_SHA		"PSK-AES128-CBC-SHA"
 #define TLS1_TXT_PSK_WITH_AES_256_CBC_SHA		"PSK-AES256-CBC-SHA"
 
+/* PSK ciphersuites from 5487 */
+#define TLS1_TXT_PSK_WITH_AES_128_GCM_SHA256		"PSK-AES128-GCM-SHA256"
+#define TLS1_TXT_PSK_WITH_AES_256_GCM_SHA384		"PSK-AES256-GCM-SHA384"
+#define TLS1_TXT_PSK_WITH_AES_128_CBC_SHA256		"PSK-AES128-CBC-SHA256"
+#define TLS1_TXT_PSK_WITH_AES_256_CBC_SHA384		"PSK-AES256-CBC-SHA384"
+
+/* RSA-PSK ciphersuites from 4279 */
+#define TLS1_TXT_RSA_PSK_WITH_RC4_128_SHA		"RSA-PSK-RC4-SHA"
+#define TLS1_TXT_RSA_PSK_WITH_3DES_EDE_CBC_SHA		"RSA-PSK-3DES-EDE-CBC-SHA"
+#define TLS1_TXT_RSA_PSK_WITH_AES_128_CBC_SHA		"RSA-PSK-AES128-CBC-SHA"
+#define TLS1_TXT_RSA_PSK_WITH_AES_256_CBC_SHA		"RSA-PSK-AES256-CBC-SHA"
+
+/* RSA-PSK ciphersuites from 5487 */
+#define TLS1_TXT_RSA_PSK_WITH_AES_128_GCM_SHA256	"RSA-PSK-AES128-GCM-SHA256"
+#define TLS1_TXT_RSA_PSK_WITH_AES_256_GCM_SHA384	"RSA-PSK-AES256-GCM-SHA384"
+#define TLS1_TXT_RSA_PSK_WITH_AES_128_CBC_SHA256	"RSA-PSK-AES128-CBC-SHA256"
+#define TLS1_TXT_RSA_PSK_WITH_AES_256_CBC_SHA384	"RSA-PSK-AES256-CBC-SHA384"
+
 /* SRP ciphersuite from RFC 5054 */
 #define TLS1_TXT_SRP_SHA_WITH_3DES_EDE_CBC_SHA		"SRP-3DES-EDE-CBC-SHA"
 #define TLS1_TXT_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA	"SRP-RSA-3DES-EDE-CBC-SHA"
-- 
1.7.9.5

Attachment: smime.p7s
Description: S/MIME cryptographic signature

Reply via email to