[openssl-commits] [openssl] master update

Dr. Stephen Henson steve at openssl.org
Thu Jul 30 14:37:58 UTC 2015


The branch master has been updated
       via  3df16cc2e27f75eac2c0991248b0c294e2c847b5 (commit)
       via  a784665e52735f77a64d01216d7535834278c27c (commit)
       via  a3f7ff2b2d1b1267cdf0bbce2374ebe149ed264a (commit)
       via  69a3a9f5d9c018eee97b4127c40bc9903c03cce4 (commit)
       via  b2f8ab8681d4c9bba3b516672689e86e83b41e53 (commit)
       via  23237159f76933a898d4da1ee67de704350e1ca9 (commit)
       via  5516fcc0c9dad543aee4c9bf849d759bb58a0644 (commit)
       via  ea6114c6d0e31e3d6d8897d753afeadec33ddeee (commit)
       via  f40ecbc37c4be64eb4203792a55b2ecaebe83cf7 (commit)
       via  2a1a04e131749a6aec280d53dfda86b595de55b3 (commit)
       via  8a0a12e5bf78e6f2e501d3af86c675498e6c7552 (commit)
       via  85269210ff39eabd1f898716f1e9bbcd2d0b8be2 (commit)
       via  7689082b7199b91aa2df5d3e481abcca480e9d7e (commit)
       via  12053a81c875473355e441d00ac81ed3c501dc9b (commit)
       via  adc5506adf4f4cb2719026354a8512e3a7807f8a (commit)
       via  13be69f3e67f8b974183e6fff6d12d9a841ee97f (commit)
       via  526f94ad68345a18559ee334e03d7f31c96f47d6 (commit)
       via  fe5eef3a3b3e6844394d976a182d88225c59ddb5 (commit)
       via  332a251fd7cca28b1cc34d5ddf26272a352f5299 (commit)
       via  8baac6a224ec194036b43e47b36b642248257b56 (commit)
       via  dcbd50608a44277f84f2a9323726a84f6f9d68ca (commit)
       via  0096d8f7e01d2c0616f9a916145b62a2d8d7acdf (commit)
       via  64651d3984ca24c48538a2a109c446fd684aa248 (commit)
      from  5e8b24dbfb98ed7c5b355cb6a959906a418e264b (commit)


- Log -----------------------------------------------------------------
commit 3df16cc2e27f75eac2c0991248b0c294e2c847b5
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Tue Jul 28 16:13:29 2015 +0100

    cleanse psk_identity on error
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit a784665e52735f77a64d01216d7535834278c27c
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Tue Jul 28 16:04:53 2015 +0100

    Free and cleanse pms on error
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit a3f7ff2b2d1b1267cdf0bbce2374ebe149ed264a
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Sat Jul 11 01:17:36 2015 +0100

    Don't request certificates for any PSK ciphersuite
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit 69a3a9f5d9c018eee97b4127c40bc9903c03cce4
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Tue Jun 30 19:14:58 2015 +0100

    CAMELLIA PSK ciphersuites from RFC6367
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit b2f8ab8681d4c9bba3b516672689e86e83b41e53
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Mon Jun 29 14:20:01 2015 +0100

    Add PSK ciphersuites to docs
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit 23237159f76933a898d4da1ee67de704350e1ca9
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Mon Jun 29 12:17:21 2015 +0100

    Update CHANGES
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit 5516fcc0c9dad543aee4c9bf849d759bb58a0644
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Mon Jun 29 00:44:39 2015 +0100

    Add RFC4785 ciphersuites
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit ea6114c6d0e31e3d6d8897d753afeadec33ddeee
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Sun Jun 28 17:05:47 2015 +0100

    Add RFC4279, RFC5487 and RFC5489 ciphersuites.
    
    Note: some of the RFC4279 ciphersuites were originally part of PR#2464.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit f40ecbc37c4be64eb4203792a55b2ecaebe83cf7
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Sun Jun 28 16:55:00 2015 +0100

    Initial new PSK ciphersuite defines
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit 2a1a04e131749a6aec280d53dfda86b595de55b3
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Sun Jun 28 16:50:53 2015 +0100

    Add full PSK trace support
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit 8a0a12e5bf78e6f2e501d3af86c675498e6c7552
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Sun Jun 28 16:58:00 2015 +0100

    PSK premaster secret derivation.
    
    Move PSK premaster secret algorithm to ssl_generate_master secret so
    existing key exchange code can be used and modified slightly to add
    the PSK wrapping structure.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit 85269210ff39eabd1f898716f1e9bbcd2d0b8be2
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Sun Jun 28 17:23:13 2015 +0100

    Extended PSK server support.
    
    Add support for RSAPSK, DHEPSK and ECDHEPSK server side.
    
    Update various checks to ensure certificate and server key exchange messages
    are only sent when required.
    
    Update message handling. PSK server key exchange parsing now include an
    identity hint prefix for all PSK server key exchange messages. PSK
    client key exchange message expects PSK identity and requests key for
    all PSK key exchange ciphersuites.
    
    Update flags for RSA, DH and ECDH so they are also used in PSK.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit 7689082b7199b91aa2df5d3e481abcca480e9d7e
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Sun Jun 28 17:15:10 2015 +0100

    Extended PSK client support.
    
    Add support for RSAPSK, DHEPSK and ECDHEPSK client side.
    
    Update various checks to ensure certificate and server key exchange messages
    are only expected when required.
    
    Update message handling. PSK server key exchange parsing now expects an
    identity hint prefix for all PSK server key exchange messages. PSK
    client key exchange message requests PSK identity and key for all PSK
    key exchange ciphersuites and includes identity in message.
    
    Update flags for RSA, DH and ECDH so they are also used in PSK.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit 12053a81c875473355e441d00ac81ed3c501dc9b
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Sun Jun 28 23:18:59 2015 +0100

    PSK PRF correction.
    
    For SHA384 PRF PSK ciphersuites we have to switch to default PRF for
    TLS < 1.2
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit adc5506adf4f4cb2719026354a8512e3a7807f8a
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Sun Jun 28 17:01:52 2015 +0100

    Make auto DH work with DHEPSK
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit 13be69f3e67f8b974183e6fff6d12d9a841ee97f
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Tue Jun 30 16:39:41 2015 +0100

    Check for kECDH with extensions.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit 526f94ad68345a18559ee334e03d7f31c96f47d6
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Sun Jun 28 17:02:56 2015 +0100

    Enable PSK if corresponding mask set.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit fe5eef3a3b3e6844394d976a182d88225c59ddb5
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Sun Jun 28 17:01:07 2015 +0100

    Disable all PSK if no callback.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit 332a251fd7cca28b1cc34d5ddf26272a352f5299
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Sun Jun 28 17:09:54 2015 +0100

    Disable unsupported PSK algorithms
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit 8baac6a224ec194036b43e47b36b642248257b56
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Sun Jun 28 17:07:41 2015 +0100

    new PSK text constants
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit dcbd50608a44277f84f2a9323726a84f6f9d68ca
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Sun Jun 28 17:10:27 2015 +0100

    New PSK aliases.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit 0096d8f7e01d2c0616f9a916145b62a2d8d7acdf
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Sun Jun 28 16:54:06 2015 +0100

    New PSK keyex text constants
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit 64651d3984ca24c48538a2a109c446fd684aa248
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Sun Jun 28 16:52:40 2015 +0100

    fields for PSK key, new constants
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

-----------------------------------------------------------------------

Summary of changes:
 CHANGES                |   8 +
 doc/apps/ciphers.pod   |  77 ++++-
 include/openssl/ssl.h  |   3 +
 include/openssl/tls1.h | 125 +++++++-
 ssl/s3_clnt.c          | 222 ++++++-------
 ssl/s3_lib.c           | 831 ++++++++++++++++++++++++++++++++++++++++++++++---
 ssl/s3_srvr.c          | 256 ++++++++-------
 ssl/ssl_ciph.c         |  22 +-
 ssl/ssl_lib.c          |   6 +
 ssl/ssl_locl.h         |  13 +
 ssl/t1_lib.c           |   6 +-
 ssl/t1_trce.c          |  49 ++-
 12 files changed, 1316 insertions(+), 302 deletions(-)

diff --git a/CHANGES b/CHANGES
index 1526aec..c5be241 100644
--- a/CHANGES
+++ b/CHANGES
@@ -3,6 +3,14 @@
  _______________
 
  Changes between 1.0.2 and 1.1.0  [xx XXX xxxx]
+
+  *) Rewrite PSK to support ECDHE_PSK, DHE_PSK and RSA_PSK. Add ciphersuites
+     from RFC4279, RFC4785, RFC5487, RFC5489.
+
+     Thanks to Christian J. Dietrich and Giuseppe D'Angelo for the
+     original RSA_PSK patch.
+     [Steve Henson]
+
   *) Dropped support for the SSL3_FLAGS_DELAY_CLIENT_FINISHED flag. This SSLeay
      era flag was never set throughout the codebase (only read). Also removed
      SSL3_FLAGS_POP_BUFFER which was only used if
diff --git a/doc/apps/ciphers.pod b/doc/apps/ciphers.pod
index c2d40ac..d7b7bea 100644
--- a/doc/apps/ciphers.pod
+++ b/doc/apps/ciphers.pod
@@ -329,7 +329,16 @@ cipher suites using GOST 28147-89 MAC B<instead of> HMAC.
 
 =item B<PSK>
 
-cipher suites using pre-shared keys (PSK).
+all cipher suites using pre-shared keys (PSK).
+
+=item B<kPSK>, B<kECDHEPSK>, B<kDHEPSK>, B<kRSAPSK>
+
+cipher suites using PSK key exchange, ECDHE_PSK, DHE_PSK or RSA_PSK.
+
+=item B<aPSK>
+
+cipher suites using PSK authentication (currently all PSK modes apart from
+RSA_PSK).
 
 =item B<SUITEB128>, B<SUITEB128ONLY>, B<SUITEB192>
 
@@ -585,10 +594,68 @@ Note: these ciphers can also be used in SSL v3.
 
 =head2 Pre shared keying (PSK) ciphersuites
 
