Hey all,

I wrote a patch for openssl-1.0.0c to support TLS-RSA-PSK cipher suites
as defined in RFC 4279. Plain PSK support has been implemented in
openssl for quite some time, I believe. This patch now adds one of the
RSA-PSK variants, namely RSA-PSK-AES256-CBC-SHA (95). Adding ciphers
92-94 should be easy, but I am not too familiar with the definition data
structure in s3_lib.c.
I clearly have to state that this patch is EXPERIMENTAL.

PROCEDURE TO APPLY PATCH
========================
download openssl-1.0.0c.tar.gz
tar xzf openssl-1.0.0c.tar.gz
cd openssl-1.0.0c
patch -p1 -i ../openssl-1.0.0c.tls-rsa-psk.patch

TESTING TLS-RSA-PSK
===================
You can test locally whether your openssl with TLS-RSA-PSK works as
follows. Make sure that you actually call the currently generated
openssl binary (in the apps directory). Must have a server.pem and
privkey.pem in the current directory.

# launching the server
openssl s_server \
 -psk c033f52671c61c8128f7f8a40be88038bcf2b07a6eb3095c36e3759f0cf40837 \
 -key privkey.pem \
 -cipher RSA-PSK-AES256-CBC-SHA \
 -debug -state

# launch the client
openssl s_client -connect localhost:4433 \
 -psk c033f52671c61c8128f7f8a40be88038bcf2b07a6eb3095c36e3759f0cf40837 \
 -cipher RSA-PSK-AES256-CBC-SHA \
 -debug -state


AUTHOR
======
This patch is written by Christian J. Dietrich
<[email protected]>
I thankfully acknowledge the support and several interesting discussions
with Christian Rossow.

Some more info can be found in my blog
http://blog.cj2s.de/archives/21-TLS-RSA-PSK-Cipher-Suites-for-OpenSSL.html
or on our website http://www.if-is.net

-- 
Christian J. Dietrich
if(is) - Institute for Internet Security
University of Applied Sciences Gelsenkirchen, Germany
https://www.internet-sicherheit.de

diff -ur -x .svn openssl-1.0.0c-orig/include/openssl/ssl.h 
openssl-1.0.0c-tlsrsapsk/include/openssl/ssl.h
--- openssl-1.0.0c-orig/include/openssl/ssl.h   2010-01-06 18:37:38.000000000 
+0100
+++ openssl-1.0.0c-tlsrsapsk/include/openssl/ssl.h      2011-02-25 
19:57:20.467303448 +0100
@@ -250,7 +250,8 @@
 #define SSL_TXT_kECDHe         "kECDHe"
 #define SSL_TXT_kECDH          "kECDH"
 #define SSL_TXT_kEECDH         "kEECDH"
-#define SSL_TXT_kPSK            "kPSK"
+#define SSL_TXT_kPSK        "kPSK"
+#define SSL_TXT_kRSAPSK     "kRSAPSK"
 #define SSL_TXT_kGOST          "kGOST"
 
 #define        SSL_TXT_aRSA            "aRSA"
@@ -274,7 +275,8 @@
 #define SSL_TXT_AECDH          "AECDH"
 #define SSL_TXT_ECDSA          "ECDSA"
 #define SSL_TXT_KRB5           "KRB5"
-#define SSL_TXT_PSK             "PSK"
+#define SSL_TXT_PSK         "PSK"
+#define SSL_TXT_RSAPSK      "RSAPSK"
 
 #define SSL_TXT_DES            "DES"
 #define SSL_TXT_3DES           "3DES"
diff -ur -x .svn openssl-1.0.0c-orig/include/openssl/tls1.h 
openssl-1.0.0c-tlsrsapsk/include/openssl/tls1.h
--- openssl-1.0.0c-orig/include/openssl/tls1.h  2009-11-11 15:51:29.000000000 
+0100
+++ openssl-1.0.0c-tlsrsapsk/include/openssl/tls1.h     2011-02-25 
19:57:20.472303472 +0100
@@ -292,6 +292,9 @@
 #define TLS1_CK_PSK_WITH_3DES_EDE_CBC_SHA               0x0300008B
 #define TLS1_CK_PSK_WITH_AES_128_CBC_SHA                0x0300008C
 #define TLS1_CK_PSK_WITH_AES_256_CBC_SHA                0x0300008D
+/* RSA-PSK */
+// FIXME: add RSA-PSK ciphers 92-94 here, too
+#define TLS1_CK_RSA_PSK_WITH_AES_256_CBC_SHA            0x03000095
 
 /* Additional TLS ciphersuites from expired Internet Draft
  * draft-ietf-tls-56-bit-ciphersuites-01.txt
@@ -442,6 +445,8 @@
 #define TLS1_TXT_PSK_WITH_3DES_EDE_CBC_SHA             "PSK-3DES-EDE-CBC-SHA"
 #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"
+// FIXME: add the 3 other RSA-PSK ciphers here, too
+#define TLS1_TXT_RSA_PSK_WITH_AES_256_CBC_SHA          "RSA-PSK-AES256-CBC-SHA"
 
 /* Camellia ciphersuites from RFC4132 */
 #define TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA         "CAMELLIA128-SHA"
Only in openssl-1.0.0c-tlsrsapsk: Makefile.bak
diff -ur -x .svn openssl-1.0.0c-orig/ssl/s3_clnt.c 
openssl-1.0.0c-tlsrsapsk/ssl/s3_clnt.c
--- openssl-1.0.0c-orig/ssl/s3_clnt.c   2010-12-02 19:24:54.000000000 +0100
+++ openssl-1.0.0c-tlsrsapsk/ssl/s3_clnt.c      2011-02-25 19:57:20.472303472 
+0100
@@ -303,7 +303,7 @@
                                }
 #endif
                        /* Check if it is anon DH/ECDH */
