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"