New version of the patch, targeting master.

It's basically style changes after the massive OpenSSL refactoring.

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 db9155f74e7cb3785851a49f1d11be2d57f70c9e 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        |  122 ++++++++++++++++++++++-----
 ssl/s3_lib.c         |  208 ++++++++++++++++++++++++++++++++++++++++++++-
 ssl/s3_srvr.c        |  227 +++++++++++++++++++++++++++++++++++++++++++++++---
 ssl/ssl.h            |    2 +
 ssl/ssl_ciph.c       |    9 +-
 ssl/ssl_lib.c        |    6 ++
 ssl/ssl_locl.h       |    2 +
 ssl/tls1.h           |   36 ++++++++
 10 files changed, 592 insertions(+), 35 deletions(-)

diff --git a/CHANGES b/CHANGES
index 26ea797..726a54a 100644
--- a/CHANGES
+++ b/CHANGES
@@ -351,6 +351,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.1k and 1.0.2 [xx XXX xxxx]
 
   *) Facilitate "universal" ARM builds targeting range of ARM ISAs, e.g.
diff --git a/doc/apps/ciphers.pod b/doc/apps/ciphers.pod
index 6d39c54..79644ef 100644
--- a/doc/apps/ciphers.pod
+++ b/doc/apps/ciphers.pod
@@ -587,10 +587,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
 
 =head1 NOTES
 
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index a383eee..d7908e5 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -320,7 +320,7 @@ int ssl3_connect(SSL *s)
         case SSL3_ST_CR_CERT_A:
         case SSL3_ST_CR_CERT_B:
             /* 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))
@@ -1367,9 +1367,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();
@@ -1414,7 +1414,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];
 
         param_len = 2;
@@ -1569,7 +1574,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
+                 )) {
         /* Temporary RSA keys only allowed in export ciphersuites */
         if (!SSL_C_IS_EXPORT(s->s3->tmp.new_cipher)) {
             al = SSL_AD_UNEXPECTED_MESSAGE;
@@ -1943,8 +1952,16 @@ 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)) {
+        /* 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))
                 /* Otherwise this shouldn't happen */
@@ -2965,7 +2982,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
@@ -2973,8 +2994,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;
 
@@ -3006,14 +3027,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);
@@ -3043,8 +3084,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));
@@ -3406,7 +3480,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);
@@ -3436,7 +3514,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 7a07a24..9da977a 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -1660,6 +1660,74 @@ 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
@@ -1972,6 +2040,144 @@ OPENSSL_GLOBAL const SSL_CIPHER ssl3_ciphers[] = {
      0},
 #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 */
 
@@ -4348,7 +4554,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 e929658..5909fc1 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -457,19 +457,23 @@ 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
+#ifndef OPENSSL_NO_RSA
+                              | SSL_kRSAPSK
+#endif
+                    )) && s->ctx->psk_identity_hint)
 #endif
 #ifndef OPENSSL_NO_SRP
                 /* SRP: send ServerKeyExchange */
@@ -525,11 +529,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;
@@ -1811,7 +1818,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
              */
@@ -1850,7 +1861,14 @@ 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) {
                 al = SSL_AD_DECODE_ERROR;
@@ -1905,7 +1923,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);
             strncpy((char *)p, s->ctx->psk_identity_hint,
@@ -1921,7 +1943,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--) {
@@ -2769,6 +2795,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 a/ssl/ssl.h b/ssl/ssl.h
index 0a6f4da..27c6012 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -235,6 +235,7 @@ extern "C" {
 # define SSL_TXT_kEECDH          "kEECDH"/* alias for kECDHE */
 # define SSL_TXT_kECDHE          "kECDHE"
 # define SSL_TXT_kPSK            "kPSK"
+# define SSL_TXT_kRSAPSK         "kRSAPSK"
 # define SSL_TXT_kGOST           "kGOST"
 # define SSL_TXT_kSRP            "kSRP"
 
@@ -263,6 +264,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 12820b6..c44083e 100644
--- a/ssl/ssl_ciph.c
+++ b/ssl/ssl_ciph.c
@@ -264,6 +264,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},
 
@@ -295,6 +296,7 @@ static const SSL_CIPHER cipher_aliases[] = {
     {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_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,
@@ -1726,6 +1730,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 a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 2a84ff2..5866391 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -2373,8 +2373,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 f3ce460..81ca8ee 100644
--- a/ssl/ssl_locl.h
+++ b/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 a/ssl/tls1.h b/ssl/tls1.h
index 1f756a4..a9923dd 100644
--- a/ssl/tls1.h
+++ b/ssl/tls1.h
@@ -405,6 +405,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
@@ -650,6 +668,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"
-- 
1.7.9.5

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

_______________________________________________
openssl-dev mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev

Reply via email to