- 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
+ PSK_WITH_NULL_SHA                         PSK-NULL-SHA
+ DHE_PSK_WITH_NULL_SHA                     DHE-PSK-NULL-SHA
+ RSA_PSK_WITH_NULL_SHA                     RSA-PSK-NULL-SHA
+
+ PSK_WITH_RC4_128_SHA                      PSK-RC4-SHA
+ PSK_WITH_3DES_EDE_CBC_SHA                 PSK-3DES-EDE-CBC-SHA
+ PSK_WITH_AES_128_CBC_SHA                  PSK-AES128-CBC-SHA
+ PSK_WITH_AES_256_CBC_SHA                  PSK-AES256-CBC-SHA
+
+ DHE_PSK_WITH_RC4_128_SHA                  DHE-PSK-RC4-SHA
+ DHE_PSK_WITH_3DES_EDE_CBC_SHA             DHE-PSK-3DES-EDE-CBC-SHA
+ DHE_PSK_WITH_AES_128_CBC_SHA              DHE-PSK-AES128-CBC-SHA
+ DHE_PSK_WITH_AES_256_CBC_SHA              DHE-PSK-AES256-CBC-SHA
+
+ RSA_PSK_WITH_RC4_128_SHA                  RSA-PSK-RC4-SHA
+ RSA_PSK_WITH_3DES_EDE_CBC_SHA             RSA-PSK-3DES-EDE-CBC-SHA
+ RSA_PSK_WITH_AES_128_CBC_SHA              RSA-PSK-AES128-CBC-SHA
+ RSA_PSK_WITH_AES_256_CBC_SHA              RSA-PSK-AES256-CBC-SHA
+
+ PSK_WITH_AES_128_GCM_SHA256               PSK-AES128-GCM-SHA256
+ PSK_WITH_AES_256_GCM_SHA384               PSK-AES256-GCM-SHA384
+ DHE_PSK_WITH_AES_128_GCM_SHA256           DHE-PSK-AES128-GCM-SHA256
+ DHE_PSK_WITH_AES_256_GCM_SHA384           DHE-PSK-AES256-GCM-SHA384
+ RSA_PSK_WITH_AES_128_GCM_SHA256           RSA-PSK-AES128-GCM-SHA256
+ RSA_PSK_WITH_AES_256_GCM_SHA384           RSA-PSK-AES256-GCM-SHA384
+
+ PSK_WITH_AES_128_CBC_SHA256               PSK-AES128-CBC-SHA256
+ PSK_WITH_AES_256_CBC_SHA384               PSK-AES256-CBC-SHA384
+ PSK_WITH_NULL_SHA256                      PSK-NULL-SHA256
+ PSK_WITH_NULL_SHA384                      PSK-NULL-SHA384
+ DHE_PSK_WITH_AES_128_CBC_SHA256           DHE-PSK-AES128-CBC-SHA256
+ DHE_PSK_WITH_AES_256_CBC_SHA384           DHE-PSK-AES256-CBC-SHA384
+ DHE_PSK_WITH_NULL_SHA256                  DHE-PSK-NULL-SHA256
+ DHE_PSK_WITH_NULL_SHA384                  DHE-PSK-NULL-SHA384
+ RSA_PSK_WITH_AES_128_CBC_SHA256           RSA-PSK-AES128-CBC-SHA256
+ RSA_PSK_WITH_AES_256_CBC_SHA384           RSA-PSK-AES256-CBC-SHA384
+ RSA_PSK_WITH_NULL_SHA256                  RSA-PSK-NULL-SHA256
+ RSA_PSK_WITH_NULL_SHA384                  RSA-PSK-NULL-SHA384
+ PSK_WITH_AES_128_GCM_SHA256               PSK-AES128-GCM-SHA256
+ PSK_WITH_AES_256_GCM_SHA384               PSK-AES256-GCM-SHA384
+
+ ECDHE_PSK_WITH_RC4_128_SHA                ECDHE-PSK-RC4-SHA
+ ECDHE_PSK_WITH_3DES_EDE_CBC_SHA           ECDHE-PSK-3DES-EDE-CBC-SHA
+ ECDHE_PSK_WITH_AES_128_CBC_SHA            ECDHE-PSK-AES128-CBC-SHA
+ ECDHE_PSK_WITH_AES_256_CBC_SHA            ECDHE-PSK-AES256-CBC-SHA
+ ECDHE_PSK_WITH_AES_128_CBC_SHA256         ECDHE-PSK-AES128-CBC-SHA256
+ ECDHE_PSK_WITH_AES_256_CBC_SHA384         ECDHE-PSK-AES256-CBC-SHA384
+ ECDHE_PSK_WITH_NULL_SHA                   ECDHE-PSK-NULL-SHA
+ ECDHE_PSK_WITH_NULL_SHA256                ECDHE-PSK-NULL-SHA256
+ ECDHE_PSK_WITH_NULL_SHA384                ECDHE-PSK-NULL-SHA384
+
+ PSK_WITH_CAMELLIA_128_CBC_SHA256          PSK-CAMELLIA128-SHA256
+ PSK_WITH_CAMELLIA_256_CBC_SHA384          PSK-CAMELLIA256-SHA384
+
+ DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256      DHE-PSK-CAMELLIA128-SHA256
+ DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384      DHE-PSK-CAMELLIA256-SHA384
+
+ RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256      RSA-PSK-CAMELLIA128-SHA256
+ RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384      RSA-PSK-CAMELLIA256-SHA384
+
+ ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256    ECDHE-PSK-CAMELLIA128-SHA256
+ ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384    ECDHE-PSK-CAMELLIA256-SHA384
 
 =head1 NOTES
 
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index c394191..6b6560d 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -204,6 +204,9 @@ 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_kECDHEPSK       "kECDHEPSK"
+# define SSL_TXT_kDHEPSK         "kDHEPSK"
 # define SSL_TXT_kGOST           "kGOST"
 # define SSL_TXT_kSRP            "kSRP"
 
diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h
index a172af3..1eef9cc 100644
--- a/include/openssl/tls1.h
+++ b/include/openssl/tls1.h
@@ -409,6 +409,45 @@ 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
 
+# define TLS1_CK_DHE_PSK_WITH_RC4_128_SHA                0x0300008E
+# define TLS1_CK_DHE_PSK_WITH_3DES_EDE_CBC_SHA           0x0300008F
+# define TLS1_CK_DHE_PSK_WITH_AES_128_CBC_SHA            0x03000090
+# define TLS1_CK_DHE_PSK_WITH_AES_256_CBC_SHA            0x03000091
+
+# 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
+
+/* 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_DHE_PSK_WITH_AES_128_GCM_SHA256         0x030000AA
+# define TLS1_CK_DHE_PSK_WITH_AES_256_GCM_SHA384         0x030000AB
+# 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_PSK_WITH_AES_128_CBC_SHA256             0x030000AE
+# define TLS1_CK_PSK_WITH_AES_256_CBC_SHA384             0x030000AF
+# define TLS1_CK_PSK_WITH_NULL_SHA256                    0x030000B0
+# define TLS1_CK_PSK_WITH_NULL_SHA384                    0x030000B1
+
+# define TLS1_CK_DHE_PSK_WITH_AES_128_CBC_SHA256         0x030000B2
+# define TLS1_CK_DHE_PSK_WITH_AES_256_CBC_SHA384         0x030000B3
+# define TLS1_CK_DHE_PSK_WITH_NULL_SHA256                0x030000B4
+# define TLS1_CK_DHE_PSK_WITH_NULL_SHA384                0x030000B5
+
+# define TLS1_CK_RSA_PSK_WITH_AES_128_CBC_SHA256         0x030000B6
+# define TLS1_CK_RSA_PSK_WITH_AES_256_CBC_SHA384         0x030000B7
+# define TLS1_CK_RSA_PSK_WITH_NULL_SHA256                0x030000B8
+# define TLS1_CK_RSA_PSK_WITH_NULL_SHA384                0x030000B9
+
+/* NULL PSK ciphersuites from RFC4785 */
+
+# define TLS1_CK_PSK_WITH_NULL_SHA                       0x0300002C
+# define TLS1_CK_DHE_PSK_WITH_NULL_SHA                   0x0300002D
+# define TLS1_CK_RSA_PSK_WITH_NULL_SHA                   0x0300002E
+
 /* AES ciphersuites from RFC3268 */
 
 # define TLS1_CK_RSA_WITH_AES_128_SHA                    0x0300002F
@@ -480,10 +519,6 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
 # define TLS1_CK_ADH_WITH_AES_128_GCM_SHA256             0x030000A6
 # define TLS1_CK_ADH_WITH_AES_256_GCM_SHA384             0x030000A7
 
-/* TLS v1.2 PSK GCM ciphersuites from RFC5487 */
-# define TLS1_CK_PSK_WITH_AES_128_GCM_SHA256             0x030000A8
-# define TLS1_CK_PSK_WITH_AES_256_GCM_SHA384             0x030000A9
-
 /* TLS 1.2 Camellia SHA-256 ciphersuites from RFC5932 */
 # define TLS1_CK_RSA_WITH_CAMELLIA_128_CBC_SHA256                0x030000BA
 # define TLS1_CK_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256             0x030000BB
@@ -565,6 +600,21 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
 # define TLS1_CK_ECDH_RSA_WITH_AES_128_GCM_SHA256        0x0300C031
 # define TLS1_CK_ECDH_RSA_WITH_AES_256_GCM_SHA384        0x0300C032
 
+/* ECDHE PSK ciphersuites from RFC5489 */
+# define TLS1_CK_ECDHE_PSK_WITH_RC4_128_SHA              0x0300C033
+# define TLS1_CK_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA         0x0300C034
+# define TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA          0x0300C035
+# define TLS1_CK_ECDHE_PSK_WITH_AES_256_CBC_SHA          0x0300C036
+
+# define TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA256       0x0300C037
+# define TLS1_CK_ECDHE_PSK_WITH_AES_256_CBC_SHA384       0x0300C038
+
+/* NULL PSK ciphersuites from RFC4785 */
+
+# define TLS1_CK_ECDHE_PSK_WITH_NULL_SHA                 0x0300C039
+# define TLS1_CK_ECDHE_PSK_WITH_NULL_SHA256              0x0300C03A
+# define TLS1_CK_ECDHE_PSK_WITH_NULL_SHA384              0x0300C03B
+
 /* Camellia-CBC ciphersuites from RFC6367 */
 # define TLS1_CK_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0x0300C072
 # define TLS1_CK_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0x0300C073
@@ -575,6 +625,15 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
 # define TLS1_CK_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256    0x0300C078
 # define TLS1_CK_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384    0x0300C079
 
+# define TLS1_CK_PSK_WITH_CAMELLIA_128_CBC_SHA256         0x0300C094
+# define TLS1_CK_PSK_WITH_CAMELLIA_256_CBC_SHA384         0x0300C095
+# define TLS1_CK_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256     0x0300C096
+# define TLS1_CK_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384     0x0300C097
+# define TLS1_CK_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256     0x0300C098
+# define TLS1_CK_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384     0x0300C099
+# define TLS1_CK_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256   0x0300C09A
+# define TLS1_CK_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384   0x0300C09B
+
 /*
  * XXX Backward compatibility alert: Older versions of OpenSSL gave some DHE
  * ciphers names with "EDH" instead of "DHE".  Going forward, we should be
@@ -589,6 +648,10 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
 # define TLS1_TXT_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA     "EXP1024-DHE-DSS-RC4-SHA"
 # define TLS1_TXT_DHE_DSS_WITH_RC4_128_SHA               "DHE-DSS-RC4-SHA"
 
+# define TLS1_TXT_PSK_WITH_NULL_SHA                      "PSK-NULL-SHA"
+# define TLS1_TXT_DHE_PSK_WITH_NULL_SHA                  "DHE-PSK-NULL-SHA"
+# define TLS1_TXT_RSA_PSK_WITH_NULL_SHA                  "RSA-PSK-NULL-SHA"
+
 /* AES ciphersuites from RFC3268 */
 # define TLS1_TXT_RSA_WITH_AES_128_SHA                   "AES128-SHA"
 # define TLS1_TXT_DH_DSS_WITH_AES_128_SHA                "DH-DSS-AES128-SHA"
