AusweisApp2/patches/openssl_rsa_psk.patch

918 lines
31 KiB
Diff

From e681bc2125a396ff34aab4c3f629683dd0ce28bb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Klitzing?= <aklitzing@gmail.com>
Date: Thu, 23 Apr 2015 20:59:30 +0200
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
---
doc/apps/ciphers.pod | 12 +++
ssl/s3_clnt.c | 106 ++++++++++++++++++++----
ssl/s3_lib.c | 206 +++++++++++++++++++++++++++++++++++++++++++++-
ssl/s3_srvr.c | 226 ++++++++++++++++++++++++++++++++++++++++++++++++---
ssl/ssl.h | 2 +
ssl/ssl_ciph.c | 9 +-
ssl/ssl_lib.c | 6 ++
ssl/ssl_locl.h | 2 +
ssl/tls1.h | 36 ++++++++
9 files changed, 572 insertions(+), 33 deletions(-)
diff --git x/doc/apps/ciphers.pod y/doc/apps/ciphers.pod
index fa16124d08..45db06c168 100644
--- x/doc/apps/ciphers.pod
+++ y/doc/apps/ciphers.pod
@@ -585,10 +585,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 x/ssl/s3_clnt.c y/ssl/s3_clnt.c
index 5b8b2da59f..ae0d4d840c 100644
--- x/ssl/s3_clnt.c
+++ y/ssl/s3_clnt.c
@@ -342,7 +342,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))
@@ -1424,9 +1424,9 @@ int ssl3_get_key_exchange(SSL *s)
}
#ifndef OPENSSL_NO_PSK
/*
- * In plain PSK ciphersuite, ServerKeyExchange can be omitted if no
- * identity hint is sent. Set session->sess_cert anyway to avoid
- * problems later.
+ * In PSK ciphersuites, ServerKeyExchange can be omitted if no
+ * identity hint is sent. Set session->sess_cert for plain PSK
+ * anyway to avoid problems later.
*/
if (alg_k & SSL_kPSK) {
s->session->sess_cert = ssl_sess_cert_new();
@@ -1471,7 +1471,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
+ || alg_k & SSL_kRSAPSK
+#endif
+ ) {
param_len = 2;
if (param_len > n) {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
@@ -2041,7 +2046,7 @@ int ssl3_get_key_exchange(SSL *s)
}
} 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)) && !(alg_k & SSL_kPSK) && !(alg_k & SSL_kRSAPSK)) {
/* Might be wrong key type, check it */
if (ssl3_check_cert_and_algorithm(s))
/* Otherwise this shouldn't happen */
@@ -3130,7 +3135,11 @@ 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
@@ -3138,8 +3147,8 @@ int ssl3_send_client_key_exchange(SSL *s)
*/
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;
@@ -3171,14 +3180,34 @@ 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);
@@ -3208,8 +3237,41 @@ int ssl3_send_client_key_exchange(SSL *s)
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));
@@ -3580,7 +3642,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
+ || alg_k & SSL_kRSAPSK
+#endif
+ ) {
if (!SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) &&
!has_bits(i, EVP_PK_RSA | EVP_PKT_ENC)) {
SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
@@ -3647,7 +3713,11 @@ int ssl3_check_cert_and_algorithm(SSL *s)
if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) &&
pkey_bits > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) {
#ifndef OPENSSL_NO_RSA
- if (alg_k & SSL_kRSA) {
+ if (alg_k & SSL_kRSA
+#ifndef OPENSSL_NO_PSK
+ || alg_k & SSL_kRSAPSK
+#endif
+ ) {
if (rsa == NULL) {
SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
SSL_R_MISSING_EXPORT_TMP_RSA_KEY);
diff --git x/ssl/s3_lib.c y/ssl/s3_lib.c
index 1014a3fce1..0187d508a1 100644
--- x/ssl/s3_lib.c
+++ y/ssl/s3_lib.c
@@ -1765,6 +1765,74 @@ OPENSSL_GLOBAL 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
@@ -2077,6 +2145,142 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
0},
#endif
+#ifndef OPENSSL_NO_PSK
+ /* PSK ciphersuites from RFC5487 */
+
+ /* 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_AEAD,
+ 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_AEAD,
+ 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_AEAD,
+ 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_AEAD,
+ SSL_TLSV1_2,
+ SSL_NOT_EXP|SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384,
+ 256,
+ 256,
+ },
+#endif /* OPENSSL_NO_RSA */
+
+ /* 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_ECDH
/* Cipher C001 */
{
@@ -4169,7 +4373,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 || alg_k & SSL_kRSAPSK) && s->psk_server_callback == NULL)
continue;
#endif /* OPENSSL_NO_PSK */
diff --git x/ssl/s3_srvr.c y/ssl/s3_srvr.c
index 0fb4845d44..3498836e7d 100644
--- x/ssl/s3_srvr.c
+++ y/ssl/s3_srvr.c
@@ -467,19 +467,22 @@ 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 For
- * ECC ciphersuites, we send a serverKeyExchange message only if
+ * sign only certificate
+ *
+ * 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 ECDH-anon or ECDHE. In other cases,
* the server certificate contains the server's public key for
* key exchange.
*/
if (0
- /*
- * 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 && s->ctx->psk_identity_hint)
+#ifndef OPENSSL_NO_RSA
+ || (alg_k & SSL_kRSAPSK && s->ctx->psk_identity_hint)
+#endif
#endif
#ifndef OPENSSL_NO_SRP
/* SRP: send ServerKeyExchange */
@@ -535,11 +538,14 @@ 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)
+#ifndef OPENSSL_NO_PSK
/*
- * With normal PSK Certificates and Certificate Requests
+ * With normal PSK, Certificates and Certificate Requests
* are omitted
*/
- || (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) {
+ || (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)
+#endif
+ ) {
/* no cert request */
skip = 1;
s->s3->tmp.cert_request = 0;
@@ -1835,7 +1841,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
+ || type & SSL_kRSAPSK
+#endif
+ ) {
/*
* reserve size for record length and PSK identity hint
*/
@@ -1884,7 +1894,8 @@ 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)) {
+ && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)
+ && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kRSAPSK)) {
if ((pkey = ssl_get_sign_pkey(s, s->s3->tmp.new_cipher, &md))
== NULL) {
al = SSL_AD_DECODE_ERROR;
@@ -1899,6 +1910,12 @@ int ssl3_send_server_key_exchange(SSL *s)
} else {
pkey = NULL;
kn = 0;
+ /* Allow space for signature algorithm */
+ if (SSL_USE_SIGALGS(s)) {
+ kn += 4;
+ const unsigned char *sig;
+ kn += tls12_get_psigalgs(s, 1, &sig);
+ }
}
if (!BUF_MEM_grow_clean(buf, n + SSL_HM_HEADER_LENGTH(s) + kn)) {
@@ -1958,7 +1975,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
+ || type & SSL_kRSAPSK
+#endif
+ ) {
/* copy PSK identity hint */
s2n(strlen(s->ctx->psk_identity_hint), p);
strncpy((char *)p, s->ctx->psk_identity_hint,
@@ -1974,7 +1995,11 @@ int ssl3_send_server_key_exchange(SSL *s)
* 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;
for (num = 2; num > 0; num--) {
@@ -2870,6 +2895,181 @@ int ssl3_get_client_key_exchange(SSL *s)
goto f_err;
} 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
+#endif
#ifndef OPENSSL_NO_SRP
if (alg_k & SSL_kSRP) {
int param_len;
diff --git x/ssl/ssl.h y/ssl/ssl.h
index 90aeb0ce4e..78cf2212ed 100644
--- x/ssl/ssl.h
+++ y/ssl/ssl.h
@@ -254,6 +254,7 @@ extern "C" {
# define SSL_TXT_kEECDH "kEECDH"
# define SSL_TXT_kECDHE "kECDHE"/* alias for kEECDH */
# define SSL_TXT_kPSK "kPSK"
+# define SSL_TXT_kRSAPSK "kRSAPSK"
# define SSL_TXT_kGOST "kGOST"
# define SSL_TXT_kSRP "kSRP"
@@ -282,6 +283,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 x/ssl/ssl_ciph.c y/ssl/ssl_ciph.c
index ccdf00fa1b..19c4ac0656 100644
--- x/ssl/ssl_ciph.c
+++ y/ssl/ssl_ciph.c
@@ -263,6 +263,7 @@ static const SSL_CIPHER cipher_aliases[] = {
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},
@@ -294,6 +295,7 @@ static const SSL_CIPHER cipher_aliases[] = {
{0, SSL_TXT_ADH, 0, SSL_kEDH, SSL_aNULL, 0, 0, 0, 0, 0, 0, 0},
{0, SSL_TXT_AECDH, 0, SSL_kEECDH, 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_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},
/* symmetric encryption aliases */
@@ -756,7 +758,7 @@ static void ssl_cipher_get_disabled(unsigned long *mkey, unsigned long *auth,
*auth |= SSL_aECDH;
#endif
#ifdef OPENSSL_NO_PSK
- *mkey |= SSL_kPSK;
+ *mkey |= SSL_kPSK | SSL_kRSAPSK;
*auth |= SSL_aPSK;
#endif
#ifdef OPENSSL_NO_SRP
@@ -1555,6 +1557,8 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, STACK
*/
ssl_cipher_apply_rule(0, SSL_kRSA, 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,
@@ -1731,6 +1735,9 @@ char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len)
case SSL_kPSK:
kx = "PSK";
break;
+ case SSL_kRSAPSK:
+ kx = "RSAPSK";
+ break;
case SSL_kSRP:
kx = "SRP";
break;
diff --git x/ssl/ssl_lib.c y/ssl/ssl_lib.c
index 3539f4b8d2..df6a45bdc4 100644
--- x/ssl/ssl_lib.c
+++ y/ssl/ssl_lib.c
@@ -2442,8 +2442,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 x/ssl/ssl_locl.h y/ssl/ssl_locl.h
index aeffc00634..25b9f1d5b1 100644
--- x/ssl/ssl_locl.h
+++ y/ssl/ssl_locl.h
@@ -314,6 +314,8 @@
# define SSL_kGOST 0x00000200L
/* SRP */
# define SSL_kSRP 0x00000400L
+/* RSA PSK */
+# define SSL_kRSAPSK 0x00000800L
/* Bits for algorithm_auth (server authentication) */
/* RSA auth */
diff --git x/ssl/tls1.h y/ssl/tls1.h
index dd1d8c109e..e04e7ddabc 100644
--- x/ssl/tls1.h
+++ y/ssl/tls1.h
@@ -410,6 +410,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
@@ -629,6 +647,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 RFC 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 RFC 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 RFC 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"
--
2.15.0