mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-30 21:45:20 +00:00
d83a3d71bc
Merge in RedPhone // FREEBIE
1406 lines
39 KiB
Diff
1406 lines
39 KiB
Diff
From 1d43b892d27915843e5714d96de269672b5b35db Mon Sep 17 00:00:00 2001
|
|
From: Adam Langley <agl@chromium.org>
|
|
Date: Thu, 14 Nov 2013 16:12:01 -0500
|
|
Subject: Implement ECDHE-PSK-WITH-AES.
|
|
|
|
Add support for TLS-ECDHE-PSK cipher suites:
|
|
* TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256, and
|
|
* TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA384.
|
|
---
|
|
ssl/s3_clnt.c | 360 ++++++++++++++++++++++----------------
|
|
ssl/s3_enc.c | 2 +-
|
|
ssl/s3_lib.c | 38 +++++-
|
|
ssl/s3_srvr.c | 541 ++++++++++++++++++++++++++++++++--------------------------
|
|
ssl/ssl_lib.c | 2 +-
|
|
ssl/tls1.h | 8 +
|
|
6 files changed, 555 insertions(+), 396 deletions(-)
|
|
|
|
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
|
|
index 8f3740f..3672cce 100644
|
|
--- a/ssl/s3_clnt.c
|
|
+++ b/ssl/s3_clnt.c
|
|
@@ -333,9 +333,10 @@ int ssl3_connect(SSL *s)
|
|
}
|
|
#endif
|
|
/* Check if it is anon DH/ECDH */
|
|
- /* or PSK */
|
|
+ /* or non-RSA PSK */
|
|
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_aPSK) &&
|
|
+ !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kRSA)))
|
|
{
|
|
ret=ssl3_get_server_certificate(s);
|
|
if (ret <= 0) goto end;
|
|
@@ -1368,7 +1369,7 @@ int ssl3_get_key_exchange(SSL *s)
|
|
omitted if no identity hint is sent. Set
|
|
session->sess_cert anyway to avoid problems
|
|
later.*/
|
|
- if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)
|
|
+ if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aPSK)
|
|
{
|
|
s->session->sess_cert=ssl_sess_cert_new();
|
|
if (s->ctx->psk_identity_hint)
|
|
@@ -1416,52 +1417,56 @@ int ssl3_get_key_exchange(SSL *s)
|
|
EVP_MD_CTX_init(&md_ctx);
|
|
|
|
#ifndef OPENSSL_NO_PSK
|
|
- if (alg_k & SSL_kPSK)
|
|
+ if (alg_a & SSL_aPSK)
|
|
{
|
|
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)
|
|
+ s->ctx->psk_identity_hint = NULL;
|
|
+ if (i != 0)
|
|
{
|
|
- al=SSL_AD_DECODE_ERROR;
|
|
- SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
|
|
- SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH);
|
|
- goto f_err;
|
|
+ /* 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;
|
|
+ }
|
|
}
|
|
- /* 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 */
|
|
+
|
|
+ if (0) {}
|
|
#ifndef OPENSSL_NO_SRP
|
|
- if (alg_k & SSL_kSRP)
|
|
+ else if (alg_k & SSL_kSRP)
|
|
{
|
|
n2s(p,i);
|
|
param_len=i+2;
|
|
@@ -1538,10 +1543,9 @@ int ssl3_get_key_exchange(SSL *s)
|
|
pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_DSA_SIGN].x509);
|
|
#endif
|
|
}
|
|
- else
|
|
#endif /* !OPENSSL_NO_SRP */
|
|
#ifndef OPENSSL_NO_RSA
|
|
- if (alg_k & SSL_kRSA)
|
|
+ else if (alg_k & SSL_kRSA)
|
|
{
|
|
if ((rsa=RSA_new()) == NULL)
|
|
{
|
|
@@ -1590,9 +1594,6 @@ int ssl3_get_key_exchange(SSL *s)
|
|
s->session->sess_cert->peer_rsa_tmp=rsa;
|
|
rsa=NULL;
|
|
}
|
|
-#else /* OPENSSL_NO_RSA */
|
|
- if (0)
|
|
- ;
|
|
#endif
|
|
#ifndef OPENSSL_NO_DH
|
|
else if (alg_k & SSL_kEDH)
|
|
@@ -1773,14 +1774,14 @@ int ssl3_get_key_exchange(SSL *s)
|
|
EC_POINT_free(srvr_ecpoint);
|
|
srvr_ecpoint = NULL;
|
|
}
|
|
- else if (alg_k)
|
|
+#endif /* !OPENSSL_NO_ECDH */
|
|
+
|
|
+ else if (!(alg_k & SSL_kPSK))
|
|
{
|
|
al=SSL_AD_UNEXPECTED_MESSAGE;
|
|
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE);
|
|
goto f_err;
|
|
}
|
|
-#endif /* !OPENSSL_NO_ECDH */
|
|
-
|
|
|
|
/* p points to the next byte, there are 'n' bytes left */
|
|
|
|
@@ -1885,8 +1886,9 @@ fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md));
|
|
}
|
|
else
|
|
{
|
|
- if (!(alg_a & SSL_aNULL) && !(alg_k & SSL_kPSK))
|
|
- /* aNULL or kPSK do not need public keys */
|
|
+ if (!(alg_a & SSL_aNULL) &&
|
|
+ /* Among PSK ciphers only RSA_PSK needs a public key */
|
|
+ !((alg_a & SSL_aPSK) && !(alg_k & SSL_kRSA)))
|
|
{
|
|
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
|
|
goto err;
|
|
@@ -2286,8 +2288,9 @@ int ssl3_get_server_done(SSL *s)
|
|
int ssl3_send_client_key_exchange(SSL *s)
|
|
{
|
|
unsigned char *p,*d;
|
|
- int n;
|
|
+ int n = 0;
|
|
unsigned long alg_k;
|
|
+ unsigned long alg_a;
|
|
#ifndef OPENSSL_NO_RSA
|
|
unsigned char *q;
|
|
EVP_PKEY *pkey=NULL;
|
|
@@ -2302,7 +2305,11 @@ int ssl3_send_client_key_exchange(SSL *s)
|
|
unsigned char *encodedPoint = NULL;
|
|
int encoded_pt_len = 0;
|
|
BN_CTX * bn_ctx = NULL;
|
|
-#endif
|
|
+#ifndef OPENSSL_NO_PSK
|
|
+ unsigned int psk_len = 0;
|
|
+ unsigned char psk[PSK_MAX_PSK_LEN];
|
|
+#endif /* OPENSSL_NO_PSK */
|
|
+#endif /* OPENSSL_NO_ECDH */
|
|
|
|
if (s->state == SSL3_ST_CW_KEY_EXCH_A)
|
|
{
|
|
@@ -2310,7 +2317,96 @@ int ssl3_send_client_key_exchange(SSL *s)
|
|
p= &(d[4]);
|
|
|
|
alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
|
|
+ alg_a=s->s3->tmp.new_cipher->algorithm_auth;
|
|
+
|
|
+#ifndef OPENSSL_NO_PSK
|
|
+ if (alg_a & SSL_aPSK)
|
|
+ {
|
|
+ char identity[PSK_MAX_IDENTITY_LEN];
|
|
+ unsigned char *t = NULL;
|
|
+ unsigned char pre_ms[PSK_MAX_PSK_LEN*2+4];
|
|
+ unsigned int pre_ms_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, sizeof(psk));
|
|
+ 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;
|
|
+ }
|
|
+
|
|
+ if (!(alg_k & SSL_kEECDH))
|
|
+ {
|
|
+ /* Create the shared secret now if we're not using ECDHE-PSK.*/
|
|
+ pre_ms_len = 2+psk_len+2+psk_len;
|
|
+ t = pre_ms;
|
|
+ s2n(psk_len, t);
|
|
+ memset(t, 0, psk_len);
|
|
+ t+=psk_len;
|
|
+ s2n(psk_len, t);
|
|
+ memcpy(t, psk, psk_len);
|
|
+
|
|
+ s->session->master_key_length =
|
|
+ s->method->ssl3_enc->generate_master_secret(s,
|
|
+ s->session->master_key,
|
|
+ pre_ms, pre_ms_len);
|
|
+ n = strlen(identity);
|
|
+ s2n(n, p);
|
|
+ memcpy(p, identity, n);
|
|
+ n += 2;
|
|
+ }
|
|
+
|
|
+ if (s->session->psk_identity_hint != NULL)
|
|
+ OPENSSL_free(s->session->psk_identity_hint);
|
|
+ s->session->psk_identity_hint = NULL;
|
|
+ if (s->ctx->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;
|
|
+ }
|
|
+ psk_err = 0;
|
|
+ psk_err:
|
|
+ OPENSSL_cleanse(identity, PSK_MAX_IDENTITY_LEN);
|
|
+ OPENSSL_cleanse(pre_ms, sizeof(pre_ms));
|
|
+ if (psk_err != 0)
|
|
+ {
|
|
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
|
|
+ goto err;
|
|
+ }
|
|
+ }
|
|
+#endif
|
|
/* Fool emacs indentation */
|
|
if (0) {}
|
|
#ifndef OPENSSL_NO_RSA
|
|
@@ -2571,14 +2667,19 @@ int ssl3_send_client_key_exchange(SSL *s)
|
|
/* perhaps clean things up a bit EAY EAY EAY EAY*/
|
|
}
|
|
#endif
|
|
-
|
|
-#ifndef OPENSSL_NO_ECDH
|
|
+#ifndef OPENSSL_NO_ECDH
|
|
else if (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe))
|
|
{
|
|
const EC_GROUP *srvr_group = NULL;
|
|
EC_KEY *tkey;
|
|
int ecdh_clnt_cert = 0;
|
|
int field_size = 0;
|
|
+#ifndef OPENSSL_NO_PSK
|
|
+ unsigned char *pre_ms;
|
|
+ unsigned char *t;
|
|
+ unsigned int pre_ms_len;
|
|
+ unsigned int i;
|
|
+#endif
|
|
|
|
if (s->session->sess_cert == NULL)
|
|
{
|
|
@@ -2706,15 +2807,41 @@ int ssl3_send_client_key_exchange(SSL *s)
|
|
goto err;
|
|
}
|
|
|
|
- /* generate master key from the result */
|
|
- s->session->master_key_length = s->method->ssl3_enc \
|
|
- -> generate_master_secret(s,
|
|
- s->session->master_key,
|
|
- p, n);
|
|
-
|
|
+#ifndef OPENSSL_NO_PSK
|
|
+ /* ECDHE PSK ciphersuites from RFC 5489 */
|
|
+ if ((alg_a & SSL_aPSK) && psk_len != 0)
|
|
+ {
|
|
+ pre_ms_len = 2+psk_len+2+n;
|
|
+ pre_ms = OPENSSL_malloc(pre_ms_len);
|
|
+ if (pre_ms == NULL)
|
|
+ {
|
|
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
|
|
+ ERR_R_MALLOC_FAILURE);
|
|
+ goto err;
|
|
+ }
|
|
+ memset(pre_ms, 0, pre_ms_len);
|
|
+ t = pre_ms;
|
|
+ s2n(psk_len, t);
|
|
+ memcpy(t, psk, psk_len);
|
|
+ t += psk_len;
|
|
+ s2n(n, t);
|
|
+ memcpy(t, p, n);
|
|
+ s->session->master_key_length = s->method->ssl3_enc \
|
|
+ -> generate_master_secret(s,
|
|
+ s->session->master_key, pre_ms, pre_ms_len);
|
|
+ OPENSSL_cleanse(pre_ms, pre_ms_len);
|
|
+ OPENSSL_free(pre_ms);
|
|
+ }
|
|
+#endif /* OPENSSL_NO_PSK */
|
|
+ if (!(alg_a & SSL_aPSK))
|
|
+ {
|
|
+ /* generate master key from the result */
|
|
+ s->session->master_key_length = s->method->ssl3_enc \
|
|
+ -> generate_master_secret(s,
|
|
+ s->session->master_key, p, n);
|
|
+ }
|
|
memset(p, 0, n); /* clean up */
|
|
-
|
|
- if (ecdh_clnt_cert)
|
|
+ if (ecdh_clnt_cert)
|
|
{
|
|
/* Send empty client key exch message */
|
|
n = 0;
|
|
@@ -2742,29 +2869,42 @@ int ssl3_send_client_key_exchange(SSL *s)
|
|
}
|
|
|
|
/* Encode the public key */
|
|
- n = EC_POINT_point2oct(srvr_group,
|
|
- EC_KEY_get0_public_key(clnt_ecdh),
|
|
- POINT_CONVERSION_UNCOMPRESSED,
|
|
+ encoded_pt_len = EC_POINT_point2oct(srvr_group,
|
|
+ EC_KEY_get0_public_key(clnt_ecdh),
|
|
+ POINT_CONVERSION_UNCOMPRESSED,
|
|
encodedPoint, encoded_pt_len, bn_ctx);
|
|
+
|
|
+ n = 0;
|
|
+#ifndef OPENSSL_NO_PSK
|
|
+ if ((alg_a & SSL_aPSK) && psk_len != 0)
|
|
+ {
|
|
+ i = strlen(s->session->psk_identity);
|
|
+ s2n(i, p);
|
|
+ memcpy(p, s->session->psk_identity, i);
|
|
+ p += i;
|
|
+ n = i + 2;
|
|
+ }
|
|
+#endif
|
|
|
|
- *p = n; /* length of encoded point */
|
|
+ *p = encoded_pt_len; /* length of encoded point */
|
|
/* Encoded point will be copied here */
|
|
- p += 1;
|
|
+ p += 1;
|
|
+ n += 1;
|
|
/* copy the point */
|
|
- memcpy((unsigned char *)p, encodedPoint, n);
|
|
+ memcpy((unsigned char *)p, encodedPoint, encoded_pt_len);
|
|
/* increment n to account for length field */
|
|
- n += 1;
|
|
+ n += encoded_pt_len;
|
|
}
|
|
|
|
/* Free allocated memory */
|
|
BN_CTX_free(bn_ctx);
|
|
if (encodedPoint != NULL) OPENSSL_free(encodedPoint);
|
|
- if (clnt_ecdh != NULL)
|
|
+ if (clnt_ecdh != NULL)
|
|
EC_KEY_free(clnt_ecdh);
|
|
EVP_PKEY_free(srvr_pub_pkey);
|
|
}
|
|
#endif /* !OPENSSL_NO_ECDH */
|
|
- else if (alg_k & SSL_kGOST)
|
|
+ else if (alg_k & SSL_kGOST)
|
|
{
|
|
/* GOST key exchange message creation */
|
|
EVP_PKEY_CTX *pkey_ctx;
|
|
@@ -2887,89 +3027,7 @@ int ssl3_send_client_key_exchange(SSL *s)
|
|
}
|
|
}
|
|
#endif
|
|
-#ifndef OPENSSL_NO_PSK
|
|
- else if (alg_k & 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
|
|
+ else if (!(alg_k & SSL_kPSK) || ((alg_k & SSL_kPSK) && !(alg_a & SSL_aPSK)))
|
|
{
|
|
ssl3_send_alert(s, SSL3_AL_FATAL,
|
|
SSL_AD_HANDSHAKE_FAILURE);
|
|
@@ -3274,7 +3332,7 @@ int ssl3_check_cert_and_algorithm(SSL *s)
|
|
alg_a=s->s3->tmp.new_cipher->algorithm_auth;
|
|
|
|
/* we don't have a certificate */
|
|
- if ((alg_a & (SSL_aDH|SSL_aNULL|SSL_aKRB5)) || (alg_k & SSL_kPSK))
|
|
+ if ((alg_a & (SSL_aDH|SSL_aNULL|SSL_aKRB5)) || ((alg_a & SSL_aPSK) && !(alg_k & SSL_kRSA)))
|
|
return(1);
|
|
|
|
sc=s->session->sess_cert;
|
|
diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c
|
|
index 6358e1b..0dac7e7 100644
|
|
--- a/ssl/s3_enc.c
|
|
+++ b/ssl/s3_enc.c
|
|
@@ -734,7 +734,7 @@ int n_ssl3_mac(SSL *ssl, unsigned char *md, int send)
|
|
}
|
|
|
|
t=EVP_MD_CTX_size(hash);
|
|
- if (t < 0)
|
|
+ if (t < 0 || t > 20)
|
|
return -1;
|
|
md_size=t;
|
|
npad=(48/md_size)*md_size;
|
|
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
|
|
index 1d87ac5..77244d3 100644
|
|
--- a/ssl/s3_lib.c
|
|
+++ b/ssl/s3_lib.c
|
|
@@ -2827,6 +2827,42 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
|
|
256,
|
|
},
|
|
|
|
+#ifndef OPENSSL_NO_PSK
|
|
+ /* ECDH PSK ciphersuites from RFC 5489 */
|
|
+
|
|
+ /* Cipher C037 */
|
|
+ {
|
|
+ 1,
|
|
+ TLS1_TXT_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
|
|
+ TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
|
|
+ SSL_kEECDH,
|
|
+ SSL_aPSK,
|
|
+ SSL_AES128,
|
|
+ SSL_SHA256,
|
|
+ SSL_TLSV1,
|
|
+ SSL_NOT_EXP|SSL_HIGH,
|
|
+ SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF_SHA256,
|
|
+ 128,
|
|
+ 128,
|
|
+ },
|
|
+
|
|
+ /* Cipher C038 */
|
|
+ {
|
|
+ 1,
|
|
+ TLS1_TXT_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
|
|
+ TLS1_CK_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
|
|
+ SSL_kEECDH,
|
|
+ SSL_aPSK,
|
|
+ SSL_AES256,
|
|
+ SSL_SHA384,
|
|
+ SSL_TLSV1,
|
|
+ SSL_NOT_EXP|SSL_HIGH,
|
|
+ SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF_SHA384,
|
|
+ 256,
|
|
+ 256,
|
|
+ },
|
|
+#endif /* OPENSSL_NO_PSK */
|
|
+
|
|
#endif /* OPENSSL_NO_ECDH */
|
|
|
|
|
|
@@ -3979,7 +3999,7 @@ SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
|
|
#endif /* OPENSSL_NO_KRB5 */
|
|
#ifndef OPENSSL_NO_PSK
|
|
/* with PSK there must be server callback set */
|
|
- if ((alg_k & SSL_kPSK) && s->psk_server_callback == NULL)
|
|
+ if ((alg_a & SSL_aPSK) && s->psk_server_callback == NULL)
|
|
continue;
|
|
#endif /* OPENSSL_NO_PSK */
|
|
|
|
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
|
|
index 9335eda..fe70124 100644
|
|
--- a/ssl/s3_srvr.c
|
|
+++ b/ssl/s3_srvr.c
|
|
@@ -217,6 +217,7 @@ int ssl3_accept(SSL *s)
|
|
{
|
|
BUF_MEM *buf;
|
|
unsigned long alg_k,Time=(unsigned long)time(NULL);
|
|
+ unsigned long alg_a;
|
|
void (*cb)(const SSL *ssl,int type,int val)=NULL;
|
|
int ret= -1;
|
|
int new_state,state,skip=0;
|
|
@@ -418,9 +419,11 @@ 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, */
|
|
- /* normal PSK or KRB5 or SRP */
|
|
+ /* non-RSA PSK or KRB5 or SRP */
|
|
if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)
|
|
- && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)
|
|
+ /* Among PSK ciphersuites only RSA_PSK uses server certificate */
|
|
+ && !(s->s3->tmp.new_cipher->algorithm_auth & SSL_aPSK &&
|
|
+ !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kRSA))
|
|
&& !(s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5))
|
|
{
|
|
ret=ssl3_send_server_certificate(s);
|
|
@@ -449,6 +452,7 @@ int ssl3_accept(SSL *s)
|
|
case SSL3_ST_SW_KEY_EXCH_A:
|
|
case SSL3_ST_SW_KEY_EXCH_B:
|
|
alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
|
|
+ alg_a = s->s3->tmp.new_cipher->algorithm_auth;
|
|
|
|
/* clear this, it may get reset by
|
|
* send_server_key_exchange */
|
|
@@ -478,10 +482,12 @@ 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 */
|
|
+ /* PSK: send ServerKeyExchange if either:
|
|
+ * - PSK identity hint is provided, or
|
|
+ * - the key exchange is kEECDH.
|
|
+ */
|
|
#ifndef OPENSSL_NO_PSK
|
|
- || ((alg_k & SSL_kPSK) && s->ctx->psk_identity_hint)
|
|
+ || ((alg_a & SSL_aPSK) && ((alg_k & SSL_kEECDH) || s->ctx->psk_identity_hint))
|
|
#endif
|
|
#ifndef OPENSSL_NO_SRP
|
|
/* SRP: send ServerKeyExchange */
|
|
@@ -1658,7 +1664,8 @@ int ssl3_send_server_key_exchange(SSL *s)
|
|
const EVP_MD *md = NULL;
|
|
unsigned char *p,*d;
|
|
int al,i;
|
|
- unsigned long type;
|
|
+ unsigned long alg_k;
|
|
+ unsigned long alg_a;
|
|
int n;
|
|
CERT *cert;
|
|
BIGNUM *r[4];
|
|
@@ -1669,15 +1676,25 @@ int ssl3_send_server_key_exchange(SSL *s)
|
|
EVP_MD_CTX_init(&md_ctx);
|
|
if (s->state == SSL3_ST_SW_KEY_EXCH_A)
|
|
{
|
|
- type=s->s3->tmp.new_cipher->algorithm_mkey;
|
|
+ alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
|
|
+ alg_a=s->s3->tmp.new_cipher->algorithm_auth;
|
|
cert=s->cert;
|
|
|
|
buf=s->init_buf;
|
|
|
|
r[0]=r[1]=r[2]=r[3]=NULL;
|
|
n=0;
|
|
+#ifndef OPENSSL_NO_PSK
|
|
+ if (alg_a & SSL_aPSK)
|
|
+ {
|
|
+ /* size for PSK identity hint */
|
|
+ n+=2;
|
|
+ if (s->ctx->psk_identity_hint)
|
|
+ n+=strlen(s->ctx->psk_identity_hint);
|
|
+ }
|
|
+#endif /* !OPENSSL_NO_PSK */
|
|
#ifndef OPENSSL_NO_RSA
|
|
- if (type & SSL_kRSA)
|
|
+ if (alg_k & SSL_kRSA)
|
|
{
|
|
rsa=cert->rsa_tmp;
|
|
if ((rsa == NULL) && (s->cert->rsa_tmp_cb != NULL))
|
|
@@ -1704,10 +1721,9 @@ int ssl3_send_server_key_exchange(SSL *s)
|
|
r[1]=rsa->e;
|
|
s->s3->tmp.use_rsa_tmp=1;
|
|
}
|
|
- else
|
|
#endif
|
|
#ifndef OPENSSL_NO_DH
|
|
- if (type & SSL_kEDH)
|
|
+ else if (alg_k & SSL_kEDH)
|
|
{
|
|
dhp=cert->dh_tmp;
|
|
if ((dhp == NULL) && (s->cert->dh_tmp_cb != NULL))
|
|
@@ -1760,10 +1776,9 @@ int ssl3_send_server_key_exchange(SSL *s)
|
|
r[1]=dh->g;
|
|
r[2]=dh->pub_key;
|
|
}
|
|
- else
|
|
#endif
|
|
#ifndef OPENSSL_NO_ECDH
|
|
- if (type & SSL_kEECDH)
|
|
+ else if (alg_k & SSL_kEECDH)
|
|
{
|
|
const EC_GROUP *group;
|
|
|
|
@@ -1876,7 +1891,7 @@ int ssl3_send_server_key_exchange(SSL *s)
|
|
* to encode the entire ServerECDHParams
|
|
* structure.
|
|
*/
|
|
- n = 4 + encodedlen;
|
|
+ n += 4 + encodedlen;
|
|
|
|
/* We'll generate the serverKeyExchange message
|
|
* explicitly so we can set these to NULLs
|
|
@@ -1886,18 +1901,9 @@ int ssl3_send_server_key_exchange(SSL *s)
|
|
r[2]=NULL;
|
|
r[3]=NULL;
|
|
}
|
|
- 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 */
|
|
#ifndef OPENSSL_NO_SRP
|
|
- if (type & SSL_kSRP)
|
|
+ else if (alg_k & SSL_kSRP)
|
|
{
|
|
if ((s->srp_ctx.N == NULL) ||
|
|
(s->srp_ctx.g == NULL) ||
|
|
@@ -1912,8 +1918,8 @@ int ssl3_send_server_key_exchange(SSL *s)
|
|
r[2]=s->srp_ctx.s;
|
|
r[3]=s->srp_ctx.B;
|
|
}
|
|
- else
|
|
#endif
|
|
+ else if (!(alg_k & SSL_kPSK))
|
|
{
|
|
al=SSL_AD_HANDSHAKE_FAILURE;
|
|
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
|
|
@@ -1923,15 +1929,16 @@ int ssl3_send_server_key_exchange(SSL *s)
|
|
{
|
|
nr[i]=BN_num_bytes(r[i]);
|
|
#ifndef OPENSSL_NO_SRP
|
|
- if ((i == 2) && (type & SSL_kSRP))
|
|
+ if ((i == 2) && (alg_k & SSL_kSRP))
|
|
n+=1+nr[i];
|
|
else
|
|
#endif
|
|
n+=2+nr[i];
|
|
}
|
|
|
|
- if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)
|
|
- && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
|
|
+ if (!(alg_a & SSL_aNULL)
|
|
+ /* Among PSK ciphersuites only RSA uses a certificate */
|
|
+ && !((alg_a & SSL_aPSK) && !(alg_k & SSL_kRSA)))
|
|
{
|
|
if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher,&md))
|
|
== NULL)
|
|
@@ -1958,7 +1965,7 @@ int ssl3_send_server_key_exchange(SSL *s)
|
|
for (i=0; i < 4 && r[i] != NULL; i++)
|
|
{
|
|
#ifndef OPENSSL_NO_SRP
|
|
- if ((i == 2) && (type & SSL_kSRP))
|
|
+ if ((i == 2) && (alg_k & SSL_kSRP))
|
|
{
|
|
*p = nr[i];
|
|
p++;
|
|
@@ -1970,8 +1977,32 @@ int ssl3_send_server_key_exchange(SSL *s)
|
|
p+=nr[i];
|
|
}
|
|
|
|
+/* Note: ECDHE PSK ciphersuites use SSL_kEECDH and SSL_aPSK.
|
|
+ * When one of them is used, the server key exchange record needs to have both
|
|
+ * the psk_identity_hint and the ServerECDHParams. */
|
|
+#ifndef OPENSSL_NO_PSK
|
|
+ if (alg_a & SSL_aPSK)
|
|
+ {
|
|
+ if (s->ctx->psk_identity_hint)
|
|
+ {
|
|
+ /* copy PSK identity hint */
|
|
+ s2n(strlen(s->ctx->psk_identity_hint), p);
|
|
+ strncpy((char *)p, s->ctx->psk_identity_hint, strlen(s->ctx->psk_identity_hint));
|
|
+ p+=strlen(s->ctx->psk_identity_hint);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ /* No identity hint is provided. */
|
|
+ *p = 0;
|
|
+ p += 1;
|
|
+ *p = 0;
|
|
+ p += 1;
|
|
+ }
|
|
+ }
|
|
+#endif /* OPENSSL_NO_PSK */
|
|
+
|
|
#ifndef OPENSSL_NO_ECDH
|
|
- if (type & SSL_kEECDH)
|
|
+ if (alg_k & SSL_kEECDH)
|
|
{
|
|
/* XXX: For now, we only support named (not generic) curves.
|
|
* In this situation, the serverKeyExchange message has:
|
|
@@ -1994,17 +2025,7 @@ int ssl3_send_server_key_exchange(SSL *s)
|
|
encodedPoint = NULL;
|
|
p += encodedlen;
|
|
}
|
|
-#endif
|
|
-
|
|
-#ifndef OPENSSL_NO_PSK
|
|
- if (type & SSL_kPSK)
|
|
- {
|
|
- /* copy PSK identity hint */
|
|
- s2n(strlen(s->ctx->psk_identity_hint), p);
|
|
- strncpy((char *)p, s->ctx->psk_identity_hint, strlen(s->ctx->psk_identity_hint));
|
|
- p+=strlen(s->ctx->psk_identity_hint);
|
|
- }
|
|
-#endif
|
|
+#endif /* OPENSSL_NO_ECDH */
|
|
|
|
/* not anonymous */
|
|
if (pkey != NULL)
|
|
@@ -2041,7 +2062,7 @@ int ssl3_send_server_key_exchange(SSL *s)
|
|
n+=u+2;
|
|
}
|
|
else
|
|
-#endif
|
|
+#endif /* OPENSSL_NO_RSA */
|
|
if (md)
|
|
{
|
|
/* For TLS1.2 and later send signature
|
|
@@ -2215,6 +2236,7 @@ int ssl3_get_client_key_exchange(SSL *s)
|
|
int i,al,ok;
|
|
long n;
|
|
unsigned long alg_k;
|
|
+ unsigned long alg_a;
|
|
unsigned char *p;
|
|
#ifndef OPENSSL_NO_RSA
|
|
RSA *rsa=NULL;
|
|
@@ -2232,7 +2254,11 @@ int ssl3_get_client_key_exchange(SSL *s)
|
|
EC_KEY *srvr_ecdh = NULL;
|
|
EVP_PKEY *clnt_pub_pkey = NULL;
|
|
EC_POINT *clnt_ecpoint = NULL;
|
|
- BN_CTX *bn_ctx = NULL;
|
|
+ BN_CTX *bn_ctx = NULL;
|
|
+#ifndef OPENSSL_NO_PSK
|
|
+ unsigned int psk_len = 0;
|
|
+ unsigned char psk[PSK_MAX_PSK_LEN];
|
|
+#endif /* OPENSSL_NO_PSK */
|
|
#endif
|
|
|
|
n=s->method->ssl_get_message(s,
|
|
@@ -2246,7 +2272,106 @@ int ssl3_get_client_key_exchange(SSL *s)
|
|
p=(unsigned char *)s->init_msg;
|
|
|
|
alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
|
|
+ alg_a=s->s3->tmp.new_cipher->algorithm_auth;
|
|
+
|
|
+#ifndef OPENSSL_NO_PSK
|
|
+ if (alg_a & SSL_aPSK)
|
|
+ {
|
|
+ unsigned char *t = NULL;
|
|
+ unsigned char pre_ms[PSK_MAX_PSK_LEN*2+4];
|
|
+ unsigned int pre_ms_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 && !(alg_k & SSL_kEECDH))
|
|
+ {
|
|
+ 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 NUL-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, sizeof(psk));
|
|
|
|
+ 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;
|
|
+ }
|
|
+ if (!(alg_k & SSL_kEECDH))
|
|
+ {
|
|
+ /* Create the shared secret now if we're not using ECDHE-PSK.*/
|
|
+ pre_ms_len=2+psk_len+2+psk_len;
|
|
+ t = pre_ms;
|
|
+ s2n(psk_len, t);
|
|
+ memset(t, 0, psk_len);
|
|
+ t+=psk_len;
|
|
+ s2n(psk_len, t);
|
|
+ memcpy(t, psk, psk_len);
|
|
+
|
|
+ s->session->master_key_length=
|
|
+ s->method->ssl3_enc->generate_master_secret(s,
|
|
+ s->session->master_key, pre_ms, pre_ms_len);
|
|
+ }
|
|
+ if (s->session->psk_identity != NULL)
|
|
+ OPENSSL_free(s->session->psk_identity);
|
|
+ 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 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;
|
|
+ }
|
|
+
|
|
+ p += i;
|
|
+ n -= (i + 2);
|
|
+ psk_err = 0;
|
|
+ psk_err:
|
|
+ OPENSSL_cleanse(pre_ms, sizeof(pre_ms));
|
|
+ if (psk_err != 0)
|
|
+ goto f_err;
|
|
+ }
|
|
+#endif /* OPENSSL_NO_PSK */
|
|
+ if (0) {}
|
|
#ifndef OPENSSL_NO_RSA
|
|
if (alg_k & SSL_kRSA)
|
|
{
|
|
@@ -2410,10 +2535,9 @@ int ssl3_get_client_key_exchange(SSL *s)
|
|
p,sizeof(rand_premaster_secret));
|
|
OPENSSL_cleanse(p,sizeof(rand_premaster_secret));
|
|
}
|
|
- else
|
|
#endif
|
|
#ifndef OPENSSL_NO_DH
|
|
- if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
|
|
+ else if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
|
|
{
|
|
n2s(p,i);
|
|
if (n != i+2)
|
|
@@ -2474,10 +2598,9 @@ int ssl3_get_client_key_exchange(SSL *s)
|
|
s->session->master_key,p,i);
|
|
OPENSSL_cleanse(p,i);
|
|
}
|
|
- else
|
|
#endif
|
|
#ifndef OPENSSL_NO_KRB5
|
|
- if (alg_k & SSL_kKRB5)
|
|
+ else if (alg_k & SSL_kKRB5)
|
|
{
|
|
krb5_error_code krb5rc;
|
|
krb5_data enc_ticket;
|
|
@@ -2666,17 +2789,20 @@ int ssl3_get_client_key_exchange(SSL *s)
|
|
** if (s->kssl_ctx) s->kssl_ctx = NULL;
|
|
*/
|
|
}
|
|
- else
|
|
#endif /* OPENSSL_NO_KRB5 */
|
|
-
|
|
#ifndef OPENSSL_NO_ECDH
|
|
- if (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe))
|
|
+ else if (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe))
|
|
{
|
|
int ret = 1;
|
|
int field_size = 0;
|
|
const EC_KEY *tkey;
|
|
const EC_GROUP *group;
|
|
const BIGNUM *priv_key;
|
|
+#ifndef OPENSSL_NO_PSK
|
|
+ unsigned char *pre_ms;
|
|
+ unsigned int pre_ms_len;
|
|
+ unsigned char *t;
|
|
+#endif /* OPENSSL_NO_PSK */
|
|
|
|
/* initialize structures for server's ECDH key pair */
|
|
if ((srvr_ecdh = EC_KEY_new()) == NULL)
|
|
@@ -2772,7 +2898,7 @@ int ssl3_get_client_key_exchange(SSL *s)
|
|
}
|
|
|
|
/* Get encoded point length */
|
|
- i = *p;
|
|
+ i = *p;
|
|
p += 1;
|
|
if (n != 1 + i)
|
|
{
|
|
@@ -2814,214 +2940,145 @@ int ssl3_get_client_key_exchange(SSL *s)
|
|
EC_KEY_free(srvr_ecdh);
|
|
BN_CTX_free(bn_ctx);
|
|
EC_KEY_free(s->s3->tmp.ecdh);
|
|
- s->s3->tmp.ecdh = NULL;
|
|
+ s->s3->tmp.ecdh = NULL;
|
|
|
|
- /* Compute the master secret */
|
|
- s->session->master_key_length = s->method->ssl3_enc-> \
|
|
- generate_master_secret(s, s->session->master_key, p, i);
|
|
-
|
|
- OPENSSL_cleanse(p, i);
|
|
- return (ret);
|
|
- }
|
|
- else
|
|
-#endif
|
|
#ifndef OPENSSL_NO_PSK
|
|
- if (alg_k & SSL_kPSK)
|
|
+ /* ECDHE PSK ciphersuites from RFC 5489 */
|
|
+ if ((alg_a & SSL_aPSK) && psk_len != 0)
|
|
{
|
|
- 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((char *)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)
|
|
+ pre_ms_len = 2+psk_len+2+i;
|
|
+ pre_ms = OPENSSL_malloc(pre_ms_len);
|
|
+ if (pre_ms == NULL)
|
|
{
|
|
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
|
|
ERR_R_MALLOC_FAILURE);
|
|
- goto psk_err;
|
|
+ goto 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;
|
|
+ memset(pre_ms, 0, pre_ms_len);
|
|
+ t = pre_ms;
|
|
+ s2n(psk_len, t);
|
|
+ memcpy(t, psk, psk_len);
|
|
+ t += psk_len;
|
|
+ s2n(i, t);
|
|
+ memcpy(t, p, i);
|
|
+ s->session->master_key_length = s->method->ssl3_enc \
|
|
+ -> generate_master_secret(s,
|
|
+ s->session->master_key, pre_ms, pre_ms_len);
|
|
+ OPENSSL_cleanse(pre_ms, pre_ms_len);
|
|
+ OPENSSL_free(pre_ms);
|
|
}
|
|
- else
|
|
-#endif
|
|
-#ifndef OPENSSL_NO_SRP
|
|
- if (alg_k & SSL_kSRP)
|
|
+#endif /* OPENSSL_NO_PSK */
|
|
+ if (!(alg_a & SSL_aPSK))
|
|
{
|
|
- int param_len;
|
|
-
|
|
- n2s(p,i);
|
|
- param_len=i+2;
|
|
- if (param_len > n)
|
|
- {
|
|
- al=SSL_AD_DECODE_ERROR;
|
|
- SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_SRP_A_LENGTH);
|
|
- goto f_err;
|
|
- }
|
|
- if (!(s->srp_ctx.A=BN_bin2bn(p,i,NULL)))
|
|
- {
|
|
- SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,ERR_R_BN_LIB);
|
|
- goto err;
|
|
- }
|
|
- if (s->session->srp_username != NULL)
|
|
- OPENSSL_free(s->session->srp_username);
|
|
- s->session->srp_username = BUF_strdup(s->srp_ctx.login);
|
|
- if (s->session->srp_username == NULL)
|
|
- {
|
|
- SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
|
|
- ERR_R_MALLOC_FAILURE);
|
|
- goto err;
|
|
- }
|
|
+ /* Compute the master secret */
|
|
+ s->session->master_key_length = s->method->ssl3_enc \
|
|
+ -> generate_master_secret(s,
|
|
+ s->session->master_key, p, i);
|
|
+ }
|
|
|
|
- if ((s->session->master_key_length = SRP_generate_server_master_secret(s,s->session->master_key))<0)
|
|
- {
|
|
- SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
|
|
- goto err;
|
|
- }
|
|
+ OPENSSL_cleanse(p, i);
|
|
+ }
|
|
+#endif
|
|
+#ifndef OPENSSL_NO_SRP
|
|
+ else if (alg_k & SSL_kSRP)
|
|
+ {
|
|
+ int param_len;
|
|
|
|
- p+=i;
|
|
+ n2s(p,i);
|
|
+ param_len=i+2;
|
|
+ if (param_len > n)
|
|
+ {
|
|
+ al=SSL_AD_DECODE_ERROR;
|
|
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_SRP_A_LENGTH);
|
|
+ goto f_err;
|
|
+ }
|
|
+ if (!(s->srp_ctx.A=BN_bin2bn(p,i,NULL)))
|
|
+ {
|
|
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,ERR_R_BN_LIB);
|
|
+ goto err;
|
|
+ }
|
|
+ if (s->session->srp_username != NULL)
|
|
+ OPENSSL_free(s->session->srp_username);
|
|
+ s->session->srp_username = BUF_strdup(s->srp_ctx.login);
|
|
+ if (s->session->srp_username == NULL)
|
|
+ {
|
|
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
|
|
+ ERR_R_MALLOC_FAILURE);
|
|
+ goto err;
|
|
}
|
|
- else
|
|
-#endif /* OPENSSL_NO_SRP */
|
|
- if (alg_k & SSL_kGOST)
|
|
- {
|
|
- int ret = 0;
|
|
- EVP_PKEY_CTX *pkey_ctx;
|
|
- EVP_PKEY *client_pub_pkey = NULL, *pk = NULL;
|
|
- unsigned char premaster_secret[32], *start;
|
|
- size_t outlen=32, inlen;
|
|
- unsigned long alg_a;
|
|
- int Ttag, Tclass;
|
|
- long Tlen;
|
|
-
|
|
- /* Get our certificate private key*/
|
|
- alg_a = s->s3->tmp.new_cipher->algorithm_auth;
|
|
- if (alg_a & SSL_aGOST94)
|
|
- pk = s->cert->pkeys[SSL_PKEY_GOST94].privatekey;
|
|
- else if (alg_a & SSL_aGOST01)
|
|
- pk = s->cert->pkeys[SSL_PKEY_GOST01].privatekey;
|
|
|
|
- pkey_ctx = EVP_PKEY_CTX_new(pk,NULL);
|
|
- EVP_PKEY_decrypt_init(pkey_ctx);
|
|
- /* If client certificate is present and is of the same type, maybe
|
|
- * use it for key exchange. Don't mind errors from
|
|
- * EVP_PKEY_derive_set_peer, because it is completely valid to use
|
|
- * a client certificate for authorization only. */
|
|
- client_pub_pkey = X509_get_pubkey(s->session->peer);
|
|
- if (client_pub_pkey)
|
|
- {
|
|
- if (EVP_PKEY_derive_set_peer(pkey_ctx, client_pub_pkey) <= 0)
|
|
- ERR_clear_error();
|
|
- }
|
|
- /* Decrypt session key */
|
|
- if (ASN1_get_object((const unsigned char **)&p, &Tlen, &Ttag, &Tclass, n) != V_ASN1_CONSTRUCTED ||
|
|
- Ttag != V_ASN1_SEQUENCE ||
|
|
- Tclass != V_ASN1_UNIVERSAL)
|
|
- {
|
|
- SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED);
|
|
- goto gerr;
|
|
- }
|
|
- start = p;
|
|
- inlen = Tlen;
|
|
- if (EVP_PKEY_decrypt(pkey_ctx,premaster_secret,&outlen,start,inlen) <=0)
|
|
+ if ((s->session->master_key_length = SRP_generate_server_master_secret(s,s->session->master_key))<0)
|
|
+ {
|
|
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
|
|
+ goto err;
|
|
+ }
|
|
|
|
- {
|
|
- SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED);
|
|
- goto gerr;
|
|
- }
|
|
- /* Generate master secret */
|
|
- s->session->master_key_length=
|
|
- s->method->ssl3_enc->generate_master_secret(s,
|
|
- s->session->master_key,premaster_secret,32);
|
|
- /* Check if pubkey from client certificate was used */
|
|
- if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2, NULL) > 0)
|
|
- ret = 2;
|
|
- else
|
|
- ret = 1;
|
|
- gerr:
|
|
- EVP_PKEY_free(client_pub_pkey);
|
|
- EVP_PKEY_CTX_free(pkey_ctx);
|
|
- if (ret)
|
|
- return ret;
|
|
- else
|
|
- goto err;
|
|
+ p+=i;
|
|
+ }
|
|
+#endif /* OPENSSL_NO_SRP */
|
|
+ else if (alg_k & SSL_kGOST)
|
|
+ {
|
|
+ int ret = 0;
|
|
+ EVP_PKEY_CTX *pkey_ctx;
|
|
+ EVP_PKEY *client_pub_pkey = NULL, *pk = NULL;
|
|
+ unsigned char premaster_secret[32], *start;
|
|
+ size_t outlen=32, inlen;
|
|
+ unsigned long alg_a;
|
|
+ int Ttag, Tclass;
|
|
+ long Tlen;
|
|
+
|
|
+ /* Get our certificate private key*/
|
|
+ alg_a = s->s3->tmp.new_cipher->algorithm_auth;
|
|
+ if (alg_a & SSL_aGOST94)
|
|
+ pk = s->cert->pkeys[SSL_PKEY_GOST94].privatekey;
|
|
+ else if (alg_a & SSL_aGOST01)
|
|
+ pk = s->cert->pkeys[SSL_PKEY_GOST01].privatekey;
|
|
+
|
|
+ pkey_ctx = EVP_PKEY_CTX_new(pk,NULL);
|
|
+ EVP_PKEY_decrypt_init(pkey_ctx);
|
|
+ /* If client certificate is present and is of the same type, maybe
|
|
+ * use it for key exchange. Don't mind errors from
|
|
+ * EVP_PKEY_derive_set_peer, because it is completely valid to use
|
|
+ * a client certificate for authorization only. */
|
|
+ client_pub_pkey = X509_get_pubkey(s->session->peer);
|
|
+ if (client_pub_pkey)
|
|
+ {
|
|
+ if (EVP_PKEY_derive_set_peer(pkey_ctx, client_pub_pkey) <= 0)
|
|
+ ERR_clear_error();
|
|
+ }
|
|
+ /* Decrypt session key */
|
|
+ if (ASN1_get_object((const unsigned char **)&p, &Tlen, &Ttag, &Tclass, n) != V_ASN1_CONSTRUCTED ||
|
|
+ Ttag != V_ASN1_SEQUENCE ||
|
|
+ Tclass != V_ASN1_UNIVERSAL)
|
|
+ {
|
|
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED);
|
|
+ goto gerr;
|
|
+ }
|
|
+ start = p;
|
|
+ inlen = Tlen;
|
|
+ if (EVP_PKEY_decrypt(pkey_ctx,premaster_secret,&outlen,start,inlen) <=0)
|
|
+ {
|
|
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED);
|
|
+ goto gerr;
|
|
}
|
|
+ /* Generate master secret */
|
|
+ s->session->master_key_length=
|
|
+ s->method->ssl3_enc->generate_master_secret(s,
|
|
+ s->session->master_key,premaster_secret,32);
|
|
+ /* Check if pubkey from client certificate was used */
|
|
+ if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2, NULL) > 0)
|
|
+ ret = 2;
|
|
+ else
|
|
+ ret = 1;
|
|
+ gerr:
|
|
+ EVP_PKEY_free(client_pub_pkey);
|
|
+ EVP_PKEY_CTX_free(pkey_ctx);
|
|
+ if (ret)
|
|
+ return ret;
|
|
else
|
|
+ goto err;
|
|
+ }
|
|
+ else if (!(alg_k & SSL_kPSK))
|
|
{
|
|
al=SSL_AD_HANDSHAKE_FAILURE;
|
|
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
|
|
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
|
|
index 0fda4ca..6c57d2a 100644
|
|
--- a/ssl/ssl_lib.c
|
|
+++ b/ssl/ssl_lib.c
|
|
@@ -1424,7 +1424,7 @@ int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p,
|
|
#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_auth & SSL_aPSK) &&
|
|
s->psk_client_callback == NULL)
|
|
continue;
|
|
#endif /* OPENSSL_NO_PSK */
|
|
diff --git a/ssl/tls1.h b/ssl/tls1.h
|
|
index 9e035fb..3e6b7c7 100644
|
|
--- a/ssl/tls1.h
|
|
+++ b/ssl/tls1.h
|
|
@@ -536,6 +536,10 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
|
|
#define TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305 0x0300CC14
|
|
#define TLS1_CK_DHE_RSA_CHACHA20_POLY1305 0x0300CC15
|
|
|
|
+/* ECDHE PSK ciphersuites from RFC 5489 */
|
|
+#define TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA256 0x0300C037
|
|
+#define TLS1_CK_ECDHE_PSK_WITH_AES_256_CBC_SHA384 0x0300C038
|
|
+
|
|
/* XXX
|
|
* Inconsistency alert:
|
|
* The OpenSSL names of ciphers with ephemeral DH here include the string
|
|
@@ -691,6 +698,10 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
|
|
#define TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 "ECDHE-ECDSA-CHACHA20-POLY1305"
|
|
#define TLS1_TXT_DHE_RSA_WITH_CHACHA20_POLY1305 "DHE-RSA-CHACHA20-POLY1305"
|
|
|
|
+/* ECDHE PSK ciphersuites from RFC 5489 */
|
|
+#define TLS1_TXT_ECDHE_PSK_WITH_AES_128_CBC_SHA256 "ECDHE-PSK-WITH-AES-128-CBC-SHA256"
|
|
+#define TLS1_TXT_ECDHE_PSK_WITH_AES_256_CBC_SHA384 "ECDHE-PSK-WITH-AES-256-CBC-SHA384"
|
|
+
|
|
#define TLS_CT_RSA_SIGN 1
|
|
#define TLS_CT_DSS_SIGN 2
|
|
#define TLS_CT_RSA_FIXED_DH 3
|
|
2.0.0.526.g5318336
|
|
|