@@ -641,6 +704,38 @@ 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"
 
+# define TLS1_TXT_DHE_PSK_WITH_RC4_128_SHA               "DHE-PSK-RC4-SHA"
+# define TLS1_TXT_DHE_PSK_WITH_3DES_EDE_CBC_SHA          "DHE-PSK-3DES-EDE-CBC-SHA"
+# define TLS1_TXT_DHE_PSK_WITH_AES_128_CBC_SHA           "DHE-PSK-AES128-CBC-SHA"
+# define TLS1_TXT_DHE_PSK_WITH_AES_256_CBC_SHA           "DHE-PSK-AES256-CBC-SHA"
+# 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"
+
+/* 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_DHE_PSK_WITH_AES_128_GCM_SHA256        "DHE-PSK-AES128-GCM-SHA256"
+# define TLS1_TXT_DHE_PSK_WITH_AES_256_GCM_SHA384        "DHE-PSK-AES256-GCM-SHA384"
+# 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_PSK_WITH_AES_128_CBC_SHA256            "PSK-AES128-CBC-SHA256"
+# define TLS1_TXT_PSK_WITH_AES_256_CBC_SHA384            "PSK-AES256-CBC-SHA384"
+# define TLS1_TXT_PSK_WITH_NULL_SHA256                   "PSK-NULL-SHA256"
+# define TLS1_TXT_PSK_WITH_NULL_SHA384                   "PSK-NULL-SHA384"
+
+# define TLS1_TXT_DHE_PSK_WITH_AES_128_CBC_SHA256        "DHE-PSK-AES128-CBC-SHA256"
+# define TLS1_TXT_DHE_PSK_WITH_AES_256_CBC_SHA384        "DHE-PSK-AES256-CBC-SHA384"
+# define TLS1_TXT_DHE_PSK_WITH_NULL_SHA256               "DHE-PSK-NULL-SHA256"
+# define TLS1_TXT_DHE_PSK_WITH_NULL_SHA384               "DHE-PSK-NULL-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"
+# define TLS1_TXT_RSA_PSK_WITH_NULL_SHA256               "RSA-PSK-NULL-SHA256"
+# define TLS1_TXT_RSA_PSK_WITH_NULL_SHA384               "RSA-PSK-NULL-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"
@@ -682,6 +777,15 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
 # define TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256           "DHE-RSA-CAMELLIA256-SHA256"
 # define TLS1_TXT_ADH_WITH_CAMELLIA_256_CBC_SHA256               "ADH-CAMELLIA256-SHA256"
 
+# define TLS1_TXT_PSK_WITH_CAMELLIA_128_CBC_SHA256               "PSK-CAMELLIA128-SHA256"
+# define TLS1_TXT_PSK_WITH_CAMELLIA_256_CBC_SHA384               "PSK-CAMELLIA256-SHA384"
+# define TLS1_TXT_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256           "DHE-PSK-CAMELLIA128-SHA256"
+# define TLS1_TXT_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384           "DHE-PSK-CAMELLIA256-SHA384"
+# define TLS1_TXT_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256           "RSA-PSK-CAMELLIA128-SHA256"
+# define TLS1_TXT_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384           "RSA-PSK-CAMELLIA256-SHA384"
+# define TLS1_TXT_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256         "ECDHE-PSK-CAMELLIA128-SHA256"
+# define TLS1_TXT_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384         "ECDHE-PSK-CAMELLIA256-SHA384"
+
 /* SEED ciphersuites from RFC4162 */
 # define TLS1_TXT_RSA_WITH_SEED_SHA                      "SEED-SHA"
 # define TLS1_TXT_DH_DSS_WITH_SEED_SHA                   "DH-DSS-SEED-SHA"
@@ -744,6 +848,19 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
 # 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"
 
+/* ECDHE PSK ciphersuites from RFC 5489 */
+# define TLS1_TXT_ECDHE_PSK_WITH_RC4_128_SHA               "ECDHE-PSK-RC4-SHA"
+# define TLS1_TXT_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA          "ECDHE-PSK-3DES-EDE-CBC-SHA"
+# define TLS1_TXT_ECDHE_PSK_WITH_AES_128_CBC_SHA           "ECDHE-PSK-AES128-CBC-SHA"
+# define TLS1_TXT_ECDHE_PSK_WITH_AES_256_CBC_SHA           "ECDHE-PSK-AES256-CBC-SHA"
+
+# define TLS1_TXT_ECDHE_PSK_WITH_AES_128_CBC_SHA256        "ECDHE-PSK-AES128-CBC-SHA256"
+# define TLS1_TXT_ECDHE_PSK_WITH_AES_256_CBC_SHA384        "ECDHE-PSK-AES256-CBC-SHA384"
+
+# define TLS1_TXT_ECDHE_PSK_WITH_NULL_SHA                  "ECDHE-PSK-NULL-SHA"
+# define TLS1_TXT_ECDHE_PSK_WITH_NULL_SHA256               "ECDHE-PSK-NULL-SHA256"
+# define TLS1_TXT_ECDHE_PSK_WITH_NULL_SHA384               "ECDHE-PSK-NULL-SHA384"
+
 /* Camellia-CBC ciphersuites from RFC6367 */
 # define TLS1_TXT_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 "ECDHE-ECDSA-CAMELLIA128-SHA256"
 # define TLS1_TXT_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 "ECDHE-ECDSA-CAMELLIA256-SHA384"
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 04af851..080dbf0 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -331,10 +331,8 @@ int ssl3_connect(SSL *s)
 
             /* Check if it is anon DH/ECDH, SRP auth */
             /* or PSK */