-                       /* or PSK */
+                       /* or plain PSK */
                        if (!(s->s3->tmp.new_cipher->algorithm_auth & 
SSL_aNULL) &&
                            !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
                                {
@@ -1186,10 +1186,10 @@
        if (s->s3->tmp.message_type != SSL3_MT_SERVER_KEY_EXCHANGE)
                {
 #ifndef OPENSSL_NO_PSK
-               /* In plain PSK ciphersuite, ServerKeyExchange can be
+               /* In PSK ciphersuites, ServerKeyExchange can be
                   omitted if no identity hint is sent. Set
-                  session->sess_cert anyway to avoid problems
-                  later.*/
+                  session->sess_cert for plain PSK anyway to avoid 
+                  problems later.*/
                if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)
                        {
                        s->session->sess_cert=ssl_sess_cert_new();
@@ -1238,7 +1238,8 @@
        EVP_MD_CTX_init(&md_ctx);
 
 #ifndef OPENSSL_NO_PSK
-       if (alg_k & SSL_kPSK)
+    /* handle PSK identity hint */
+       if (alg_k & (SSL_kPSK|SSL_kRSAPSK)) // CJD
                {
                char tmp_id_hint[PSK_MAX_IDENTITY_LEN+1];
 
@@ -1283,7 +1284,7 @@
        else
 #endif /* !OPENSSL_NO_PSK */
 #ifndef OPENSSL_NO_RSA
-       if (alg_k & SSL_kRSA)
+       if (alg_k & (SSL_kRSA|SSL_kRSAPSK)) // CJD
                {
                if ((rsa=RSA_new()) == NULL)
                        {
@@ -1322,7 +1323,7 @@
                n-=param_len;
 
                /* this should be because we are using an export cipher */
-               if (alg_a & SSL_aRSA)
+               if (alg_a & SSL_aRSA) // FIXME CJD: is this needed for kRSAPSK, 
too?
                        
pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
                else
                        {
@@ -1620,8 +1621,9 @@
                }
        else
                {
-               if (!(alg_a & SSL_aNULL) && !(alg_k & SSL_kPSK))
-                       /* aNULL or kPSK do not need public keys */
+               if (!(alg_a & SSL_aNULL) && !(alg_k & (SSL_kPSK|SSL_kRSAPSK)))
+                       /* aNULL or kPSK do not need public keys 
+             * CJD: added SSL_kRSAPSK here, too */
                        {
                        
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
                        goto err;
@@ -2020,15 +2022,22 @@
                /* Fool emacs indentation */
                if (0) {}
 #ifndef OPENSSL_NO_RSA
-               else if (alg_k & SSL_kRSA)
+        /** here we can see normal RSA key exchange **/
+        /* ClientKeyExchange consists of the encrypted premaster secret 
+         * which in turn consists of version (2 bytes) and 46 random bytes */
+               else if (alg_k & SSL_kRSA) // plain kRSA case
                        {
                        RSA *rsa;
+            /* this contains the premaster secret */
                        unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH];
 
+            /* get the server's public key */
                        if (s->session->sess_cert->peer_rsa_tmp != NULL)
+                /* for this session the server's rsa has been extracted */
                                rsa=s->session->sess_cert->peer_rsa_tmp;
                        else
                                {
+                /* get the pubkey from the server's certificate */
                                
pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
                                if ((pkey == NULL) ||
                                        (pkey->type != EVP_PKEY_RSA) ||
@@ -2040,23 +2049,37 @@
                                rsa=pkey->pkey.rsa;
                                EVP_PKEY_free(pkey);
                                }
-                               
+                       
+            /* build the pre master secret in tmp_buf:
+             * [client_version|2b] [len_rand|2b] [rand|46b] =: pms
+             * encrypted_pms = RSA_public_encrypt(pms)
+             * [len_epms|2b] [encrypted_pms]   */
+            /* two bytes version */
                        tmp_buf[0]=s->client_version>>8;
                        tmp_buf[1]=s->client_version&0xff;
+            /* 46 random bytes */
                        if (RAND_bytes(&(tmp_buf[2]),sizeof tmp_buf-2) <= 0)
                                        goto err;
 
+            /* assume premaster secret and master secret have same length */
                        s->session->master_key_length=sizeof tmp_buf;
 
+            /* q now points to the send buffer (where p was pointing) */
                        q=p;
-                       /* Fix buf for TLS and beyond */
+                       /* Fix buf for TLS and beyond. Before writing to p, 
skip 2 bytes
+             * which are supposed to specify the length of the encrypted pms.
+             * This is only needed for certain versions >= TLS 1.0 */
                        if (s->version > SSL3_VERSION)
                                p+=2;
-                       n=RSA_public_encrypt(sizeof tmp_buf,
-                               tmp_buf,p,rsa,RSA_PKCS1_PADDING);
+            /*
+             *   int RSA_public_encrypt(int flen, unsigned char *from,
+             *       unsigned char *to, RSA *rsa, int padding);
+             * encrypt from tmp_buf into p using the key in rsa */
+                       n=RSA_public_encrypt(sizeof tmp_buf, tmp_buf,
+                p, rsa, RSA_PKCS1_PADDING);
 #ifdef PKCS1_CHECK
-                       if (s->options & SSL_OP_PKCS1_CHECK_1) p[1]++;
-                       if (s->options & SSL_OP_PKCS1_CHECK_2) tmp_buf[0]=0x70;
+                       if (s->options & SSL_OP_PKCS1_CHECK_1) p[1]++;          
// ???
+                       if (s->options & SSL_OP_PKCS1_CHECK_2) tmp_buf[0]=0x70; 
// ???
 #endif
                        if (n <= 0)
                                {
@@ -2552,10 +2575,20 @@
 
                        }
 #ifndef OPENSSL_NO_PSK
+        /** plain PSK case **/
                else if (alg_k & SSL_kPSK)
                        {
                        char identity[PSK_MAX_IDENTITY_LEN];
                        unsigned char *t = NULL;
+            /*
+             * plain PSK case:
+             *   N = len(psk) in octets
+             *   pre_ms = N + N*'0' + N + psk 
+             * RSA-PSK case:
+             *   uint16 prefix = 48
+             *   pre_ms = prefix + epms + psk_len + psk
+             *              2b      ?b      2b      ?b
+             */
                        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;
@@ -2568,6 +2601,8 @@
                                goto err;
                                }
 
+            /* fills psk_len, identity and psk_or_pre_ms */
+            /* psk_or_pre_ms is filled with the psk at the beginning */
                        psk_len = s->psk_client_callback(s, 
s->ctx->psk_identity_hint,
                                identity, PSK_MAX_IDENTITY_LEN,
                                psk_or_pre_ms, sizeof(psk_or_pre_ms));
@@ -2584,14 +2619,25 @@
                                goto psk_err;
                                }
 
-                       /* create PSK pre_master_secret */
+                       /* create PSK pre_master_secret, it should look like 
pre_ms at the end
+             *
+             * // currently the psk is at the beginning of psk_or_pre_ms
+             * psk_or_pre_ms = [psk]....
+             *
+             * N = len(psk) in octets
+             *          [A]    [B]      [C]    [D]
+             * pre_ms =  N +  N*'0'  +   N  +  psk
+             *          2b +  N byt  +  2b  +  N bytes */
                        pre_ms_len = 2+psk_len+2+psk_len;
                        t = psk_or_pre_ms;
+            /* copy the psk to 4 bytes after the first psk (fills [D]) */
                        memmove(psk_or_pre_ms+psk_len+4, psk_or_pre_ms, 
psk_len);
+                       // write psk_len as uint16 (2 bytes) into the first 2 
bytes of t, increase t
                        s2n(psk_len, t);
-                       memset(t, 0, psk_len);
-                       t+=psk_len;
-                       s2n(psk_len, t);
+                       memset(t, 0, psk_len); // write psk_len zeroes into t
+                       t+=psk_len; // increase t by psk_len
+                       s2n(psk_len, t);    // write psk_len as uint16 into t
+            // at this point, psk_or_pre_ms is filled with all required values
 
                        if (s->session->psk_identity_hint != NULL)
                                OPENSSL_free(s->session->psk_identity_hint);
@@ -2614,14 +2660,19 @@
                                goto psk_err;
                                }
 
+            /* generate the master secret based on premaster secret in 
psk_or_pre_ms */
                        s->session->master_key_length =
                                s->method->ssl3_enc->generate_master_secret(s,
                                        s->session->master_key,
                                        psk_or_pre_ms, pre_ms_len); 
+            /* now build the ClientKeyExchange message
+             * which consists of the psk_identity encoded as opaque */
+            /* I think n must contain the length of the whole 
ClientKeyExchange 
+             * message, thus update it accordingly! */
                        n = strlen(identity);
-                       s2n(n, p);
-                       memcpy(p, identity, n);
-                       n+=2;
+                       s2n(n, p); // write n as uint16 into p
+                       memcpy(p, identity, n); // copy identity into p
+                       n+=2; // increase n (2 length bytes)
                        psk_err = 0;
                psk_err:
                        OPENSSL_cleanse(identity, PSK_MAX_IDENTITY_LEN);
@@ -2633,6 +2684,164 @@
                                }
                        }
 #endif
+#ifndef OPENSSL_NO_PSK
+#ifndef OPENSSL_NO_RSA
+        /** RSA-PSK case **/
+               else if (alg_k & SSL_kRSAPSK)        // CJD
+                       {
+                       char identity[PSK_MAX_IDENTITY_LEN];
+                       unsigned char *t = NULL;            // temp
+            /* stores the premaster secret */
+                       unsigned char psk_or_pre_ms[PSK_MAX_PSK_LEN*2+4];
+                       unsigned int pre_ms_len = 0, psk_len = 0;
+            RSA *rsa;
+            int enc_n; // contains number of encrypted bytes after RSA 
encryption
+                       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;
+                               }
+
+                       psk_len = s->psk_client_callback(s, 
s->ctx->psk_identity_hint,
+                               identity, PSK_MAX_IDENTITY_LEN,
+                               psk_or_pre_ms, sizeof(psk_or_pre_ms));
+                       if (psk_len > PSK_MAX_PSK_LEN)
+                               {
+                               SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+                                       ERR_R_INTERNAL_ERROR);
+                               goto rsapsk_err;
+                               }
+                       else if (psk_len == 0)
+                               {
+                               SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+                                       SSL_R_PSK_IDENTITY_NOT_FOUND);
+                               goto rsapsk_err;
+                               }
+
+                       /* create RSA-PSK pre_master_secret, it should look 
like pre_ms at the end
+             *
+             * // currently the psk is at the beginning of psk_or_pre_ms
+             * psk_or_pre_ms = [psk]....
+             *
+             * N = len(psk) in octets
+             *          [A]     [B1]     [B2]     [C]    [D]
+             * pre_ms = 48 +  version + random +   N  +  psk
+             *          2b +     2b   +   46b  +  2b  +  N bytes */
+                       pre_ms_len = 2+2+46+2+psk_len;
+                       // initialize t at beginning of psk_or_pre_ms, then 
increase it as necessary
+                       t = psk_or_pre_ms;
+            // move the PSK from the beginning to the end   [D]
+                       memmove(psk_or_pre_ms+52, psk_or_pre_ms, psk_len);
+            // prefix (48 as uint16)  [A]
+            unsigned int pmsprefix = 48;
+            s2n(pmsprefix, t);   // write 48 into t, automatically increases t
+            // client version [B1]
+            psk_or_pre_ms[2]=s->client_version>>8;
+            psk_or_pre_ms[3]=s->client_version&0xff;
+            t+=2;
+            // 46 random bytes [B2]
+            if (RAND_bytes(&(psk_or_pre_ms[4]),46) <= 0)
+                    goto err;
+            t+=46;  // increase t by the length of the random bytes
+            // write psk_len into t    [C]
+                       s2n(psk_len, t); // write psk_len as uint16 into t, 
increasing t
+            // at this point psk_or_pre_ms is filled with the premaster secret
+
+            /* copy psk_identity_hint from context into 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_SEND_CLIENT_KEY_EXCHANGE,
+                                       ERR_R_MALLOC_FAILURE);
+                               goto rsapsk_err;
+                               }
+
+            /* store the psk_identity in the session */
+                       if (s->session->psk_identity != NULL)
+                               OPENSSL_free(s->session->psk_identity);
+                       s->session->psk_identity = BUF_strdup(identity);
+                       if (s->session->psk_identity == NULL)
+                               {
+                               SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+                                       ERR_R_MALLOC_FAILURE);
+                               goto rsapsk_err;
+                               }
+
+                       s->session->master_key_length =
+                               s->method->ssl3_enc->generate_master_secret(s,
+                                       s->session->master_key,
+                                       psk_or_pre_ms, pre_ms_len); 
+
+            /* now build ClientKeyExchange payload which consists of
+             * psk_identity and the encrypted pre_ms, encoded like so:
+             *              [id_len] [identity] [epms_len] [epms]    
+             * len in bytes    2         k          2        m      */
+            /* get the rsa object which has the server's public key */
+                       if (s->session->sess_cert->peer_rsa_tmp != NULL)
+                /* for this session the server's rsa has been extracted */
+                               rsa=s->session->sess_cert->peer_rsa_tmp;
+                       else
+                               {
+                /* get the pubkey from the server's certificate */
+                               
pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
+                // FIXME CJD: do we need to check pkey->type for RSAPSK here?
+                               if ((pkey == NULL) ||                 // pubkey 
is NULL
+                                       (pkey->type != EVP_PKEY_RSA) ||   // 
pubkey cannot be used for RSA
+                                       (pkey->pkey.rsa == NULL))         // 
pubkey's rsa obj is NULL
+                                       {
+                                       
SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
+                                       goto err; // FIXME CJD: check target, 
maybe rsapsk_err?
+                                       }
+                               rsa=pkey->pkey.rsa;
+                               EVP_PKEY_free(pkey);
+                               }
+
+            t=p;
+            /* n must finally contain the length of the 
+             * whole ClientKeyExchange payload, thus update it accordingly! */
+                       n = strlen(identity);
+                       s2n(n, t);              // write n as uint16 into t, 
increasing t (t=p+2)
+                       memcpy(t, identity, n); // copy identity into t (n 
bytes long)
+            t+=n; // t = p+2+n
+                       /* increase n by 2 as the length of identity was 
written before */
+                       n+=2; // n now covers [id_len] and [identity]
+
+            /* write encrypted pre_ms into t, leaving space 
+             * for the length before (2 bytes) therefore t+2 */
+            // encrypt 48 bytes from psk_or_pre_ms into t
+            enc_n=RSA_public_encrypt(48, &(psk_or_pre_ms[2]), 
+                t+2, rsa, RSA_PKCS1_PADDING);
+            if (enc_n <= 0)
+                {
+                
SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_BAD_RSA_ENCRYPT);
+                goto err;
+                }
+            n+=enc_n;
+            s2n(enc_n, t); // write the length of the encrypted pms in front 
of epms
+            n+=2; // add the 2 bytes that are needed for [epms_len]
+            
+            /* Fix buf for TLS and beyond */
+            // NOT NEEDED
+            
+                       psk_err = 0;
+               rsapsk_err:
+                       OPENSSL_cleanse(identity, PSK_MAX_IDENTITY_LEN);
+                       OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms));
+                       if (psk_err != 0)
+                               {
+                               ssl3_send_alert(s, SSL3_AL_FATAL, 
SSL_AD_HANDSHAKE_FAILURE);
+                               goto err;
+                               }
+                       }
+#endif /* OPENSSL_NO_RSA */
+#endif /* OPENSSL_NO_PSK */
                else
                        {
                        ssl3_send_alert(s, SSL3_AL_FATAL,
@@ -2932,7 +3141,7 @@
                }
 #endif
 #ifndef OPENSSL_NO_RSA
-       if ((alg_k & SSL_kRSA) &&
+       if ((alg_k & (SSL_kRSA|SSL_kRSAPSK)) && // CJD: CHECKME: not 100% sure
                !(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);
@@ -2963,7 +3172,7 @@
        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|SSL_kRSAPSK)) // CJD
                        {
                        if (rsa == NULL
                            || RSA_size(rsa)*8 > 
SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher))
diff -ur -x .svn openssl-1.0.0c-orig/ssl/s3_lib.c 
openssl-1.0.0c-tlsrsapsk/ssl/s3_lib.c
--- openssl-1.0.0c-orig/ssl/s3_lib.c    2009-10-16 17:24:19.000000000 +0200
+++ openssl-1.0.0c-tlsrsapsk/ssl/s3_lib.c       2011-02-25 19:57:20.471303475 
+0100
@@ -1507,6 +1507,27 @@
        256,
        256,
        },
