summaryrefslogtreecommitdiffstats
path: root/ssl
diff options
context:
space:
mode:
authorNils Larsch <nils@openssl.org>2006-03-10 23:06:27 +0000
committerNils Larsch <nils@openssl.org>2006-03-10 23:06:27 +0000
commitddac197404f585b8da58df794fc3beb9d08e8cd2 (patch)
treebe75e03f93b8ad8c2cf5e76f58d3b11bb73854ed /ssl
parent0e8e6f19b2919e14c5bb7b645a359b96ad9fc13d (diff)
add initial support for RFC 4279 PSK SSL ciphersuites
PR: 1191 Submitted by: Mika Kousa and Pasi Eronen of Nokia Corporation Reviewed by: Nils Larsch
Diffstat (limited to 'ssl')
-rw-r--r--ssl/s3_clnt.c180
-rw-r--r--ssl/s3_enc.c27
-rw-r--r--ssl/s3_lib.c89
-rw-r--r--ssl/s3_srvr.c158
-rw-r--r--ssl/ssl.h77
-rw-r--r--ssl/ssl_asn1.c89
-rw-r--r--ssl/ssl_ciph.c39
-rw-r--r--ssl/ssl_err.c6
-rw-r--r--ssl/ssl_lib.c114
-rw-r--r--ssl/ssl_locl.h36
-rw-r--r--ssl/ssl_sess.c36
-rw-r--r--ssl/ssl_stat.c30
-rw-r--r--ssl/ssl_txt.c32
-rw-r--r--ssl/ssltest.c142
-rw-r--r--ssl/t1_enc.c27
-rw-r--r--ssl/tls1.h38
16 files changed, 1101 insertions, 19 deletions
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 995c8298b8..237dfb61d9 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -121,6 +121,32 @@
* Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
*
*/
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
#include <stdio.h>
#include "ssl_locl.h"
@@ -266,7 +292,9 @@ int ssl3_connect(SSL *s)
case SSL3_ST_CR_CERT_A:
case SSL3_ST_CR_CERT_B:
/* Check if it is anon DH/ECDH */
- if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL))
+ /* or PSK */
+ if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL)
+ && !(s->s3->tmp.new_cipher->algorithms & SSL_kPSK))
{
ret=ssl3_get_server_certificate(s);
if (ret <= 0) goto end;
@@ -1043,17 +1071,28 @@ int ssl3_get_key_exchange(SSL *s)
-1,
s->max_cert_list,
&ok);
-
if (!ok) return((int)n);
if (s->s3->tmp.message_type != SSL3_MT_SERVER_KEY_EXCHANGE)
{
+#ifndef OPENSSL_NO_PSK
+ /* In plain PSK ciphersuite, ServerKeyExchange can be
+ omitted if no identity hint is sent. Set
+ session->sess_cert anyway to avoid problems
+ later.*/
+ if (s->s3->tmp.new_cipher->algorithms & SSL_kPSK)
+ {
+ s->session->sess_cert=ssl_sess_cert_new();
+ if (s->ctx->psk_identity_hint)
+ OPENSSL_free(s->ctx->psk_identity_hint);
+ s->ctx->psk_identity_hint = NULL;
+ }
+#endif
s->s3->tmp.reuse_message=1;
return(1);
}
param=p=(unsigned char *)s->init_msg;
-
if (s->session->sess_cert != NULL)
{
#ifndef OPENSSL_NO_RSA
@@ -1087,6 +1126,51 @@ int ssl3_get_key_exchange(SSL *s)
alg=s->s3->tmp.new_cipher->algorithms;
EVP_MD_CTX_init(&md_ctx);
+#ifndef OPENSSL_NO_PSK
+ if (alg & SSL_kPSK)
+ {
+ char tmp_id_hint[PSK_MAX_IDENTITY_LEN+1];
+
+ al=SSL_AD_HANDSHAKE_FAILURE;
+ n2s(p,i);
+ param_len=i+2;
+ /* Store PSK identity hint for later use, hint is used
+ * in ssl3_send_client_key_exchange. Assume that the
+ * maximum length of a PSK identity hint can be as
+ * long as the maximum length of a PSK identity. */
+ if (i > PSK_MAX_IDENTITY_LEN)
+ {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
+ SSL_R_DATA_LENGTH_TOO_LONG);
+ goto f_err;
+ }
+ if (param_len > n)
+ {
+ al=SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
+ SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH);
+ goto f_err;
+ }
+ /* 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);
+ if (s->ctx->psk_identity_hint != NULL)
+ OPENSSL_free(s->ctx->psk_identity_hint);
+ s->ctx->psk_identity_hint = BUF_strdup(tmp_id_hint);
+ if (s->ctx->psk_identity_hint == NULL)
+ {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
+ goto f_err;
+ }
+
+ p+=i;
+ n-=param_len;
+ }
+ else
+#endif /* !OPENSSL_NO_PSK */
#ifndef OPENSSL_NO_RSA
if (alg & SSL_kRSA)
{
@@ -1430,12 +1514,13 @@ int ssl3_get_key_exchange(SSL *s)
}
else
{
- /* still data left over */
- if (!(alg & SSL_aNULL))
+ if (!(alg & SSL_aNULL) && !(alg & SSL_kPSK))
+ /* aNULL or kPSK do not need public keys */
{
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
goto err;
}
+ /* still data left over */
if (n != 0)
{
al=SSL_AD_DECODE_ERROR;
@@ -2104,6 +2189,88 @@ int ssl3_send_client_key_exchange(SSL *s)
EVP_PKEY_free(srvr_pub_pkey);
}
#endif /* !OPENSSL_NO_ECDH */
+#ifndef OPENSSL_NO_PSK
+ else if (l & SSL_kPSK)
+ {
+ char identity[PSK_MAX_IDENTITY_LEN];
+ 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;
+
+ 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 psk_err;
+ }
+ else if (psk_len == 0)
+ {
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+ SSL_R_PSK_IDENTITY_NOT_FOUND);
+ goto psk_err;
+ }
+
+ /* create PSK pre_master_secret */
+ pre_ms_len = 2+psk_len+2+psk_len;
+ t = psk_or_pre_ms;
+ memmove(psk_or_pre_ms+psk_len+4, psk_or_pre_ms, psk_len);
+ s2n(psk_len, t);
+ memset(t, 0, psk_len);
+ t+=psk_len;
+ s2n(psk_len, t);
+
+ if (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 psk_err;
+ }
+
+ 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 psk_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);
+ n = strlen(identity);
+ s2n(n, p);
+ memcpy(p, identity, n);
+ n+=2;
+ psk_err = 0;
+ psk_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
else
{
ssl3_send_alert(s, SSL3_AL_FATAL,
@@ -2316,7 +2483,6 @@ int ssl3_check_cert_and_algorithm(SSL *s)
#endif
sc=s->session->sess_cert;
-
if (sc == NULL)
{
SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,ERR_R_INTERNAL_ERROR);
@@ -2326,7 +2492,7 @@ int ssl3_check_cert_and_algorithm(SSL *s)
algs=s->s3->tmp.new_cipher->algorithms;
/* we don't have a certificate */
- if (algs & (SSL_aDH|SSL_aNULL|SSL_aKRB5))
+ if (algs & (SSL_aDH|SSL_aNULL|SSL_aKRB5|SSL_kPSK))
return(1);
#ifndef OPENSSL_NO_RSA
diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c
index 4baba2efb5..b4c6f0f19b 100644
--- a/ssl/s3_enc.c
+++ b/ssl/s3_enc.c
@@ -108,6 +108,32 @@
* Hudson (tjh@cryptsoft.com).
*
*/
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
#include <stdio.h>
#include "ssl_locl.h"
@@ -714,6 +740,7 @@ int ssl3_alert_code(int code)
case SSL_AD_UNRECOGNIZED_NAME: return(SSL3_AD_HANDSHAKE_FAILURE);
case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE: return(SSL3_AD_HANDSHAKE_FAILURE);
case SSL_AD_BAD_CERTIFICATE_HASH_VALUE: return(SSL3_AD_HANDSHAKE_FAILURE);
+ case SSL_AD_UNKNOWN_PSK_IDENTITY:return(TLS1_AD_UNKNOWN_PSK_IDENTITY);
default: return(-1);
}
}
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 6ccd8b1324..aecf6d62a8 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -121,6 +121,32 @@
* Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
*
*/
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
#include <stdio.h>
#include <openssl/objects.h>
@@ -997,6 +1023,63 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
SSL_ALL_STRENGTHS
},
#endif
+#ifndef OPENSSL_NO_PSK
+ /* Cipher 8A */
+ {
+ 1,
+ TLS1_TXT_PSK_WITH_RC4_128_SHA,
+ TLS1_CK_PSK_WITH_RC4_128_SHA,
+ SSL_kPSK|SSL_aPSK|SSL_RC4|SSL_SHA|SSL_TLSV1,
+ SSL_NOT_EXP|SSL_MEDIUM,
+ 0,
+ 128,
+ 128,
+ SSL_ALL_CIPHERS,
+ SSL_ALL_STRENGTHS,
+ },
+
+ /* Cipher 8B */
+ {
+ 1,
+ TLS1_TXT_PSK_WITH_3DES_EDE_CBC_SHA,
+ TLS1_CK_PSK_WITH_3DES_EDE_CBC_SHA,
+ SSL_kPSK|SSL_aPSK|SSL_3DES|SSL_SHA|SSL_TLSV1,
+ SSL_NOT_EXP|SSL_HIGH,
+ 0,
+ 168,
+ 168,
+ SSL_ALL_CIPHERS,
+ SSL_ALL_STRENGTHS,
+ },
+
+ /* Cipher 8C */
+ {
+ 1,
+ TLS1_TXT_PSK_WITH_AES_128_CBC_SHA,
+ TLS1_CK_PSK_WITH_AES_128_CBC_SHA,
+ SSL_kPSK|SSL_aPSK|SSL_AES|SSL_SHA|SSL_TLSV1,
+ SSL_NOT_EXP|SSL_MEDIUM,
+ 0,
+ 128,
+ 128,
+ SSL_ALL_CIPHERS,
+ SSL_ALL_STRENGTHS,
+ },
+
+ /* Cipher 8D */
+ {
+ 1,
+ TLS1_TXT_PSK_WITH_AES_256_CBC_SHA,
+ TLS1_CK_PSK_WITH_AES_256_CBC_SHA,
+ SSL_kPSK|SSL_aPSK|SSL_AES|SSL_SHA|SSL_TLSV1,
+ SSL_NOT_EXP|SSL_HIGH,
+ 0,
+ 256,
+ 256,
+ SSL_ALL_CIPHERS,
+ SSL_ALL_STRENGTHS,
+ },
+#endif /* OPENSSL_NO_PSK */
#ifndef OPENSSL_NO_ECDH
/* Cipher C001 */
{
@@ -2018,6 +2101,12 @@ SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
continue;
}
#endif /* OPENSSL_NO_KRB5 */
+#ifndef OPENSSL_NO_PSK
+ /* with PSK there must be server callback set */
+ if ((alg & SSL_PSK) && s->psk_server_callback == NULL)
+ continue;
+#endif /* OPENSSL_NO_PSK */
+
if (SSL_C_IS_EXPORT(c))
{
ok=((alg & emask) == alg)?1:0;
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
index 44b9c9cdac..8859540fa8 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -121,6 +121,32 @@
* Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
*
*/
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
#define REUSE_CIPHER_BUG
#define NETSCAPE_HANG_BUG
@@ -302,7 +328,9 @@ int ssl3_accept(SSL *s)
case SSL3_ST_SW_CERT_A:
case SSL3_ST_SW_CERT_B:
/* Check if it is anon DH or anon ECDH */
- if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL))
+ /* or normal PSK */
+ if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL)
+ && !(s->s3->tmp.new_cipher->algorithms & SSL_kPSK))
{
ret=ssl3_send_server_certificate(s);
if (ret <= 0) goto end;
@@ -336,6 +364,8 @@ int ssl3_accept(SSL *s)
/* only send if a DH key exchange, fortezza or
* RSA but we have a sign only certificate
*
+ * PSK: may send PSK identity hints
+ *
* For ECC ciphersuites, we send a serverKeyExchange
* message only if the cipher suite is either
* ECDH-anon or ECDHE. In other cases, the
@@ -343,6 +373,11 @@ int ssl3_accept(SSL *s)
* 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
+ || ((l & SSL_kPSK) && s->ctx->psk_identity_hint)
+#endif
|| (l & SSL_kECDHE)
|| (l & (SSL_DH|SSL_kFZA))
|| ((l & SSL_kRSA)
@@ -380,7 +415,10 @@ int ssl3_accept(SSL *s)
* (against the specs, but s3_clnt.c accepts this for SSL 3) */
!(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) ||
/* never request cert in Kerberos ciphersuites */
- (s->s3->tmp.new_cipher->algorithms & SSL_aKRB5))
+ (s->s3->tmp.new_cipher->algorithms & SSL_aKRB5)
+ /* With normal PSK Certificates and
+ * Certificate Requests are omitted */
+ || (s->s3->tmp.new_cipher->algorithms & SSL_kPSK))
{
/* no cert request */
skip=1;
@@ -1390,6 +1428,14 @@ int ssl3_send_server_key_exchange(SSL *s)
}
else
#endif /* !OPENSSL_NO_ECDH */
+#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 */
{
al=SSL_AD_HANDSHAKE_FAILURE;
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
@@ -1401,7 +1447,8 @@ int ssl3_send_server_key_exchange(SSL *s)
n+=2+nr[i];
}
- if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL))
+ if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL)
+ && !(s->s3->tmp.new_cipher->algorithms & SSL_kPSK))
{
if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher))
== NULL)
@@ -1457,6 +1504,16 @@ 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(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)
{
@@ -2178,6 +2235,101 @@ int ssl3_get_client_key_exchange(SSL *s)
}
else
#endif
+#ifndef OPENSSL_NO_PSK
+ if (l & 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, PSK_MAX_IDENTITY_LEN+1);
+
+ 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);
+
+ if (s->session->psk_identity != NULL)
+ OPENSSL_free(s->session->psk_identity);
+ s->session->psk_identity = BUF_strdup(p);
+ if (s->session->psk_identity == NULL)
+ {
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+ ERR_R_MALLOC_FAILURE);
+ goto psk_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 psk_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;
+ psk_err:
+ OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms));
+ if (psk_err != 0)
+ goto f_err;
+ }
+ else
+#endif
{
al=SSL_AD_HANDSHAKE_FAILURE;
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
diff --git a/ssl/ssl.h b/ssl/ssl.h
index e4534f3062..33792ea8fe 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -166,6 +166,32 @@
* ECC cipher suite support in OpenSSL originally developed by
* SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
*/
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
#ifndef HEADER_SSL_H
#define HEADER_SSL_H
@@ -294,6 +320,9 @@ extern "C" {
#define SSL_TXT_TLSV1 "TLSv1"
#define SSL_TXT_ALL "ALL"
#define SSL_TXT_ECC "ECCdraft" /* ECC ciphersuites are not yet official */
+#define SSL_TXT_PSK "PSK"
+#define SSL_TXT_kPSK "kPSK"
+#define SSL_TXT_aPSK "aPSK"
/*
* COMPLEMENTOF* definitions. These identifiers are used to (de-select)
@@ -410,8 +439,9 @@ typedef struct ssl_method_st
* Timeout [ 2 ] EXPLICIT INTEGER, -- optional Timeout ins seconds
* Peer [ 3 ] EXPLICIT X509, -- optional Peer Certificate
* Session_ID_context [ 4 ] EXPLICIT OCTET_STRING, -- the Session ID context
- * Verify_result [ 5 ] EXPLICIT INTEGER -- X509_V_... code for `Peer'
- * Compression [6] IMPLICIT ASN1_OBJECT -- compression OID XXXXX
+ * Verify_result [ 5 ] EXPLICIT INTEGER, -- X509_V_... code for `Peer'
+ * PSK_identity_hint [ 6 ] EXPLICIT OCTET_STRING, -- PSK identity hint
+ * PSK_identity [ 7 ] EXPLICIT OCTET_STRING -- PSK identity
* }
* Look in ssl/ssl_asn1.c for more details
* I'm using EXPLICIT tags so I can read the damn things using asn1parse :-).
@@ -439,7 +469,10 @@ typedef struct ssl_session_st
unsigned int krb5_client_princ_len;
unsigned char krb5_client_princ[SSL_MAX_KRB5_PRINCIPAL_LENGTH];
#endif /* OPENSSL_NO_KRB5 */
-
+#ifndef OPENSSL_NO_PSK
+ char *psk_identity_hint;
+ char *psk_identity;
+#endif
int not_resumable;
/* The cert is the certificate used to establish this connection */
@@ -764,6 +797,14 @@ struct ssl_ctx_st
int (*tlsext_servername_callback)(SSL*, int *, void *);
void *tlsext_servername_arg;
#endif
+#ifndef OPENSSL_NO_PSK
+ char *psk_identity_hint;
+ unsigned int (*psk_client_callback)(SSL *ssl, const char *hint, char *identity,
+ unsigned int max_identity_len, unsigned char *psk,
+ unsigned int max_psk_len);
+ unsigned int (*psk_server_callback)(SSL *ssl, const char *identity,
+ unsigned char *psk, unsigned int max_psk_len);
+#endif
};
#define SSL_SESS_CACHE_OFF 0x0000
@@ -816,6 +857,21 @@ struct ssl_ctx_st
#define SSL_CTX_set_cookie_generate_cb(ctx,cb) ((ctx)->app_gen_cookie_cb=(cb))
#define SSL_CTX_set_cookie_verify_cb(ctx,cb) ((ctx)->app_verify_cookie_cb=(cb))
+#ifndef OPENSSL_NO_PSK
+/* the maximum length of the buffer given to callbacks containing the
+ * resulting identity/psk */
+#define PSK_MAX_IDENTITY_LEN 128
+#define PSK_MAX_PSK_LEN 64
+#define SSL_CTX_set_psk_client_callback(ctx,cb) ((ctx)->psk_client_callback=(cb))
+#define SSL_set_psk_client_callback(ssl, cb) ((ssl)->psk_client_callback=(cb))
+#define SSL_CTX_set_psk_server_callback(ctx,cb) ((ctx)->psk_server_callback=(cb))
+#define SSL_set_psk_server_callback(ssl, cb) ((ssl)->psk_server_callback=(cb))
+int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint);
+int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint);
+const char *SSL_get_psk_identity_hint(const SSL *s);
+const char *SSL_get_psk_identity(const SSL *s);
+#endif
+
#define SSL_NOTHING 1
#define SSL_WRITING 2
#define SSL_READING 3
@@ -966,6 +1022,14 @@ struct ssl_st
KSSL_CTX *kssl_ctx; /* Kerberos 5 context */
#endif /* OPENSSL_NO_KRB5 */
+#ifndef OPENSSL_NO_PSK
+ unsigned int (*psk_client_callback)(SSL *ssl, const char *hint, char *identity,
+ unsigned int max_identity_len, unsigned char *psk,
+ unsigned int max_psk_len);
+ unsigned int (*psk_server_callback)(SSL *ssl, const char *identity,
+ unsigned char *psk, unsigned int max_psk_len);
+#endif
+
SSL_CTX *ctx;
/* set this flag to 1 and a sleep(1) is put into all SSL_read()
* and SSL_write() calls, good for nbio debuging :-) */
@@ -1149,6 +1213,7 @@ size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count);
#define SSL_AD_UNRECOGNIZED_NAME TLS1_AD_UNRECOGNIZED_NAME
#define SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE
#define SSL_AD_BAD_CERTIFICATE_HASH_VALUE TLS1_AD_BAD_CERTIFICATE_HASH_VALUE
+#define SSL_AD_UNKNOWN_PSK_IDENTITY TLS1_AD_UNKNOWN_PSK_IDENTITY /* fatal */
#define SSL_ERROR_NONE 0
#define SSL_ERROR_SSL 1
@@ -1718,6 +1783,7 @@ void ERR_load_SSL_strings(void);
#define SSL_F_SSL_CTX_USE_PRIVATEKEY 174
#define SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1 175
#define SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE 176
+#define SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT 272
#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY 177
#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1 178
#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE 179
@@ -1756,6 +1822,7 @@ void ERR_load_SSL_strings(void);
#define SSL_F_SSL_USE_PRIVATEKEY 201
#define SSL_F_SSL_USE_PRIVATEKEY_ASN1 202
#define SSL_F_SSL_USE_PRIVATEKEY_FILE 203
+#define SSL_F_SSL_USE_PSK_IDENTITY_HINT 273
#define SSL_F_SSL_USE_RSAPRIVATEKEY 204
#define SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1 205
#define SSL_F_SSL_USE_RSAPRIVATEKEY_FILE 206
@@ -1789,6 +1856,7 @@ void ERR_load_SSL_strings(void);
#define SSL_R_BAD_MESSAGE_TYPE 114
#define SSL_R_BAD_PACKET_LENGTH 115
#define SSL_R_BAD_PROTOCOL_VERSION_NUMBER 116
+#define SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH 157
#define SSL_R_BAD_RESPONSE_ARGUMENT 117
#define SSL_R_BAD_RSA_DECRYPT 118
#define SSL_R_BAD_RSA_ENCRYPT 119
@@ -1908,6 +1976,9 @@ void ERR_load_SSL_strings(void);
#define SSL_R_PRE_MAC_LENGTH_TOO_LONG 205
#define SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS 206
#define SSL_R_PROTOCOL_IS_SHUTDOWN 207
+#define SSL_R_PSK_IDENTITY_NOT_FOUND 223
+#define SSL_R_PSK_NO_CLIENT_CB 224
+#define SSL_R_PSK_NO_SERVER_CB 225
#define SSL_R_PUBLIC_KEY_ENCRYPT_ERROR 208
#define SSL_R_PUBLIC_KEY_IS_NOT_RSA 209
#define SSL_R_PUBLIC_KEY_NOT_RSA 210
diff --git a/ssl/ssl_asn1.c b/ssl/ssl_asn1.c
index 1ff31d4402..a8193a58da 100644
--- a/ssl/ssl_asn1.c
+++ b/ssl/ssl_asn1.c
@@ -55,6 +55,32 @@
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
#include <stdio.h>
#include <stdlib.h>
@@ -81,12 +107,16 @@ typedef struct ssl_session_asn1_st
#ifndef OPENSSL_NO_TLSEXT
ASN1_OCTET_STRING tlsext_hostname;
#endif /* OPENSSL_NO_TLSEXT */
+#ifndef OPENSSL_NO_PSK
+ ASN1_OCTET_STRING psk_identity_hint;
+ ASN1_OCTET_STRING psk_identity;
+#endif /* OPENSSL_NO_PSK */
} SSL_SESSION_ASN1;
int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
{
#define LSIZE2 (sizeof(long)*2)
- int v1=0,v2=0,v3=0,v4=0,v5=0,v6=0;
+ int v1=0,v2=0,v3=0,v4=0,v5=0,v6=0,v7=0,v8=0;
unsigned char buf[4],ibuf1[LSIZE2],ibuf2[LSIZE2];
unsigned char ibuf3[LSIZE2],ibuf4[LSIZE2],ibuf5[LSIZE2];
long l;
@@ -156,7 +186,7 @@ int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
a.krb5_princ.data=in->krb5_client_princ;
}
#endif /* OPENSSL_NO_KRB5 */
-
+
if (in->time != 0L)
{
a.time.length=LSIZE2;
@@ -189,6 +219,20 @@ int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
a.tlsext_hostname.data=(unsigned char *)in->tlsext_hostname;
}
#endif /* OPENSSL_NO_TLSEXT */
+#ifndef OPENSSL_NO_PSK
+ if (in->psk_identity_hint)
+ {
+ a.psk_identity_hint.length=strlen(in->psk_identity_hint);
+ a.psk_identity_hint.type=V_ASN1_OCTET_STRING;
+ a.psk_identity_hint.data=in->psk_identity_hint;
+ }
+ if (in->psk_identity)
+ {
+ a.psk_identity.length=strlen(in->psk_identity);
+ a.psk_identity.type=V_ASN1_OCTET_STRING;
+ a.psk_identity.data=in