-            if (!
-                (s->s3->tmp.
-                 new_cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP))
-                    && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) {
+            if (!(s->s3->tmp.new_cipher->algorithm_auth &
+                    (SSL_aNULL | SSL_aSRP | SSL_aPSK))) {
                 ret = ssl3_get_server_certificate(s);
                 if (ret <= 0)
                     goto end;
@@ -1414,7 +1412,7 @@ int ssl3_get_key_exchange(SSL *s)
          * Can't skip server key exchange if this is an ephemeral
          * ciphersuite.
          */
-        if (alg_k & (SSL_kDHE | SSL_kECDHE)) {
+        if (alg_k & (SSL_kDHE | SSL_kECDHE | SSL_kDHEPSK | SSL_kECDHEPSK)) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_UNEXPECTED_MESSAGE);
             al = SSL_AD_UNEXPECTED_MESSAGE;
             goto f_err;
@@ -1447,8 +1445,8 @@ int ssl3_get_key_exchange(SSL *s)
     al = SSL_AD_DECODE_ERROR;
 
 #ifndef OPENSSL_NO_PSK
-    if (alg_k & SSL_kPSK) {
-        char tmp_id_hint[PSK_MAX_IDENTITY_LEN + 1];
+    /* PSK ciphersuites are preceded by an identity hint */
+    if (alg_k & SSL_PSK) {
 
         param_len = 2;
         if (param_len > n) {
@@ -1475,23 +1473,24 @@ int ssl3_get_key_exchange(SSL *s)
         }
         param_len += i;
 
-        /*
-         * If received PSK identity hint contains NULL characters, the hint
-         * is truncated from the first NULL. p may not be ending with NULL,
-         * so create a NULL-terminated string.
-         */
-        memcpy(tmp_id_hint, p, i);
-        memset(tmp_id_hint + i, 0, PSK_MAX_IDENTITY_LEN + 1 - i);
         OPENSSL_free(s->session->psk_identity_hint);
-        s->session->psk_identity_hint = BUF_strdup(tmp_id_hint);
-        if (s->session->psk_identity_hint == NULL) {
-            al = SSL_AD_HANDSHAKE_FAILURE;
-            SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
-            goto f_err;
+        if (i != 0) {
+            s->session->psk_identity_hint = BUF_strndup((char *)p, i);
+            if (s->session->psk_identity_hint == NULL) {
+                al = SSL_AD_HANDSHAKE_FAILURE;
+                SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
+                goto f_err;
+            }
+        } else {
+            s->session->psk_identity_hint = NULL;
         }
 
         p += i;
         n -= param_len;
+    }
+
+    /* Nothing else to do for plain PSK or RSAPSK */
+    if (alg_k & (SSL_kPSK | SSL_kRSAPSK)) {
     } else
 #endif                          /* !OPENSSL_NO_PSK */
 #ifndef OPENSSL_NO_SRP
@@ -1661,7 +1660,7 @@ int ssl3_get_key_exchange(SSL *s)
     if (0) ;
 #endif
 #ifndef OPENSSL_NO_DH
-    else if (alg_k & SSL_kDHE) {
+    else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
         if ((dh = DH_new()) == NULL) {
             SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_DH_LIB);
             goto err;
@@ -1742,7 +1741,7 @@ int ssl3_get_key_exchange(SSL *s)
 #endif                          /* !OPENSSL_NO_DH */
 
 #ifndef OPENSSL_NO_EC
-    else if (alg_k & SSL_kECDHE) {
+    else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
         EC_GROUP *ngroup;
         const EC_GROUP *group;
 
@@ -1945,8 +1944,8 @@ 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 or PSK do not need public keys */
+        if (!(alg_a & (SSL_aNULL | SSL_aSRP)) && !(alg_k & SSL_PSK)) {
             /* Might be wrong key type, check it */
             if (ssl3_check_cert_and_algorithm(s))
                 /* Otherwise this shouldn't happen */
@@ -2329,6 +2328,9 @@ int ssl3_send_client_key_exchange(SSL *s)
 {
     unsigned char *p;
     int n;
+#ifndef OPENSSL_NO_PSK
+    size_t pskhdrlen = 0;
+#endif
     unsigned long alg_k;
 #ifndef OPENSSL_NO_RSA
     unsigned char *q;
@@ -2344,17 +2346,93 @@ int ssl3_send_client_key_exchange(SSL *s)
 #endif
     unsigned char *pms = NULL;
     size_t pmslen = 0;
+    alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
 
     if (s->state == SSL3_ST_CW_KEY_EXCH_A) {
         p = ssl_handshake_start(s);
 
-        alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+
+#ifndef OPENSSL_NO_PSK
+        if (alg_k & SSL_PSK) {
+            int psk_err = 1;
+            /*
+             * 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 + 1];
+            size_t identitylen;
+            unsigned char psk[PSK_MAX_PSK_LEN];
+            size_t psklen;
+
+            if (s->psk_client_callback == NULL) {
+                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+                       SSL_R_PSK_NO_CLIENT_CB);
+                goto err;
+            }
+
+            memset(identity, 0, sizeof(identity));
+
+            psklen = s->psk_client_callback(s, s->session->psk_identity_hint,
+                                            identity, sizeof(identity) - 1,
+                                            psk, sizeof(psk));
+
+            if (psklen > PSK_MAX_PSK_LEN) {
+                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+                       ERR_R_INTERNAL_ERROR);
+                goto psk_err;
+            } else if (psklen == 0) {
+                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+                       SSL_R_PSK_IDENTITY_NOT_FOUND);
+                goto psk_err;
+            }
+
+            OPENSSL_free(s->s3->tmp.psk);
+            s->s3->tmp.psk = BUF_memdup(psk, psklen);
+            OPENSSL_cleanse(psk, psklen);
+
+            if (s->s3->tmp.psk == NULL) {
+                OPENSSL_cleanse(identity, sizeof(identity));
+                goto memerr;
+            }
+
+            s->s3->tmp.psklen = psklen;
+
+            identitylen = strlen(identity);
+            if (identitylen > PSK_MAX_IDENTITY_LEN) {
+                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+                       ERR_R_INTERNAL_ERROR);
+                goto psk_err;
+            }
+            OPENSSL_free(s->session->psk_identity);
+            s->session->psk_identity = BUF_strdup(identity);
+            if (s->session->psk_identity == NULL) {
+                OPENSSL_cleanse(identity, sizeof(identity));
+                goto memerr;
+            }
+
+            s2n(identitylen, p);
+            memcpy(p, identity, identitylen);
+            pskhdrlen = 2 + identitylen;
+            p += identitylen;
+            psk_err = 0;
+ psk_err:
+            OPENSSL_cleanse(identity, sizeof(identity));
+            if (psk_err != 0) {
+                ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+                goto err;
+            }
+        }
+        if (alg_k & SSL_kPSK) {
+            n = 0;
+        } else
+#endif
 
         /* Fool emacs indentation */
         if (0) {
         }
 #ifndef OPENSSL_NO_RSA
-        else if (alg_k & SSL_kRSA) {
+        else if (alg_k & (SSL_kRSA | SSL_kRSAPSK)) {
             RSA *rsa;
             pmslen = SSL_MAX_MASTER_KEY_LENGTH;
             pms = OPENSSL_malloc(pmslen);
@@ -2414,7 +2492,7 @@ int ssl3_send_client_key_exchange(SSL *s)
         }
 #endif
 #ifndef OPENSSL_NO_DH
-        else if (alg_k & (SSL_kDHE | SSL_kDHr | SSL_kDHd)) {
+        else if (alg_k & (SSL_kDHE | SSL_kDHr | SSL_kDHd | SSL_kDHEPSK)) {
             DH *dh_srvr, *dh_clnt;
             if (s->s3->peer_dh_tmp != NULL)
                 dh_srvr = s->s3->peer_dh_tmp;
@@ -2493,7 +2571,7 @@ int ssl3_send_client_key_exchange(SSL *s)
 #endif
 
 #ifndef OPENSSL_NO_EC
-        else if (alg_k & (SSL_kECDHE | SSL_kECDHr | SSL_kECDHe)) {
+        else if (alg_k & (SSL_kECDHE | SSL_kECDHr | SSL_kECDHe | SSL_kECDHEPSK)) {
             const EC_GROUP *srvr_group = NULL;
             EC_KEY *tkey;
             int ecdh_clnt_cert = 0;
@@ -2781,88 +2859,16 @@ int ssl3_send_client_key_exchange(SSL *s)
             }
         }
 #endif
-#ifndef OPENSSL_NO_PSK
-        else if (alg_k & SSL_kPSK) {
-            /*
-             * The callback needs PSK_MAX_IDENTITY_LEN + 1 bytes to return a
-             * \0-terminated identity. The last byte is for us for simulating
-             * strnlen.
-             */
-            char identity[PSK_MAX_IDENTITY_LEN + 2];
-            size_t identity_len;
-            unsigned char *t = NULL;
-            unsigned int psk_len = 0;
-            int psk_err = 1;
-
-            n = 0;
-            if (s->psk_client_callback == NULL) {
-                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
-                       SSL_R_PSK_NO_CLIENT_CB);
-                goto err;
-            }
-
-            memset(identity, 0, sizeof(identity));
-            /* Allocate maximum size buffer */
-            pmslen = PSK_MAX_PSK_LEN * 2 + 4;
-            pms = OPENSSL_malloc(pmslen);
-            if (!pms)
-                goto memerr;
-
-            psk_len = s->psk_client_callback(s, s->session->psk_identity_hint,
-                                             identity, sizeof(identity) - 1,
-                                             pms, pmslen);
-            if (psk_len > PSK_MAX_PSK_LEN) {
-                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
-                       ERR_R_INTERNAL_ERROR);
-                goto psk_err;
-            } else if (psk_len == 0) {
-                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
-                       SSL_R_PSK_IDENTITY_NOT_FOUND);
-                goto psk_err;
-            }
-            /* Change pmslen to real length */
-            pmslen = 2 + psk_len + 2 + psk_len;
-            identity[PSK_MAX_IDENTITY_LEN + 1] = '\0';
-            identity_len = strlen(identity);
-            if (identity_len > PSK_MAX_IDENTITY_LEN) {
-                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
-                       ERR_R_INTERNAL_ERROR);
-                goto psk_err;
-            }
-            /* create PSK pre_master_secret */
-            t = pms;
-            memmove(pms + psk_len + 4, pms, psk_len);
-            s2n(psk_len, t);
-            memset(t, 0, psk_len);
-            t += psk_len;
-            s2n(psk_len, t);
-
-            OPENSSL_free(s->session->psk_identity);
-            s->session->psk_identity = BUF_strdup(identity);
-            if (s->session->psk_identity == NULL) {
-                SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
-                       ERR_R_MALLOC_FAILURE);
-                goto psk_err;
-            }
-
-            s2n(identity_len, p);
-            memcpy(p, identity, identity_len);
-            n = 2 + identity_len;
-            psk_err = 0;
- psk_err:
-            OPENSSL_cleanse(identity, sizeof(identity));
-            if (psk_err != 0) {
-                ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
-                goto err;
-            }
-        }
-#endif
         else {
             ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
             SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
             goto err;
         }
 
+#ifndef OPENSSL_NO_PSK
+        n += pskhdrlen;
+#endif
+
         if (!ssl_set_handshake_header(s, SSL3_MT_CLIENT_KEY_EXCHANGE, n)) {
             ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
             SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
@@ -2876,7 +2882,7 @@ int ssl3_send_client_key_exchange(SSL *s)
     n = ssl_do_write(s);
 #ifndef OPENSSL_NO_SRP
     /* Check for SRP */
-    if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) {
+    if (alg_k & SSL_kSRP) {
         /*
          * If everything written generate master key: no need to save PMS as
          * srp_generate_client_master_secret generates it internally.
@@ -2900,7 +2906,7 @@ int ssl3_send_client_key_exchange(SSL *s)
             pms = s->s3->tmp.pms;
             pmslen = s->s3->tmp.pmslen;
         }
-        if (pms == NULL) {
+        if (pms == NULL && !(alg_k & SSL_kPSK)) {
             ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
             SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
             goto err;
@@ -2924,6 +2930,10 @@ int ssl3_send_client_key_exchange(SSL *s)
     EC_KEY_free(clnt_ecdh);
     EVP_PKEY_free(srvr_pub_pkey);
 #endif
+#ifndef OPENSSL_NO_PSK
+    OPENSSL_clear_free(s->s3->tmp.psk, s->s3->tmp.psklen);
+    s->s3->tmp.psk = NULL;
+#endif
     s->state = SSL_ST_ERR;
     return (-1);
 }
@@ -3261,7 +3271,7 @@ int ssl3_check_cert_and_algorithm(SSL *s)
     }
 #endif
 #ifndef OPENSSL_NO_RSA
-    if (alg_k & SSL_kRSA) {
+    if (alg_k & (SSL_kRSA | SSL_kRSAPSK)) {
         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,
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 8b7c52a..0fc0881 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -600,6 +600,53 @@ OPENSSL_GLOBAL const SSL_CIPHER ssl3_ciphers[] = {
      112,
      168,
      },
+#ifndef OPENSSL_NO_PSK
+    /* Cipher 2C */
+    {
+     1,
+     TLS1_TXT_PSK_WITH_NULL_SHA,
+     TLS1_CK_PSK_WITH_NULL_SHA,
+     SSL_kPSK,
+     SSL_aPSK,
+     SSL_eNULL,
+     SSL_SHA1,
+     SSL_TLSV1,
+     SSL_NOT_EXP | SSL_STRONG_NONE | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+     0,
+     0,
+     },
+    /* Cipher 2D */
+    {
+     1,
+     TLS1_TXT_DHE_PSK_WITH_NULL_SHA,
+     TLS1_CK_DHE_PSK_WITH_NULL_SHA,
+     SSL_kDHEPSK,
+     SSL_aPSK,
+     SSL_eNULL,
+     SSL_SHA1,
+     SSL_TLSV1,
+     SSL_NOT_EXP | SSL_STRONG_NONE | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+     0,
+     0,
+     },
+    /* Cipher 2E */
+    {
+     1,
+     TLS1_TXT_RSA_PSK_WITH_NULL_SHA,
+     TLS1_CK_RSA_PSK_WITH_NULL_SHA,
+     SSL_kRSAPSK,
+     SSL_aRSA,
+     SSL_eNULL,
+     SSL_SHA1,
+     SSL_TLSV1,
+     SSL_NOT_EXP | SSL_STRONG_NONE | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+     0,
+     0,
+     },
+#endif
 
 /* New AES ciphersuites */
 /* Cipher 2F */
@@ -1253,6 +1300,7 @@ OPENSSL_GLOBAL const SSL_CIPHER ssl3_ciphers[] = {
 #endif                          /* OPENSSL_NO_CAMELLIA */
 
 #ifndef OPENSSL_NO_PSK
+    /* PSK ciphersuites from RFC 4279 */
     /* Cipher 8A */
     {
      1,
@@ -1316,6 +1364,134 @@ OPENSSL_GLOBAL const SSL_CIPHER ssl3_ciphers[] = {
      256,
      256,
      },
+
+    /* Cipher 8E */
+    {
+     1,
+     TLS1_TXT_DHE_PSK_WITH_RC4_128_SHA,
+     TLS1_CK_DHE_PSK_WITH_RC4_128_SHA,
+     SSL_kDHEPSK,
+     SSL_aPSK,
+     SSL_RC4,
+     SSL_SHA1,
+     SSL_TLSV1,
+     SSL_NOT_EXP | SSL_MEDIUM,
+     SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+     128,
+     128,
+     },
+
+    /* Cipher 8F */
+    {
+     1,
+     TLS1_TXT_DHE_PSK_WITH_3DES_EDE_CBC_SHA,
+     TLS1_CK_DHE_PSK_WITH_3DES_EDE_CBC_SHA,
+     SSL_kDHEPSK,
+     SSL_aPSK,
+     SSL_3DES,
+     SSL_SHA1,
+     SSL_TLSV1,
+     SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+     112,
+     168,
+     },
+
+    /* Cipher 90 */
+    {
+     1,
+     TLS1_TXT_DHE_PSK_WITH_AES_128_CBC_SHA,
+     TLS1_CK_DHE_PSK_WITH_AES_128_CBC_SHA,
+     SSL_kDHEPSK,
+     SSL_aPSK,
+     SSL_AES128,
+     SSL_SHA1,
+     SSL_TLSV1,
+     SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+     128,
+     128,
+     },
+
+    /* Cipher 91 */
+    {
+     1,
+     TLS1_TXT_DHE_PSK_WITH_AES_256_CBC_SHA,
+     TLS1_CK_DHE_PSK_WITH_AES_256_CBC_SHA,
+     SSL_kDHEPSK,
+     SSL_aPSK,
+     SSL_AES256,
+     SSL_SHA1,
+     SSL_TLSV1,
+     SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+     256,
+     256,
+     },
+
+    /* 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_FIPS,
+     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_FIPS,
+     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_FIPS,
+     SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+     256,
+     256,
+     },
 #endif                          /* OPENSSL_NO_PSK */
 
 #ifndef OPENSSL_NO_SEED
@@ -1597,55 +1773,312 @@ OPENSSL_GLOBAL const SSL_CIPHER ssl3_ciphers[] = {
      128,
      },
 
-    /* Cipher A7 */
+    /* Cipher A7 */
+    {
+     1,
+     TLS1_TXT_ADH_WITH_AES_256_GCM_SHA384,
+     TLS1_CK_ADH_WITH_AES_256_GCM_SHA384,
+     SSL_kDHE,
+     SSL_aNULL,
+     SSL_AES256GCM,
+     SSL_AEAD,
+     SSL_TLSV1_2,
+     SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+     256,
+     256,
+     },
+#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_FIPS,
+     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_FIPS,
+     SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+     256,
+     256,
+     },
+
+    /* Cipher AA */
+    {
+     1,
+     TLS1_TXT_DHE_PSK_WITH_AES_128_GCM_SHA256,
+     TLS1_CK_DHE_PSK_WITH_AES_128_GCM_SHA256,
+     SSL_kDHEPSK,
+     SSL_aPSK,
+     SSL_AES128GCM,
+     SSL_AEAD,
+     SSL_TLSV1_2,
+     SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+     128,
+     128,
+     },
+
+    /* Cipher AB */
+    {
+     1,
+     TLS1_TXT_DHE_PSK_WITH_AES_256_GCM_SHA384,
+     TLS1_CK_DHE_PSK_WITH_AES_256_GCM_SHA384,
+     SSL_kDHEPSK,
+     SSL_aPSK,
+     SSL_AES256GCM,
+     SSL_AEAD,
+     SSL_TLSV1_2,
+     SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+     256,
+     256,
+     },
+
+    /* 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_FIPS,
+     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_FIPS,
+     SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+     256,
+     256,
+     },
+
+    /* 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_FIPS,
+     SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+     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_FIPS,
+     SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+     256,
+     256,
+     },
+
+    /* Cipher B0 */
+    {
+     1,
+     TLS1_TXT_PSK_WITH_NULL_SHA256,
+     TLS1_CK_PSK_WITH_NULL_SHA256,
+     SSL_kPSK,
+     SSL_aPSK,
+     SSL_eNULL,
+     SSL_SHA256,
+     SSL_TLSV1,
+     SSL_NOT_EXP | SSL_STRONG_NONE | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+     0,
+     0,
+     },
+
+    /* Cipher B1 */
+    {
+     1,
+     TLS1_TXT_PSK_WITH_NULL_SHA384,
+     TLS1_CK_PSK_WITH_NULL_SHA384,
+     SSL_kPSK,
+     SSL_aPSK,
+     SSL_eNULL,
+     SSL_SHA384,
+     SSL_TLSV1,
+     SSL_NOT_EXP | SSL_STRONG_NONE | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+     0,
+     0,
+     },
+
+    /* Cipher B2 */
+    {
+     1,
+     TLS1_TXT_DHE_PSK_WITH_AES_128_CBC_SHA256,
+     TLS1_CK_DHE_PSK_WITH_AES_128_CBC_SHA256,
+     SSL_kDHEPSK,
+     SSL_aPSK,
+     SSL_AES128,
+     SSL_SHA256,
+     SSL_TLSV1,
+     SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+     128,
+     128,
+     },
+
+    /* Cipher B3 */
+    {
+     1,
+     TLS1_TXT_DHE_PSK_WITH_AES_256_CBC_SHA384,
+     TLS1_CK_DHE_PSK_WITH_AES_256_CBC_SHA384,
+     SSL_kDHEPSK,
+     SSL_aPSK,
+     SSL_AES256,
+     SSL_SHA384,
+     SSL_TLSV1,
+     SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+     256,
+     256,
+     },
+
+    /* Cipher B4 */
+    {
+     1,
+     TLS1_TXT_DHE_PSK_WITH_NULL_SHA256,
+     TLS1_CK_DHE_PSK_WITH_NULL_SHA256,
+     SSL_kDHEPSK,
+     SSL_aPSK,
+     SSL_eNULL,
+     SSL_SHA256,
+     SSL_TLSV1,
+     SSL_NOT_EXP | SSL_STRONG_NONE | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+     0,
+     0,
+     },
+
+    /* Cipher B5 */
+    {
+     1,
+     TLS1_TXT_DHE_PSK_WITH_NULL_SHA384,
+     TLS1_CK_DHE_PSK_WITH_NULL_SHA384,
+     SSL_kDHEPSK,
+     SSL_aPSK,
+     SSL_eNULL,
+     SSL_SHA384,
+     SSL_TLSV1,
+     SSL_NOT_EXP | SSL_STRONG_NONE | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+     0,
+     0,
+     },
+
+    /* 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_FIPS,
+     SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+     128,
+     128,
+     },
+
+    /* Cipher B7 */
     {
      1,
-     TLS1_TXT_ADH_WITH_AES_256_GCM_SHA384,
-     TLS1_CK_ADH_WITH_AES_256_GCM_SHA384,
-     SSL_kDHE,
-     SSL_aNULL,
-     SSL_AES256GCM,
-     SSL_AEAD,
-     SSL_TLSV1_2,
+     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_FIPS,
      SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
      256,
      256,
      },
-#ifndef OPENSSL_NO_PSK
-    /* Cipher A8 */
+
+    /* Cipher B8 */
     {
      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_FIPS,
-     SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
-     128,
-     128,
+     TLS1_TXT_RSA_PSK_WITH_NULL_SHA256,
+     TLS1_CK_RSA_PSK_WITH_NULL_SHA256,
+     SSL_kRSAPSK,
+     SSL_aRSA,
+     SSL_eNULL,
+     SSL_SHA256,
+     SSL_TLSV1,
+     SSL_NOT_EXP | SSL_STRONG_NONE | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+     0,
+     0,
      },
 
-    /* Cipher A9 */
+    /* Cipher B9 */
     {
      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_FIPS,
+     TLS1_TXT_RSA_PSK_WITH_NULL_SHA384,
+     TLS1_CK_RSA_PSK_WITH_NULL_SHA384,
+     SSL_kRSAPSK,
+     SSL_aRSA,
+     SSL_eNULL,
+     SSL_SHA384,
+     SSL_TLSV1,
+     SSL_NOT_EXP | SSL_STRONG_NONE | SSL_FIPS,
      SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
-     256,
-     256,
+     0,
+     0,
      },
-
-#endif
+#endif                          /* OPENSSL_NO_PSK */
 
 #ifndef OPENSSL_NO_CAMELLIA
     /* TLS 1.2 Camellia SHA-256 ciphersuites from RFC5932 */
@@ -2669,6 +3102,151 @@ OPENSSL_GLOBAL const SSL_CIPHER ssl3_ciphers[] = {
      256,
      },
 
+    /* PSK ciphersuites from RFC 5489 */
+    /* Cipher C033 */
+    {
+     1,
+     TLS1_TXT_ECDHE_PSK_WITH_RC4_128_SHA,
+     TLS1_CK_ECDHE_PSK_WITH_RC4_128_SHA,
+     SSL_kECDHEPSK,
+     SSL_aPSK,
+     SSL_RC4,
+     SSL_SHA1,
+     SSL_TLSV1,
+     SSL_NOT_EXP | SSL_MEDIUM,
+     SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+     128,
+     128,
+     },
+
+    /* Cipher C034 */
+    {
+     1,
+     TLS1_TXT_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,
+     TLS1_CK_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,
+     SSL_kECDHEPSK,
+     SSL_aPSK,
+     SSL_3DES,
+     SSL_SHA1,
+     SSL_TLSV1,
+     SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+     112,
+     168,
+     },
+
+    /* Cipher C035 */
+    {
+     1,
+     TLS1_TXT_ECDHE_PSK_WITH_AES_128_CBC_SHA,
+     TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA,
+     SSL_kECDHEPSK,
+     SSL_aPSK,
+     SSL_AES128,
+     SSL_SHA1,
+     SSL_TLSV1,
+     SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+     128,
+     128,
+     },
+
+    /* Cipher C036 */
+    {
+     1,
+     TLS1_TXT_ECDHE_PSK_WITH_AES_256_CBC_SHA,
+     TLS1_CK_ECDHE_PSK_WITH_AES_256_CBC_SHA,
+     SSL_kECDHEPSK,
+     SSL_aPSK,
+     SSL_AES256,
+     SSL_SHA1,
+     SSL_TLSV1,
+     SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+     256,
+     256,
+     },
+
+    /* Cipher C037 */
+    {
+     1,
+     TLS1_TXT_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
+     TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
+     SSL_kECDHEPSK,
+     SSL_aPSK,
+     SSL_AES128,
+     SSL_SHA256,
+     SSL_TLSV1,
+     SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+     128,
+     128,
+     },
+
+    /* Cipher C038 */
+    {
+     1,
+     TLS1_TXT_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
+     TLS1_CK_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
+     SSL_kECDHEPSK,
+     SSL_aPSK,
+     SSL_AES256,
+     SSL_SHA384,
+     SSL_TLSV1,
+     SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+     256,
+     256,
+     },
+
+    /* Cipher C039 */
+    {
+     1,
+     TLS1_TXT_ECDHE_PSK_WITH_NULL_SHA,
+     TLS1_CK_ECDHE_PSK_WITH_NULL_SHA,
+     SSL_kECDHEPSK,
+     SSL_aPSK,
+     SSL_eNULL,
+     SSL_SHA1,
+     SSL_TLSV1,
+     SSL_NOT_EXP | SSL_STRONG_NONE | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+     0,
+     0,
+     },
+
+    /* Cipher C03A */
+    {
+     1,
+     TLS1_TXT_ECDHE_PSK_WITH_NULL_SHA256,
+     TLS1_CK_ECDHE_PSK_WITH_NULL_SHA256,
+     SSL_kECDHEPSK,
+     SSL_aPSK,
+     SSL_eNULL,
+     SSL_SHA256,
+     SSL_TLSV1,
+     SSL_NOT_EXP | SSL_STRONG_NONE | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+     0,
+     0,
+     },
+
+    /* Cipher C03B */
+    {
+     1,
+     TLS1_TXT_ECDHE_PSK_WITH_NULL_SHA384,
+     TLS1_CK_ECDHE_PSK_WITH_NULL_SHA384,
+     SSL_kECDHEPSK,
+     SSL_aPSK,
+     SSL_eNULL,
+     SSL_SHA384,
+     SSL_TLSV1,
+     SSL_NOT_EXP | SSL_STRONG_NONE | SSL_FIPS,
+     SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+     0,
+     0,
+     },
+
 # ifndef OPENSSL_NO_CAMELLIA
     {                           /* Cipher C072 */
      1,
@@ -2784,6 +3362,120 @@ OPENSSL_GLOBAL const SSL_CIPHER ssl3_ciphers[] = {
 # endif                         /* OPENSSL_NO_CAMELLIA */
 #endif                          /* OPENSSL_NO_EC */
 
+#if !defined(OPENSSL_NO_CAMELLIA) && !defined(OPENSSL_NO_PSK)
+    {                           /* Cipher C094 */
+     1,
+     TLS1_TXT_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+     TLS1_CK_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+     SSL_kPSK,
+     SSL_aPSK,
+     SSL_CAMELLIA128,
+     SSL_SHA256,
+     SSL_TLSV1,
+     SSL_NOT_EXP | SSL_HIGH,
+     SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+     128,
+     128},
+
+    {                           /* Cipher C095 */
+     1,
+     TLS1_TXT_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+     TLS1_CK_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+     SSL_kPSK,
+     SSL_aPSK,
+     SSL_CAMELLIA256,
+     SSL_SHA384,
+     SSL_TLSV1,
+     SSL_NOT_EXP | SSL_HIGH,
+     SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+     256,
+     256},
+
+    {                           /* Cipher C096 */
+     1,
+     TLS1_TXT_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+     TLS1_CK_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+     SSL_kDHEPSK,
+     SSL_aPSK,
+     SSL_CAMELLIA128,
+     SSL_SHA256,
+     SSL_TLSV1,
+     SSL_NOT_EXP | SSL_HIGH,
+     SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+     128,
+     128},
+
+    {                           /* Cipher C097 */
+     1,
+     TLS1_TXT_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+     TLS1_CK_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+     SSL_kDHEPSK,
+     SSL_aPSK,
+     SSL_CAMELLIA256,
+     SSL_SHA384,
+     SSL_TLSV1,
+     SSL_NOT_EXP | SSL_HIGH,
+     SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+     256,
+     256},
+
+    {                           /* Cipher C098 */
+     1,
+     TLS1_TXT_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+     TLS1_CK_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+     SSL_kRSAPSK,
+     SSL_aRSA,
+     SSL_CAMELLIA128,
+     SSL_SHA256,
+     SSL_TLSV1,
+     SSL_NOT_EXP | SSL_HIGH,
+     SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+     128,
+     128},
+
+    {                           /* Cipher C099 */
+     1,
+     TLS1_TXT_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+     TLS1_CK_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+     SSL_kRSAPSK,
+     SSL_aRSA,
+     SSL_CAMELLIA256,
+     SSL_SHA384,
+     SSL_TLSV1,
+     SSL_NOT_EXP | SSL_HIGH,
+     SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+     256,
+     256},
+
+    {                           /* Cipher C09A */
+     1,
+     TLS1_TXT_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+     TLS1_CK_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+     SSL_kECDHEPSK,
+     SSL_aPSK,
+     SSL_CAMELLIA128,
+     SSL_SHA256,
+     SSL_TLSV1,
+     SSL_NOT_EXP | SSL_HIGH,
+     SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
+     128,
+     128},
+
+    {                           /* Cipher C09B */
+     1,
+     TLS1_TXT_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+     TLS1_CK_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+     SSL_kECDHEPSK,
+     SSL_aPSK,
+     SSL_CAMELLIA256,
+     SSL_SHA384,
+     SSL_TLSV1,
+     SSL_NOT_EXP | SSL_HIGH,
+     SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
+     256,
+     256},
+#endif
+
 #ifdef TEMP_GOST_TLS
 /* Cipher FF00 */
     {
@@ -3933,7 +4625,7 @@ SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
 
 #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_PSK) && s->psk_server_callback == NULL)
             continue;
 #endif                          /* OPENSSL_NO_PSK */
 
@@ -4217,13 +4909,19 @@ int ssl3_renegotiate_check(SSL *s)
 /*
  * If we are using default SHA1+MD5 algorithms switch to new SHA256 PRF and
  * handshake macs if required.
+ *
+ * If PSK and using SHA384 for TLS < 1.2 switch to default.
  */
 long ssl_get_algorithm2(SSL *s)
 {
     long alg2 = s->s3->tmp.new_cipher->algorithm2;
-    if (s->method->ssl3_enc->enc_flags & SSL_ENC_FLAG_SHA256_PRF
-        && alg2 == (SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF))
-        return SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256;
+    if (s->method->ssl3_enc->enc_flags & SSL_ENC_FLAG_SHA256_PRF) {
+        if (alg2 == (SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF))
+            return SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256;
+    } else if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK) {
+        if (alg2 == (SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384))
+            return SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF;
+    }
     return alg2;
 }
 
@@ -4253,13 +4951,56 @@ int ssl_fill_hello_random(SSL *s, int server, unsigned char *result, int len)
 int ssl_generate_master_secret(SSL *s, unsigned char *pms, size_t pmslen,
                                int free_pms)
 {
-    s->session->master_key_length =
-        s->method->ssl3_enc->generate_master_secret(s, s->session->master_key,
-                                                    pms, pmslen);
-    if (free_pms)
-        OPENSSL_clear_free(pms, pmslen);
-    else
-        OPENSSL_cleanse(pms, pmslen);
+#ifndef OPENSSL_NO_PSK
+    unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+    if (alg_k & SSL_PSK) {
+        unsigned char *pskpms, *t;
+        size_t psklen = s->s3->tmp.psklen;
+        size_t pskpmslen;
+
+        /* create PSK premaster_secret */
+
+        /* For plain PSK "other_secret" is psklen zeroes */
+        if (alg_k & SSL_kPSK)
+            pmslen = psklen;
+
+        pskpmslen = 4 + pmslen + psklen;
+        pskpms = OPENSSL_malloc(pskpmslen);
+        if (pskpms == NULL) {
+            s->session->master_key_length = 0;
+            goto err;
+        }
+        t = pskpms;
+        s2n(pmslen, t);
+        if (alg_k & SSL_kPSK)
+            memset(t, 0, pmslen);
+        else
+            memcpy(t, pms, pmslen);
+        t += pmslen;
+        s2n(psklen, t);
+        memcpy(t, s->s3->tmp.psk, psklen);
+
+        OPENSSL_clear_free(s->s3->tmp.psk, psklen);
+        s->s3->tmp.psk = NULL;
+        s->session->master_key_length =
+            s->method->ssl3_enc->generate_master_secret(s,
+                                                        s->session->master_key,
+                                                        pskpms, pskpmslen);
+        OPENSSL_clear_free(pskpms, pskpmslen);
+    } else
+#endif
+        s->session->master_key_length =
+            s->method->ssl3_enc->generate_master_secret(s,
+                                                        s->session->master_key,
+                                                        pms, pmslen);
+
+    err:
+    if (pms) {
+        if (free_pms)
+            OPENSSL_clear_free(pms, pmslen);
+        else
+            OPENSSL_cleanse(pms, pmslen);
+    }
     if (s->server == 0)
         s->s3->tmp.pms = NULL;
     return s->session->master_key_length >= 0;
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
index cbe80eb..72deedc 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -403,10 +403,8 @@ int ssl3_accept(SSL *s)
         case SSL3_ST_SW_CERT_B:
             /* Check if it is anon DH or anon ECDH, */
             /* normal PSK or SRP */
-            if (!
-                (s->s3->tmp.
-                 new_cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP))
-&& !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) {
+            if (!(s->s3->tmp.new_cipher->algorithm_auth &
+                 (SSL_aNULL | SSL_aSRP | SSL_aPSK))) {
                 ret = ssl3_send_server_certificate(s);
                 if (ret <= 0)
                     goto end;
@@ -446,7 +444,10 @@ int ssl3_accept(SSL *s)
                  * provided
                  */
 #ifndef OPENSSL_NO_PSK
-                || ((alg_k & SSL_kPSK) && s->ctx->psk_identity_hint)
+                /* Only send SKE if we have identity hint for plain PSK */
+                || ((alg_k & (SSL_kPSK | SSL_kRSAPSK)) && s->ctx->psk_identity_hint)
+                /* For other PSK always send SKE */
+                || (alg_k & (SSL_PSK & (SSL_kDHEPSK | SSL_kECDHEPSK)))
 #endif
 #ifndef OPENSSL_NO_SRP
                 /* SRP: send ServerKeyExchange */
@@ -502,7 +503,7 @@ int ssl3_accept(SSL *s)
                     * 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_PSK)) {
                 /* no cert request */
                 skip = 1;
                 s->s3->tmp.cert_request = 0;
@@ -1722,6 +1723,19 @@ int ssl3_send_server_key_exchange(SSL *s)
 
         r[0] = r[1] = r[2] = r[3] = NULL;
         n = 0;
+#ifndef OPENSSL_NO_PSK
+        if (type & SSL_PSK) {
+            /*
+             * reserve size for record length and PSK identity hint
+             */
+            n += 2;
+            if (s->ctx->psk_identity_hint)
+                n += strlen(s->ctx->psk_identity_hint);
+        }
+        /* Plain PSK or RSAPSK nothing to do */
+        if (type & (SSL_kPSK | SSL_kRSAPSK)) {
+        } else
+#endif                          /* !OPENSSL_NO_PSK */
 #ifndef OPENSSL_NO_RSA
         if (type & SSL_kRSA) {
             rsa = cert->rsa_tmp;
@@ -1752,7 +1766,7 @@ int ssl3_send_server_key_exchange(SSL *s)
         } else
 #endif
 #ifndef OPENSSL_NO_DH
-        if (type & SSL_kDHE) {
+        if (type & (SSL_kDHE | SSL_kDHEPSK)) {
             if (s->cert->dh_tmp_auto) {
                 dhp = ssl_get_auto_dh(s);
                 if (dhp == NULL) {
@@ -1817,7 +1831,7 @@ int ssl3_send_server_key_exchange(SSL *s)
         } else
 #endif
 #ifndef OPENSSL_NO_EC
-        if (type & SSL_kECDHE) {
+        if (type & (SSL_kECDHE | SSL_kECDHEPSK)) {
             const EC_GROUP *group;
 
             ecdhp = cert->ecdh_tmp;
@@ -1933,7 +1947,7 @@ int ssl3_send_server_key_exchange(SSL *s)
              * additional bytes to encode the entire ServerECDHParams
              * structure.
              */
-            n = 4 + encodedlen;
+            n += 4 + encodedlen;
 
             /*
              * We'll generate the serverKeyExchange message explicitly so we
@@ -1945,14 +1959,6 @@ int ssl3_send_server_key_exchange(SSL *s)
             r[3] = NULL;
         } else
 #endif                          /* !OPENSSL_NO_EC */
-#ifndef OPENSSL_NO_PSK
-        if (type & SSL_kPSK) {
-            /*
-             * reserve size for record length and PSK identity hint
-             */
-            n += 2 + strlen(s->ctx->psk_identity_hint);
-        } else
-#endif                          /* !OPENSSL_NO_PSK */
 #ifndef OPENSSL_NO_SRP
         if (type & SSL_kSRP) {
             if ((s->srp_ctx.N == NULL) ||
@@ -1984,8 +1990,8 @@ int ssl3_send_server_key_exchange(SSL *s)
                 n += 2 + nr[i];
         }
 
-        if (!(s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP))
-            && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) {
+        if (!(s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL|SSL_aSRP))
+            && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK)) {
             if ((pkey = ssl_get_sign_pkey(s, s->s3->tmp.new_cipher, &md))
                 == NULL) {
                 al = SSL_AD_DECODE_ERROR;
@@ -2003,6 +2009,20 @@ int ssl3_send_server_key_exchange(SSL *s)
         }
         d = p = ssl_handshake_start(s);
 
+#ifndef OPENSSL_NO_PSK
+        if (type & SSL_PSK) {
+            /* copy PSK identity hint */
+            if (s->ctx->psk_identity_hint) {
+                s2n(strlen(s->ctx->psk_identity_hint), p);
+                strncpy((char *)p, s->ctx->psk_identity_hint,
+                        strlen(s->ctx->psk_identity_hint));
+                p += strlen(s->ctx->psk_identity_hint);
+            } else {
+                s2n(0, p);
+            }
+        }
+#endif
+
         for (i = 0; i < 4 && r[i] != NULL; i++) {
 #ifndef OPENSSL_NO_SRP
             if ((i == 2) && (type & SSL_kSRP)) {
@@ -2016,7 +2036,7 @@ int ssl3_send_server_key_exchange(SSL *s)
         }
 
 #ifndef OPENSSL_NO_EC
-        if (type & SSL_kECDHE) {
+        if (type & (SSL_kECDHE | SSL_kECDHEPSK)) {
             /*
              * XXX: For now, we only support named (not generic) curves. In
              * this situation, the serverKeyExchange message has: [1 byte
@@ -2038,16 +2058,6 @@ int ssl3_send_server_key_exchange(SSL *s)
         }
 #endif
 
-#ifndef OPENSSL_NO_PSK
-        if (type & SSL_kPSK) {
-            /* copy PSK identity hint */
-            s2n(strlen(s->ctx->psk_identity_hint), p);
-            strncpy((char *)p, s->ctx->psk_identity_hint,
-                    strlen(s->ctx->psk_identity_hint));
-            p += strlen(s->ctx->psk_identity_hint);
-        }
-#endif
-
         /* not anonymous */
         if (pkey != NULL) {
             /*
@@ -2249,8 +2259,94 @@ int ssl3_get_client_key_exchange(SSL *s)
 
     alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
 
+#ifndef OPENSSL_NO_PSK
+    /* For PSK parse and retrieve identity, obtain PSK key */
+    if (alg_k & SSL_PSK) {
+        unsigned char psk[PSK_MAX_PSK_LEN];
+        size_t psklen;
+        if (n < 2) {
+            al = SSL_AD_DECODE_ERROR;
+            SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
+            goto f_err;
+        }
+        n2s(p, i);
+        if (i + 2 > n) {
+            al = SSL_AD_DECODE_ERROR;
+            SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
+            goto f_err;
+        }
+        if (i > PSK_MAX_IDENTITY_LEN) {
+            al = SSL_AD_DECODE_ERROR;
+            SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+                   SSL_R_DATA_LENGTH_TOO_LONG);
+            goto f_err;
+        }
+        if (s->psk_server_callback == NULL) {
+            al = SSL_AD_INTERNAL_ERROR;
+            SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+                   SSL_R_PSK_NO_SERVER_CB);
+            goto f_err;
+        }
+
+        OPENSSL_free(s->session->psk_identity);
+        s->session->psk_identity = BUF_strndup((char *)p, i);
+
+        if (s->session->psk_identity == NULL) {
+            al = SSL_AD_INTERNAL_ERROR;
+            SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+                   ERR_R_MALLOC_FAILURE);
+            goto f_err;
+        }
+
+        psklen = s->psk_server_callback(s, s->session->psk_identity,
+                                         psk, sizeof(psk));
+
+        if (psklen > PSK_MAX_PSK_LEN) {
+            al = SSL_AD_INTERNAL_ERROR;
+            SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+            goto f_err;
+        } else if (psklen == 0) {
+            /*
+             * PSK related to the given identity not found
+             */
+            SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+                   SSL_R_PSK_IDENTITY_NOT_FOUND);
+            al = SSL_AD_UNKNOWN_PSK_IDENTITY;
+            goto f_err;
+        }
+
+        OPENSSL_free(s->s3->tmp.psk);
+        s->s3->tmp.psk = BUF_memdup(psk, psklen);
+        OPENSSL_cleanse(psk, psklen);
+
+        if (s->s3->tmp.psk == NULL) {
+            al = SSL_AD_INTERNAL_ERROR;
+            SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
+            goto f_err;
+        }
+
+        s->s3->tmp.psklen = psklen;
+
+        n -= i + 2;
+        p += i;
+    }
+    if (alg_k & SSL_kPSK) {
+        /* Identity extracted earlier: should be nothing left */
+        if (n != 0) {
+            al = SSL_AD_HANDSHAKE_FAILURE;
+            SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
+            goto f_err;
+        }
+        /* PSK handled by ssl_generate_master_secret */
+        if (!ssl_generate_master_secret(s, NULL, 0, 0)) {
+            al = SSL_AD_INTERNAL_ERROR;
+            SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+            goto f_err;
+        }
+    } else
+#endif
 #ifndef OPENSSL_NO_RSA
-    if (alg_k & SSL_kRSA) {
+    if (alg_k & (SSL_kRSA | SSL_kRSAPSK)) {
         unsigned char rand_premaster_secret[SSL_MAX_MASTER_KEY_LENGTH];
         int decrypt_len;
         unsigned char decrypt_good, version_good;
@@ -2389,13 +2485,13 @@ int ssl3_get_client_key_exchange(SSL *s)
     } else
 #endif
 #ifndef OPENSSL_NO_DH
-    if (alg_k & (SSL_kDHE | SSL_kDHr | SSL_kDHd)) {
+    if (alg_k & (SSL_kDHE | SSL_kDHr | SSL_kDHd | SSL_kDHEPSK)) {
         int idx = -1;
         EVP_PKEY *skey = NULL;
         if (n > 1) {
             n2s(p, i);
         } else {
-            if (alg_k & SSL_kDHE) {
+            if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
                 al = SSL_AD_HANDSHAKE_FAILURE;
                 SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
                        SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG);
@@ -2483,7 +2579,7 @@ int ssl3_get_client_key_exchange(SSL *s)
 #endif
 
 #ifndef OPENSSL_NO_EC
-    if (alg_k & (SSL_kECDHE | SSL_kECDHr | SSL_kECDHe)) {
+    if (alg_k & (SSL_kECDHE | SSL_kECDHr | SSL_kECDHe | SSL_kECDHEPSK)) {
         int ret = 1;
         int field_size = 0;
         const EC_KEY *tkey;
@@ -2526,7 +2622,7 @@ int ssl3_get_client_key_exchange(SSL *s)
         if (n == 0L) {
             /* Client Publickey was in Client Certificate */
 
-            if (alg_k & SSL_kECDHE) {
+            if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
                 al = SSL_AD_HANDSHAKE_FAILURE;
                 SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
                        SSL_R_MISSING_TMP_ECDH_KEY);
@@ -2612,92 +2708,6 @@ int ssl3_get_client_key_exchange(SSL *s)
         return (ret);
     } else
 #endif
-#ifndef OPENSSL_NO_PSK
-    if (alg_k & SSL_kPSK) {
-        unsigned char *t = NULL;
-        unsigned char psk_or_pre_ms[PSK_MAX_PSK_LEN * 2 + 4];
-        unsigned int pre_ms_len = 0, psk_len = 0;
-        int psk_err = 1;
-        char tmp_id[PSK_MAX_IDENTITY_LEN + 1];
-
-        al = SSL_AD_HANDSHAKE_FAILURE;
-
-        n2s(p, i);
-        if (n != i + 2) {
-            SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
-            goto psk_err;
-        }
-        if (i > PSK_MAX_IDENTITY_LEN) {
-            SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
-                   SSL_R_DATA_LENGTH_TOO_LONG);
-            goto psk_err;
-        }
-        if (s->psk_server_callback == NULL) {
-            SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
-                   SSL_R_PSK_NO_SERVER_CB);
-            goto psk_err;
-        }
-
-        /*
-         * Create guaranteed NULL-terminated identity string for the callback
-         */
-        memcpy(tmp_id, p, i);
-        memset(tmp_id + i, 0, PSK_MAX_IDENTITY_LEN + 1 - i);
-        psk_len = s->psk_server_callback(s, tmp_id,
-                                         psk_or_pre_ms,
-                                         sizeof(psk_or_pre_ms));
-        OPENSSL_cleanse(tmp_id, sizeof(tmp_id));
-
-        if (psk_len > PSK_MAX_PSK_LEN) {
-            SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
-            goto psk_err;
-        } else if (psk_len == 0) {
-            /*
-             * PSK related to the given identity not found
-             */
-            SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
-                   SSL_R_PSK_IDENTITY_NOT_FOUND);
-            al = SSL_AD_UNKNOWN_PSK_IDENTITY;
-            goto psk_err;
-        }
-
-        /* create PSK pre_master_secret */
-        pre_ms_len = 2 + psk_len + 2 + psk_len;
-        t = psk_or_pre_ms;
-        memmove(psk_or_pre_ms + psk_len + 4, psk_or_pre_ms, psk_len);
-        s2n(psk_len, t);
-        memset(t, 0, psk_len);
-        t += psk_len;
-        s2n(psk_len, t);
-
-        OPENSSL_free(s->session->psk_identity);
-        s->session->psk_identity = BUF_strdup((char *)p);
-        if (s->session->psk_identity == NULL) {
-            SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
-            goto psk_err;
-        }
-
-        OPENSSL_free(s->session->psk_identity_hint);
-        s->session->psk_identity_hint = BUF_strdup(s->ctx->psk_identity_hint);
-        if (s->ctx->psk_identity_hint != NULL &&
-            s->session->psk_identity_hint == NULL) {
-            SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
-            goto psk_err;
-        }
-
-        if (!ssl_generate_master_secret(s, psk_or_pre_ms, pre_ms_len, 0)) {
-            al = SSL_AD_INTERNAL_ERROR;
-            SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
-            goto f_err;
-        }
-        psk_err = 0;
- psk_err:
-        if (psk_err != 0) {
-            OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms));
-            goto f_err;
-        }
-    } else
-#endif
 #ifndef OPENSSL_NO_SRP
     if (alg_k & SSL_kSRP) {
         int param_len;
@@ -2820,6 +2830,10 @@ int ssl3_get_client_key_exchange(SSL *s)
     EC_KEY_free(srvr_ecdh);
     BN_CTX_free(bn_ctx);
 #endif
+#ifndef OPENSSL_NO_PSK
+    OPENSSL_clear_free(s->s3->tmp.psk, s->s3->tmp.psklen);
+    s->s3->tmp.psk = NULL;
+#endif
     s->state = SSL_ST_ERR;
     return (-1);
 }
diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c
index 7f932b0..da64301 100644
--- a/ssl/ssl_ciph.c
+++ b/ssl/ssl_ciph.c
@@ -314,6 +314,9 @@ 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_kECDHEPSK, 0, SSL_kECDHEPSK, 0, 0, 0, 0, 0, 0, 0, 0},
+    {0, SSL_TXT_kDHEPSK, 0, SSL_kDHEPSK, 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},
 
@@ -342,7 +345,7 @@ 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_PSK, 0, 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 */
@@ -492,22 +495,22 @@ void ssl_load_ciphers(void)
     disabled_auth_mask = 0;
 
 #ifdef OPENSSL_NO_RSA
-    disabled_mkey_mask |= SSL_kRSA;
+    disabled_mkey_mask |= SSL_kRSA | SSL_kRSAPSK;
     disabled_auth_mask |= SSL_aRSA;
 #endif
 #ifdef OPENSSL_NO_DSA
     disabled_auth_mask |= SSL_aDSS;
 #endif
 #ifdef OPENSSL_NO_DH
-    disabled_mkey_mask |= SSL_kDHr | SSL_kDHd | SSL_kDHE;
+    disabled_mkey_mask |= SSL_kDHr | SSL_kDHd | SSL_kDHE | SSL_kDHEPSK;
     disabled_auth_mask |= SSL_aDH;
 #endif
 #ifdef OPENSSL_NO_EC
-    disabled_mkey_mask |= SSL_kECDHe | SSL_kECDHr;
+    disabled_mkey_mask |= SSL_kECDHe | SSL_kECDHr | SSL_kECDHEPSK;
     disabled_auth_mask |= SSL_aECDSA | SSL_aECDH;
 #endif
 #ifdef OPENSSL_NO_PSK
-    disabled_mkey_mask |= SSL_kPSK;
+    disabled_mkey_mask |= SSL_PSK;
     disabled_auth_mask |= SSL_aPSK;
 #endif
 #ifdef OPENSSL_NO_SRP
@@ -1626,6 +1629,15 @@ 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_kECDHEPSK:
+        kx = "ECDHEPSK";
+        break;
+    case SSL_kDHEPSK:
+        kx = "DHEPSK";
+        break;
     case SSL_kSRP:
         kx = "SRP";
         break;
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index d20d95b..5a0ec8a 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -2112,6 +2112,12 @@ void ssl_set_masks(SSL *s, const SSL_CIPHER *cipher)
     mask_a |= SSL_aPSK;
     emask_k |= SSL_kPSK;
     emask_a |= SSL_aPSK;
+    if (mask_k & SSL_kRSA)
+        mask_k |= SSL_kRSAPSK;
+    if (mask_k & SSL_kDHE)
+        mask_k |= SSL_kDHEPSK;
+    if (mask_k & SSL_kECDHE)
+        mask_k |= SSL_kECDHEPSK;
 #endif
 
     s->s3->tmp.mask_k = mask_k;
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 1cdcb8b..c75219b 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -315,6 +315,14 @@
 /* SRP */
 # define SSL_kSRP        0x00000400L
 
+# define SSL_kRSAPSK             0x00000800L
+# define SSL_kECDHEPSK           0x00001000L
+# define SSL_kDHEPSK             0x00002000L
+
+/* all PSK */
+
+#define SSL_PSK     (SSL_kPSK | SSL_kRSAPSK | SSL_kECDHEPSK | SSL_kDHEPSK)
+
 /* Bits for algorithm_auth (server authentication) */
 /* RSA auth */
 # define SSL_aRSA                0x00000001L
@@ -1269,6 +1277,11 @@ typedef struct ssl3_state_st {
         /* Temporary storage for premaster secret */
         unsigned char *pms;
         size_t pmslen;
+#ifndef OPENSSL_NO_PSK
+        /* Temporary storage for PSK key */
+        unsigned char *psk;
+        size_t psklen;
+#endif
         /*
          * signature algorithms peer reports: e.g. supported signature
          * algorithms extension for server or as part of a certificate
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index e593654..47abf2b 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -1111,7 +1111,7 @@ void ssl_set_client_disabled(SSL *s)
     /* with PSK there must be client callback set */
     if (!s->psk_client_callback) {
         s->s3->tmp.mask_a |= SSL_aPSK;
-        s->s3->tmp.mask_k |= SSL_kPSK;
+        s->s3->tmp.mask_k |= SSL_PSK;
     }
 #endif                         /* OPENSSL_NO_PSK */
 #ifndef OPENSSL_NO_SRP
@@ -1157,7 +1157,7 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf,
 
             alg_k = c->algorithm_mkey;
             alg_a = c->algorithm_auth;
-            if ((alg_k & (SSL_kECDHE | SSL_kECDHr | SSL_kECDHe)
+            if ((alg_k & (SSL_kECDHE | SSL_kECDHr | SSL_kECDHe | SSL_kECDHEPSK)
                  || (alg_a & SSL_aECDSA))) {
                 using_ecc = 1;
                 break;
@@ -4165,7 +4165,7 @@ DH *ssl_get_auto_dh(SSL *s)
     int dh_secbits = 80;
     if (s->cert->dh_tmp_auto == 2)
         return DH_get_1024_160();
-    if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) {
+    if (s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aPSK)) {
         if (s->s3->tmp.new_cipher->strength_bits == 256)
             dh_secbits = 128;
         else
diff --git a/ssl/t1_trce.c b/ssl/t1_trce.c
index 40c5beb..74d157d 100644
--- a/ssl/t1_trce.c
+++ b/ssl/t1_trce.c
@@ -928,6 +928,18 @@ static int ssl_get_keyex(const char **pname, SSL *ssl)
         *pname = "PSK";
         return SSL_kPSK;
     }
+    if (alg_k & SSL_kRSAPSK) {
+        *pname = "RSAPSK";
+        return SSL_kRSAPSK;
+    }
+    if (alg_k & SSL_kDHEPSK) {
+        *pname = "DHEPSK";
+        return SSL_kDHEPSK;
+    }
+    if (alg_k & SSL_kECDHEPSK) {
+        *pname = "ECDHEPSK";
+        return SSL_kECDHEPSK;
+    }
     if (alg_k & SSL_kSRP) {
         *pname = "SRP";
         return SSL_kSRP;
@@ -948,9 +960,15 @@ static int ssl_print_client_keyex(BIO *bio, int indent, SSL *ssl,
     id = ssl_get_keyex(&algname, ssl);
     BIO_indent(bio, indent, 80);
     BIO_printf(bio, "KeyExchangeAlgorithm=%s\n", algname);
+    if (id & SSL_PSK) {
+        if (!ssl_print_hexbuf(bio, indent + 2,
+                              "psk_identity", 2, &msg, &msglen))
+            return 0;
+    }
     switch (id) {
 
     case SSL_kRSA:
+    case SSL_kRSAPSK:
         if (TLS1_get_version(ssl) == SSL3_VERSION) {
             ssl_print_hex(bio, indent + 2,
                           "EncyptedPreMasterSecret", msg, msglen);
@@ -971,6 +989,7 @@ static int ssl_print_client_keyex(BIO *bio, int indent, SSL *ssl,
             break;
         }
     case SSL_kDHE:
+    case SSL_kDHEPSK:
         if (!ssl_print_hexbuf(bio, indent + 2, "dh_Yc", 2, &msg, &msglen))
             return 0;
         break;
@@ -983,19 +1002,14 @@ static int ssl_print_client_keyex(BIO *bio, int indent, SSL *ssl,
             break;
         }
     case SSL_kECDHE:
+    case SSL_kECDHEPSK:
         if (!ssl_print_hexbuf(bio, indent + 2, "ecdh_Yc", 1, &msg, &msglen))
             return 0;
         break;
 
-    case SSL_kPSK:
-        if (!ssl_print_hexbuf(bio, indent + 2,
-                              "psk_identity", 2, &msg, &msglen))
-            return 0;
-        break;
-
     }
 
-    return 1;
+    return !msglen;
 }
 
 static int ssl_print_server_keyex(BIO *bio, int indent, SSL *ssl,
@@ -1006,6 +1020,11 @@ static int ssl_print_server_keyex(BIO *bio, int indent, SSL *ssl,
     id = ssl_get_keyex(&algname, ssl);
     BIO_indent(bio, indent, 80);
     BIO_printf(bio, "KeyExchangeAlgorithm=%s\n", algname);
+    if (id & SSL_PSK) {
+        if (!ssl_print_hexbuf(bio, indent + 2,
+                              "psk_identity_hint", 2, &msg, &msglen))
+            return 0;
+    }
     switch (id) {
         /* Should never happen */
     case SSL_kDHd:
@@ -1027,6 +1046,7 @@ static int ssl_print_server_keyex(BIO *bio, int indent, SSL *ssl,
         break;
 
     case SSL_kDHE:
+    case SSL_kDHEPSK:
         if (!ssl_print_hexbuf(bio, indent + 2, "dh_p", 2, &msg, &msglen))
             return 0;
         if (!ssl_print_hexbuf(bio, indent + 2, "dh_g", 2, &msg, &msglen))
@@ -1036,6 +1056,7 @@ static int ssl_print_server_keyex(BIO *bio, int indent, SSL *ssl,
         break;
 
     case SSL_kECDHE:
+    case SSL_kECDHEPSK:
         if (msglen < 1)
             return 0;
         BIO_indent(bio, indent + 2, 80);
@@ -1054,17 +1075,19 @@ static int ssl_print_server_keyex(BIO *bio, int indent, SSL *ssl,
             msglen -= 3;
             if (!ssl_print_hexbuf(bio, indent + 2, "point", 1, &msg, &msglen))
                 return 0;
+        } else {
+            BIO_printf(bio, "UNKNOWN CURVE PARAMETER TYPE %d\n", msg[0]);
+            return 0;
         }
         break;
 
     case SSL_kPSK:
-        if (!ssl_print_hexbuf(bio, indent + 2,
-                              "psk_identity_hint", 2, &msg, &msglen))
-            return 0;
-        /* No signature */
-        return 1;
+    case SSL_kRSAPSK:
+        break;
     }
-    return ssl_print_signature(bio, indent, ssl, &msg, &msglen);
+    if (!(id & SSL_PSK))
+        ssl_print_signature(bio, indent, ssl, &msg, &msglen);
+    return !msglen;
 }
 
 static int ssl_print_certificate(BIO *bio, int indent,


More information about the openssl-commits mailing list