+
+#ifndef OPENSSL_NO_RSA
+    /** RSA-PSK ciphersuites **/
+    // FIXME: add RSA-PSK ciphers 92-94
+
+       /* 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
@@ -2895,7 +2916,7 @@
 #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 -ur -x .svn openssl-1.0.0c-orig/ssl/s3_srvr.c 
openssl-1.0.0c-tlsrsapsk/ssl/s3_srvr.c
--- openssl-1.0.0c-orig/ssl/s3_srvr.c   2010-12-02 19:24:55.000000000 +0100
+++ openssl-1.0.0c-tlsrsapsk/ssl/s3_srvr.c      2011-02-25 19:57:20.468303456 
+0100
@@ -344,8 +344,8 @@
 
                case SSL3_ST_SW_CERT_A:
                case SSL3_ST_SW_CERT_B:
-                       /* Check if it is anon DH or anon ECDH, */
-                       /* normal PSK or KRB5 */
+                       /* If it is anon DH or anon ECDH, */
+                       /* normal PSK or KRB5, then don't send server cert(s) */
                        if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)
                                && !(s->s3->tmp.new_cipher->algorithm_mkey & 
SSL_kPSK)
                                && !(s->s3->tmp.new_cipher->algorithm_auth & 
SSL_aKRB5))
@@ -396,7 +396,8 @@
                        /* only send if a DH key exchange, fortezza or
                         * RSA but we have a sign only certificate
                         *
-                        * PSK: may send PSK identity hints
+                        * PSK|RSAPSK: may send PSK identity hints.
+             *   Send ServerKeyExchange if PSK identity hint is provided.
                         *
                         * For ECC ciphersuites, we send a serverKeyExchange
                         * message only if the cipher suite is either
@@ -405,10 +406,9 @@
                         * public key for key exchange.
                         */
                        if (s->s3->tmp.use_rsa_tmp
-                       /* PSK: send ServerKeyExchange if PSK identity
-                        * hint if provided */
 #ifndef OPENSSL_NO_PSK
-                           || ((alg_k & SSL_kPSK) && s->ctx->psk_identity_hint)
+                /* send ServKeyExch if PSK identity hint is provided */
+                           || ((alg_k & (SSL_kPSK|SSL_kRSAPSK)) && 
s->ctx->psk_identity_hint)
 #endif
                            || (alg_k & (SSL_kDHr|SSL_kDHd|SSL_kEDH))
                            || (alg_k & SSL_kEECDH)
@@ -448,9 +448,12 @@
                                 !(s->verify_mode & 
SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) ||
                                 /* never request cert in Kerberos ciphersuites 
*/
                                (s->s3->tmp.new_cipher->algorithm_auth & 
SSL_aKRB5)
-                               /* With normal PSK Certificates and
+                               /* With normal PSK, Certificates and
                                 * Certificate Requests are omitted */
-                               || (s->s3->tmp.new_cipher->algorithm_mkey & 
SSL_kPSK))
+                /* CJD: I am not sure whether kRSAPSK falls into the same
+                 * category. I think, with kRSAPSK client certs make no
+                 * sense either, thus the CertRequest can be skipped, too. */
+                               || (s->s3->tmp.new_cipher->algorithm_mkey & 
(SSL_kPSK|SSL_kRSAPSK)))
                                {
                                /* no cert request */
                                skip=1;
@@ -1445,6 +1448,7 @@
                r[0]=r[1]=r[2]=r[3]=NULL;
                n=0;
 #ifndef OPENSSL_NO_RSA
+        /** plain RSA case for ServerKeyExchange **/
                if (type & SSL_kRSA)
                        {
                        rsa=cert->rsa_tmp;
@@ -1667,6 +1671,47 @@
                                }
                        else
 #endif /* !OPENSSL_NO_PSK */
+#ifndef OPENSSL_NO_RSA
+#ifndef OPENSSL_NO_PSK
+        /** RSAPSK case for ServerKeyExchange **/
+               if (type & SSL_kRSAPSK) // CJD
+                       {
+            /* RSA part */
+            /** NOTE: Using temporary RSA keys with RSAPSK does not make sense.
+             * We should probably remove the temp RSA key part from RSAPSK 
case. */
+            /*
+                       rsa=cert->rsa_tmp;
+                       if ((rsa == NULL) && (s->cert->rsa_tmp_cb != NULL))
+                               {
+                               rsa=s->cert->rsa_tmp_cb(s,
+                                     SSL_C_IS_EXPORT(s->s3->tmp.new_cipher),
+                                     
SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher));
+                               if(rsa == NULL)
+                               {
+                                       al=SSL_AD_HANDSHAKE_FAILURE;
+                                       
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_ERROR_GENERATING_TMP_RSA_KEY);
+                                       goto f_err;
+                               }
+                               RSA_up_ref(rsa);
+                               cert->rsa_tmp=rsa;
+                               }
+                       if (rsa == NULL)
+                               {
+                               al=SSL_AD_HANDSHAKE_FAILURE;
+                               
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_RSA_KEY);
+                               goto f_err;
+                               }
+                       r[0]=rsa->n;
+                       r[1]=rsa->e;
+                       s->s3->tmp.use_rsa_tmp=1;
+            */
+            /* PSK part */
+                   /* reserve size for record length and PSK identity hint */
+                       n+=2+strlen(s->ctx->psk_identity_hint);
+                       }
+               else
+#endif /* !OPENSSL_NO_PSK */
+#endif /* !OPENSSL_NO_RSA */
                        {
                        al=SSL_AD_HANDSHAKE_FAILURE;
                        
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
@@ -1680,9 +1725,10 @@
 
                if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)
                        && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
+            /* CJD: no change needed for RSAPSK. we need the pkey 
+             * in case of RSAPSK. */
                        {
-                       if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher))
-                               == NULL)
+                       if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher)) 
== NULL)
                                {
                                al=SSL_AD_DECODE_ERROR;
                                goto f_err;
@@ -1736,9 +1782,9 @@
 #endif
 
 #ifndef OPENSSL_NO_PSK
-               if (type & SSL_kPSK)
+               if (type & (SSL_kPSK|SSL_kRSAPSK)) // CJD
                        {
-                       /* copy PSK identity hint */
+                       /* copy PSK identity hint into ServerKeyExchange msg */
                        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);
@@ -1753,28 +1799,33 @@
 #ifndef OPENSSL_NO_RSA
                        if (pkey->type == EVP_PKEY_RSA)
                                {
-                               q=md_buf;
-                               j=0;
-                               for (num=2; num > 0; num--)
-                                       {
-                                       EVP_DigestInit_ex(&md_ctx,(num == 2)
-                                               ?s->ctx->md5:s->ctx->sha1, 
NULL);
-                                       
EVP_DigestUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
-                                       
EVP_DigestUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
-                                       EVP_DigestUpdate(&md_ctx,&(d[4]),n);
-                                       EVP_DigestFinal_ex(&md_ctx,q,
-                                               (unsigned int *)&i);
-                                       q+=i;
-                                       j+=i;
-                                       }
-                               if (RSA_sign(NID_md5_sha1, md_buf, j,
-                                       &(p[2]), &u, pkey->pkey.rsa) <= 0)
-                                       {
-                                       
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_RSA);
-                                       goto err;
-                                       }
-                               s2n(u,p);
-                               n+=u+2;
+                /* CJD: I think the following is where the temp RSA key
+                 * is put into the ServerKeyExchange msg and this should
+                 * be skipped for RSAPSK */
+                if(!(type & SSL_kRSAPSK)) {
+                    q=md_buf;
+                    j=0;
+                    for (num=2; num > 0; num--)
+                        {
+                        EVP_DigestInit_ex(&md_ctx,(num == 2)
+                            ?s->ctx->md5:s->ctx->sha1, NULL);
+                        
EVP_DigestUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
+                        
EVP_DigestUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
+                        EVP_DigestUpdate(&md_ctx,&(d[4]),n);
+                        EVP_DigestFinal_ex(&md_ctx,q,
+                            (unsigned int *)&i);
+                        q+=i;
+                        j+=i;
+                        }
+                    if (RSA_sign(NID_md5_sha1, md_buf, j,
+                        &(p[2]), &u, pkey->pkey.rsa) <= 0)
+                        {
+                        
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_RSA);
+                        goto err;
+                        }
+                    s2n(u,p);
+                    n+=u+2;
+                    }
                                }
                        else
 #endif
