Fix TLS-PSK identity hint implementation issues.
PSK identity hint can be stored in SSL_CTX and in SSL/SSL_SESSION,
similar to other TLS parameters, with the value in SSL/SSL_SESSION
taking precedence over the one in SSL_CTX. The value in SSL_CTX is
shared (used as the default) between all SSL instances associated
with that SSL_CTX, whereas the value in SSL/SSL_SESSION is confined
to that particular TLS/SSL connection/session.
The existing implementation of TLS-PSK does not correctly distinguish
between PSK identity hint in SSL_CTX and in SSL/SSL_SESSION. This
change fixes these issues:
1. SSL_use_psk_identity_hint does nothing and returns "success" when
the SSL object does not have an associated SSL_SESSION.
2. On the client, the hint in SSL_CTX (which is shared between
multiple SSL instances) is overwritten with the hint received from
server or reset to NULL if no hint was received.
3. On the client, psk_client_callback is invoked with the hint from
SSL_CTX rather than from current SSL/SSL_SESSION (i.e., the one
received from the server). Issue #2 above masks this issue.
4. On the server, the hint in SSL/SSL_SESSION is ignored and the hint
from SSL_CTX is sent to the client.
5. On the server, the hint in SSL/SSL_SESSION is reset to the one in
SSL_CTX after the ClientKeyExchange message step.
This change fixes the issues by:
* Adding storage for the hint in the SSL object. The idea being that
the hint in the associated SSL_SESSION takes precedence.
* Reading the hint during the handshake only from the associated
SSL_SESSION object.
* Initializing the hint in SSL object with the one from the SSL_CTX
object.
* Initializing the hint in SSL_SESSION object with the one from the
SSL object.
* Making SSL_use_psk_identity_hint and SSL_get_psk_identity_hint
set/get the hint to/from SSL_SESSION associated with the provided
SSL object, or, if no SSL_SESSION is available, set/get the hint
to/from the provided SSL object.
* Removing code which resets the hint during handshake.
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 64d3094..b0af827 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -1410,9 +1410,11 @@
if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_aPSK)
{
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;
+ if (s->session->psk_identity_hint)
+ {
+ OPENSSL_free(s->session->psk_identity_hint);
+ s->session->psk_identity_hint = NULL;
+ }
}
#endif
s->s3->tmp.reuse_message=1;
@@ -1462,9 +1464,11 @@
al=SSL_AD_HANDSHAKE_FAILURE;
n2s(p,i);
param_len=i+2;
- if (s->ctx->psk_identity_hint)
- OPENSSL_free(s->ctx->psk_identity_hint);
- s->ctx->psk_identity_hint = NULL;
+ if (s->session->psk_identity_hint)
+ {
+ OPENSSL_free(s->session->psk_identity_hint);
+ s->session->psk_identity_hint = NULL;
+ }
if (i != 0)
{
/* Store PSK identity hint for later use, hint is used
@@ -1488,8 +1492,8 @@
* NULL-terminated string. */
memcpy(tmp_id_hint, p, i);
memset(tmp_id_hint+i, 0, PSK_MAX_IDENTITY_LEN+1-i);
- s->ctx->psk_identity_hint = BUF_strdup(tmp_id_hint);
- if (s->ctx->psk_identity_hint == NULL)
+ s->session->psk_identity_hint = BUF_strdup(tmp_id_hint);
+ if (s->session->psk_identity_hint == NULL)
{
OPENSSL_PUT_ERROR(SSL, ssl3_get_key_exchange, ERR_R_MALLOC_FAILURE);
goto f_err;
@@ -2303,7 +2307,7 @@
goto err;
}
- psk_len = s->psk_client_callback(s, s->ctx->psk_identity_hint,
+ psk_len = s->psk_client_callback(s, s->session->psk_identity_hint,
identity, PSK_MAX_IDENTITY_LEN, psk, sizeof(psk));
if (psk_len > PSK_MAX_PSK_LEN)
{
@@ -2337,20 +2341,6 @@
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)
- {
- OPENSSL_PUT_ERROR(SSL, 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);