@@ -1974,6 +2025,7 @@
        alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
 
 #ifndef OPENSSL_NO_RSA
+    /** plain RSA case for ClientKeyExchange **/
        if (alg_k & SSL_kRSA)
                {
                /* FIX THIS UP EAY EAY EAY EAY */
@@ -2008,7 +2060,9 @@
                /* TLS and [incidentally] DTLS{0xFEFF} */
                if (s->version > SSL3_VERSION && s->version != DTLS1_BAD_VER)
                        {
-                       n2s(p,i);
+                       n2s(p,i);   // read uint16 from p into i, increases p 
by 2
+            /* guess: n contains message length
+             * compare n with the specified length in i */
                        if (n != i+2)
                                {
                                if (!(s->options & SSL_OP_TLS_D5_BUG))
@@ -2023,6 +2077,7 @@
                                n=i;
                        }
 
+        // decrypt n bytes from p into p
                i=RSA_private_decrypt((int)n,p,p,rsa,RSA_PKCS1_PADDING);
 
                al = -1;
@@ -2486,6 +2541,7 @@
        else
 #endif
 #ifndef OPENSSL_NO_PSK
+        /** plain PSK case **/
                if (alg_k & SSL_kPSK)
                        {
                        unsigned char *t = NULL;
@@ -2580,6 +2636,235 @@
                        }
                else
 #endif
+#ifndef OPENSSL_NO_RSA
+#ifndef OPENSSL_NO_PSK
+    /** This handles RSA-PSK ClientKeyExchange **/
+       if (alg_k & SSL_kRSAPSK)
+               {
+        unsigned char *t = NULL;
+        /* orig_p points to the initial value of p and is required 
+         * for a call to OPENSSL_cleanse at the end. don't touch! */
+        unsigned char *orig_p = p;
+        unsigned char psk_or_pre_ms[PSK_MAX_PSK_LEN*2+4];
+        unsigned int pre_ms_len = 0, psk_len = 0;
+        char tmp_id[PSK_MAX_IDENTITY_LEN+1]; // temp storage for the identity 
str
+        int b_consumed = 0; // counts the number of consumed bytes of CKE 
payload
+        int epms_len = 0; // length of encrypted premaster secret
+        int psk_err = 1; // error flag for the RSAPSK branch
+
+        /**
+         * things defined elsewhere, but used here (CKE=ClientKeyExchange):
+         * n (probably) contains the CKE payload length 
+         * p points to the CKE payload **/
+
+               /* 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 rsapsk_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 rsapsk_err;
+                               }
+                       rsa=pkey->pkey.rsa;
+                       }
+
+        /* In plain RSA key exchange, the ClientKeyExchange payload consists 
+         * of epms_len (2 bytes) and the encrypted premaster secret (>SSLv3).
+         *               [epms_len] [epms] 
+         * len in bytes       2        m     
+         *
+         * For RSAPSK it looks like so:
+         *               [id_len] [identity] [epms_len] [epms] 
+         * len in bytes     2         k          2        m     
+         *
+         * [epms], when decrypted, consists of:
+         *               [version] [random_by_client]
+         * len in bytes      2            46                             */
+        /* read and check id_len */
+        n2s(p,i); // read 2 bytes as uint16 from p into i, p+=2
+        b_consumed+=2; // increase the total num of CKE payload bytes read
+        if (i > PSK_MAX_IDENTITY_LEN)
+            {
+            SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+                SSL_R_DATA_LENGTH_TOO_LONG);
+            goto rsapsk_err;
+            }
+        if (s->psk_server_callback == NULL)
+            {
+            SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+                   SSL_R_PSK_NO_SERVER_CB);
+            goto rsapsk_err;
+            }
+
+        /* read identity */
+        /* Create guaranteed NULL-terminated identity
+         * string for the callback */
+        memcpy(tmp_id, p, i);
+        p+=i; // make p point to after [identity]
+        b_consumed+=i;
+        // fill remaining space in tmp_id with zeroes
+        memset(tmp_id+i, 0, PSK_MAX_IDENTITY_LEN+1-i);
+        /* get the PSK via callback */
+        psk_len = s->psk_server_callback(s, tmp_id,
+            psk_or_pre_ms, sizeof(psk_or_pre_ms));
+        OPENSSL_cleanse(tmp_id, PSK_MAX_IDENTITY_LEN+1);
+
+        // psk_len error handling
+        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)
+            {
+            /* 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 rsapsk_err;
+            }
+
+        /** read epms_len and then read and decrypt epms **/
+        n2s(p,i); // read 2 bytes as uint16 from p into i, p+=2
+        epms_len=i;
+        /** 
+         * FIXME: add a check
+         *   epms_len     ==   (total_payload_len) - (payload_bytes_consumed)
+         *   epms_len  should equal   n - b_consumed                    **/
+        // decrypt  epms_len  bytes from p into p (the premaster secret)
+               i=RSA_private_decrypt(epms_len, p, p, 
+                rsa, RSA_PKCS1_PADDING);
+
+               al = -1;
+               
+               if (i != SSL_MAX_MASTER_KEY_LENGTH)
+                       {
+                       al=SSL_AD_DECODE_ERROR;
+                       /* 
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_RSA_DECRYPT); */
+                       }
+
+        /** now check the version (first 2 bytes of the premaster secret) **/
+               if ((al == -1) && !((p[0] == (s->client_version>>8)) && (p[1] 
== (s->client_version & 0xff))))
+                       {
+                       /* The premaster secret must contain the same version 
number as the
+                        * ClientHello to detect version rollback attacks 
(strangely, the
+                        * protocol does not offer such protection for DH 
ciphersuites).
+                        * However, buggy clients exist that send the 
negotiated protocol
+                        * version instead if the server does not support the 
requested
+                        * protocol version.
+                        * If SSL_OP_TLS_ROLLBACK_BUG is set, tolerate such 
clients. */
+                       if (!((s->options & SSL_OP_TLS_ROLLBACK_BUG) &&
+                               (p[0] == (s->version>>8)) && (p[1] == 
(s->version & 0xff))))
+                               {
+                               al=SSL_AD_DECODE_ERROR;
+                               /* 
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_PROTOCOL_VERSION_NUMBER); */
+
+                               /* The Klima-Pokorny-Rosa extension of 
Bleichenbacher's attack
+                                * (http://eprint.iacr.org/2003/052/) exploits 
the version
+                                * number check as a "bad version oracle" -- an 
alert would
+                                * reveal that the plaintext corresponding to 
some ciphertext
+                                * made up by the adversary is properly 
formatted except
+                                * that the version number is wrong.  To avoid 
such attacks,
+                                * we should treat this just like any other 
decryption error. */
+                               }
+                       }
+
+               if (al != -1)
+                       {
+                       /* Some decryption failure -- use random value instead 
as countermeasure
+                        * against Bleichenbacher's attack on PKCS #1 v1.5 RSA 
padding
+                        * (see RFC 2246, section 7.4.7.1). */
+                       ERR_clear_error();
+                       i = SSL_MAX_MASTER_KEY_LENGTH;
+                       p[0] = s->client_version >> 8;
+                       p[1] = s->client_version & 0xff;
+                       if (RAND_pseudo_bytes(p+2, i-2) <= 0) /* should be 
RAND_bytes, but we cannot work around a failure */
+                               goto rsapsk_err; // CHECKME CD: goto target 
correctly adapted? was err
+                       }
+       
+        /* create RSA-PSK pre_master_secret, it should look like pre_ms at the 
end
+         *
+         * // currently the psk is at the beginning of psk_or_pre_ms
+         * psk_or_pre_ms = [psk]....
+         *
+         * N = len(psk) in octets
+         *          [A]     [B1]     [B2]     [C]    [D]
+         * pre_ms = 48 +  version + random +   N  +  psk
+         *          2b +     2b   +   46b  +  2b  +  N bytes */
+        pre_ms_len=2+2+46+2+psk_len;
+        // initialize t at beginning of psk_or_pre_ms, then increase it as 
necessary
+        t = psk_or_pre_ms;
+        // move the PSK from the beginning to the end   [D]
+        memmove(psk_or_pre_ms+52, psk_or_pre_ms, psk_len);
+        // prefix (48 as uint16)  [A]
+        unsigned int pmsprefix = 48;
+        s2n(pmsprefix, t);   // write 48 into t, automatically increases t
+        // copy version [B1] and random [B2] (48 bytes) from p into t
+        memcpy(t, p, 48);
+        t+=48;
+        // write psk_len into t   [C]
+        s2n(psk_len, t);
+        // at this point psk_or_pre_ms is filled with the premaster secret
+
+        if (s->session->psk_identity != NULL)
+            OPENSSL_free(s->session->psk_identity);
+        /* in the plain PSK case, the following line copies the identity
+         * from the payload into the session. must be adapted for the
+         * RSAPSK case. */
+        //s->session->psk_identity = BUF_strdup((char *)p);
+        // CHECKME CD: is this correctly adapted? CD
+        s->session->psk_identity = BUF_strdup(tmp_id);
+        OPENSSL_cleanse(tmp_id, PSK_MAX_IDENTITY_LEN+1);
+        if (s->session->psk_identity == NULL)
+            {
+            SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+                ERR_R_MALLOC_FAILURE);
+            goto rsapsk_err;
+            }
+
+        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;
+            }
+
+        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;
+               //FIXME OPENSSL_cleanse(p,i); // this came from the plain RSA 
case and cleans the 48 bytes decrypted premaster secret
+        OPENSSL_cleanse(orig_p, n); // clear the whole payload area
+    rsapsk_err: // this label has been renamed from psk_err ro rsapsk_err
+        OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms));
+        if (psk_err != 0)
+            goto f_err;
+        }
+    else
+#endif /* !OPENSSL_NO_PSK */
+#endif /* !OPENSSL_NO_RSA */
                if (alg_k & SSL_kGOST) 
                        {
                        int ret = 0;
diff -ur -x .svn openssl-1.0.0c-orig/ssl/ssl_ciph.c 
openssl-1.0.0c-tlsrsapsk/ssl/ssl_ciph.c
--- openssl-1.0.0c-orig/ssl/ssl_ciph.c  2010-06-15 19:25:14.000000000 +0200
+++ openssl-1.0.0c-tlsrsapsk/ssl/ssl_ciph.c     2011-02-25 19:57:20.466303441 
+0100
@@ -246,7 +246,8 @@
        {0,SSL_TXT_kEECDH,0,  SSL_kEECDH,0,0,0,0,0,0,0,0},
        {0,SSL_TXT_ECDH,0,    SSL_kECDHr|SSL_kECDHe|SSL_kEECDH,0,0,0,0,0,0,0,0},
 
-        {0,SSL_TXT_kPSK,0,    SSL_kPSK,  0,0,0,0,0,0,0,0},
+    {0,SSL_TXT_kPSK,0,    SSL_kPSK,  0,0,0,0,0,0,0,0},
+    {0,SSL_TXT_kRSAPSK,0, SSL_kRSAPSK,  0,0,0,0,0,0,0,0},
        {0,SSL_TXT_kGOST,0, SSL_kGOST,0,0,0,0,0,0,0,0},
 
        /* server authentication aliases */
@@ -259,7 +260,7 @@
        {0,SSL_TXT_aECDH,0,   0,SSL_aECDH, 0,0,0,0,0,0,0},
        {0,SSL_TXT_aECDSA,0,  0,SSL_aECDSA,0,0,0,0,0,0,0},
        {0,SSL_TXT_ECDSA,0,   0,SSL_aECDSA, 0,0,0,0,0,0,0},
-        {0,SSL_TXT_aPSK,0,    0,SSL_aPSK,  0,0,0,0,0,0,0},
+    {0,SSL_TXT_aPSK,0,    0,SSL_aPSK,  0,0,0,0,0,0,0},
        {0,SSL_TXT_aGOST94,0,0,SSL_aGOST94,0,0,0,0,0,0,0},
        {0,SSL_TXT_aGOST01,0,0,SSL_aGOST01,0,0,0,0,0,0,0},
        {0,SSL_TXT_aGOST,0,0,SSL_aGOST94|SSL_aGOST01,0,0,0,0,0,0,0},
@@ -272,7 +273,9 @@
        {0,SSL_TXT_RSA,0,     SSL_kRSA,SSL_aRSA,0,0,0,0,0,0,0},
        {0,SSL_TXT_ADH,0,     SSL_kEDH,SSL_aNULL,0,0,0,0,0,0,0},
        {0,SSL_TXT_AECDH,0,   SSL_kEECDH,SSL_aNULL,0,0,0,0,0,0,0},
-        {0,SSL_TXT_PSK,0,     SSL_kPSK,SSL_aPSK,0,0,0,0,0,0,0},
+    {0,SSL_TXT_PSK,0,     SSL_kPSK,SSL_aPSK,0,0,0,0,0,0,0},
+    // CJD: RSAPSK is  PSK as key exchange  and  RSA as auth_algo
+    {0,SSL_TXT_RSAPSK,0,  SSL_kRSAPSK,SSL_aRSA,0,0,0,0,0,0,0},
 
 
        /* symmetric encryption aliases */
@@ -658,7 +661,7 @@
        *auth |= SSL_aECDH;
 #endif
 #ifdef OPENSSL_NO_PSK
-       *mkey |= SSL_kPSK;
+       *mkey |= SSL_kPSK|SSL_kRSAPSK;
        *auth |= SSL_aPSK;
 #endif
        /* Check for presence of GOST 34.10 algorithms, and if they
@@ -1341,6 +1344,8 @@
        ssl_cipher_apply_rule(0, 0, SSL_aECDH, 0, 0, 0, 0, CIPHER_ORD, -1, 
&head, &tail);
        /* ssl_cipher_apply_rule(0, 0, SSL_aDH, 0, 0, 0, 0, CIPHER_ORD, -1, 
&head, &tail); */
        ssl_cipher_apply_rule(0, SSL_kRSA, 0, 0, 0, 0, 0, CIPHER_ORD, -1, 
&head, &tail);
+    // CHECKME CD: RSAPSK comes before plain PSK
+       ssl_cipher_apply_rule(0, SSL_kRSAPSK, 0,0, 0, 0, 0, CIPHER_ORD, -1, 
&head, &tail);
        ssl_cipher_apply_rule(0, SSL_kPSK, 0,0, 0, 0, 0, CIPHER_ORD, -1, &head, 
&tail);
        ssl_cipher_apply_rule(0, SSL_kKRB5, 0,0, 0, 0, 0, CIPHER_ORD, -1, 
&head, &tail);
 
@@ -1511,6 +1516,9 @@
        case SSL_kPSK:
                kx="PSK";
                break;
+       case SSL_kRSAPSK:
+               kx="RSAPSK";
+               break;
        default:
                kx="unknown";
                }
diff -ur -x .svn openssl-1.0.0c-orig/ssl/ssl.h 
openssl-1.0.0c-tlsrsapsk/ssl/ssl.h
--- openssl-1.0.0c-orig/ssl/ssl.h       2010-01-06 18:37:38.000000000 +0100
+++ openssl-1.0.0c-tlsrsapsk/ssl/ssl.h  2011-02-25 19:57:20.467303448 +0100
@@ -250,7 +250,8 @@
 #define SSL_TXT_kECDHe         "kECDHe"
 #define SSL_TXT_kECDH          "kECDH"
 #define SSL_TXT_kEECDH         "kEECDH"
-#define SSL_TXT_kPSK            "kPSK"
+#define SSL_TXT_kPSK        "kPSK"
+#define SSL_TXT_kRSAPSK     "kRSAPSK"
 #define SSL_TXT_kGOST          "kGOST"
 
 #define        SSL_TXT_aRSA            "aRSA"
@@ -274,7 +275,8 @@
 #define SSL_TXT_AECDH          "AECDH"
 #define SSL_TXT_ECDSA          "ECDSA"
 #define SSL_TXT_KRB5           "KRB5"
-#define SSL_TXT_PSK             "PSK"
+#define SSL_TXT_PSK         "PSK"
+#define SSL_TXT_RSAPSK      "RSAPSK"
 
 #define SSL_TXT_DES            "DES"
 #define SSL_TXT_3DES           "3DES"
diff -ur -x .svn openssl-1.0.0c-orig/ssl/ssl_lib.c 
openssl-1.0.0c-tlsrsapsk/ssl/ssl_lib.c
--- openssl-1.0.0c-orig/ssl/ssl_lib.c   2010-06-15 19:25:14.000000000 +0200
+++ openssl-1.0.0c-tlsrsapsk/ssl/ssl_lib.c      2011-02-25 19:57:20.471303475 
+0100
@@ -1362,7 +1362,8 @@
 #endif /* OPENSSL_NO_KRB5 */
 #ifndef OPENSSL_NO_PSK
                /* with PSK there must be client callback set */
-               if (((c->algorithm_mkey & SSL_kPSK) || (c->algorithm_auth & 
SSL_aPSK)) &&
+               if (((c->algorithm_mkey & (SSL_kPSK|SSL_kRSAPSK)) 
+            || (c->algorithm_auth & SSL_aPSK)) &&
                    s->psk_client_callback == NULL)
                        continue;
 #endif /* OPENSSL_NO_PSK */
@@ -2016,8 +2017,10 @@
 
 #ifndef OPENSSL_NO_PSK
        mask_k |= SSL_kPSK;
+       mask_k |= SSL_kRSAPSK;   // CJD
        mask_a |= SSL_aPSK;
        emask_k |= SSL_kPSK;
+       emask_k |= SSL_kRSAPSK;  // CJD
        emask_a |= SSL_aPSK;
 #endif
 
@@ -2119,6 +2122,10 @@
        
        alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
        alg_a = s->s3->tmp.new_cipher->algorithm_auth;
+#ifdef RSAPSK_DEBUG
+    printf("ssl_get_server_send_cert: alg_k=%08lx alg_a=%08lx\n", alg_k, 
alg_a);
+    fflush(stdout);
+#endif /* RSAPSK_DEBUG */
 
        if (alg_k & (SSL_kECDHr|SSL_kECDHe))
                {
diff -ur -x .svn openssl-1.0.0c-orig/ssl/ssl_locl.h 
openssl-1.0.0c-tlsrsapsk/ssl/ssl_locl.h
--- openssl-1.0.0c-orig/ssl/ssl_locl.h  2009-12-08 12:38:18.000000000 +0100
+++ openssl-1.0.0c-tlsrsapsk/ssl/ssl_locl.h     2011-02-25 19:57:20.472303472 
+0100
@@ -289,6 +289,7 @@
 #define SSL_kEECDH             0x00000080L /* ephemeral ECDH */
 #define SSL_kPSK               0x00000100L /* PSK */
 #define SSL_kGOST       0x00000200L /* GOST key exchange */
+#define SSL_kRSAPSK            0x00000400L /* RSA-PSK */
 
 /* Bits for algorithm_auth (server authentication) */
 #define SSL_aRSA               0x00000001L /* RSA auth */
diff -ur -x .svn openssl-1.0.0c-orig/ssl/tls1.h 
openssl-1.0.0c-tlsrsapsk/ssl/tls1.h
--- openssl-1.0.0c-orig/ssl/tls1.h      2009-11-11 15:51:29.000000000 +0100
+++ openssl-1.0.0c-tlsrsapsk/ssl/tls1.h 2011-02-25 19:57:20.472303472 +0100
@@ -292,6 +292,9 @@
 #define TLS1_CK_PSK_WITH_3DES_EDE_CBC_SHA               0x0300008B
 #define TLS1_CK_PSK_WITH_AES_128_CBC_SHA                0x0300008C
 #define TLS1_CK_PSK_WITH_AES_256_CBC_SHA                0x0300008D
+/* RSA-PSK */
+// FIXME: add RSA-PSK ciphers 92-94 here, too
+#define TLS1_CK_RSA_PSK_WITH_AES_256_CBC_SHA            0x03000095
 
 /* Additional TLS ciphersuites from expired Internet Draft
  * draft-ietf-tls-56-bit-ciphersuites-01.txt
@@ -442,6 +445,8 @@
 #define TLS1_TXT_PSK_WITH_3DES_EDE_CBC_SHA             "PSK-3DES-EDE-CBC-SHA"
 #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"
+// FIXME: add the 3 other RSA-PSK ciphers here, too
+#define TLS1_TXT_RSA_PSK_WITH_AES_256_CBC_SHA          "RSA-PSK-AES256-CBC-SHA"
 
 /* Camellia ciphersuites from RFC4132 */
 #define TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA         "CAMELLIA128-SHA"

Reply via email to