Fix PSK identity hint handling.

For server use a PSK identity hint value in the CERT structure which
is inherited when SSL_new is called and which allows applications to
set hints on a per-SSL basis. The previous version of
SSL_use_psk_identity_hint tried (wrongly) to use the SSL_SESSION structure.

PR#4039

Reviewed-by: Matt Caswell <matt@openssl.org>
This commit is contained in:
Dr. Stephen Henson 2015-09-14 17:58:04 +01:00
parent aabd492320
commit df6da24bda
5 changed files with 30 additions and 24 deletions

View File

@ -478,7 +478,7 @@ int dtls1_accept(SSL *s)
* provided * provided
*/ */
#ifndef OPENSSL_NO_PSK #ifndef OPENSSL_NO_PSK
|| ((alg_k & SSL_kPSK) && s->ctx->psk_identity_hint) || ((alg_k & SSL_kPSK) && s->cert->psk_identity_hint)
#endif #endif
|| (alg_k & SSL_kDHE) || (alg_k & SSL_kDHE)
|| (alg_k & SSL_kECDHE) || (alg_k & SSL_kECDHE)

View File

@ -444,7 +444,7 @@ int ssl3_accept(SSL *s)
*/ */
#ifndef OPENSSL_NO_PSK #ifndef OPENSSL_NO_PSK
/* Only send SKE if we have identity hint for plain PSK */ /* Only send SKE if we have identity hint for plain PSK */
|| ((alg_k & (SSL_kPSK | SSL_kRSAPSK)) && s->ctx->psk_identity_hint) || ((alg_k & (SSL_kPSK | SSL_kRSAPSK)) && s->cert->psk_identity_hint)
/* For other PSK always send SKE */ /* For other PSK always send SKE */
|| (alg_k & (SSL_PSK & (SSL_kDHEPSK | SSL_kECDHEPSK))) || (alg_k & (SSL_PSK & (SSL_kDHEPSK | SSL_kECDHEPSK)))
#endif #endif
@ -1708,8 +1708,8 @@ int ssl3_send_server_key_exchange(SSL *s)
* reserve size for record length and PSK identity hint * reserve size for record length and PSK identity hint
*/ */
n += 2; n += 2;
if (s->ctx->psk_identity_hint) if (s->cert->psk_identity_hint)
n += strlen(s->ctx->psk_identity_hint); n += strlen(s->cert->psk_identity_hint);
} }
/* Plain PSK or RSAPSK nothing to do */ /* Plain PSK or RSAPSK nothing to do */
if (type & (SSL_kPSK | SSL_kRSAPSK)) { if (type & (SSL_kPSK | SSL_kRSAPSK)) {
@ -1991,11 +1991,11 @@ int ssl3_send_server_key_exchange(SSL *s)
#ifndef OPENSSL_NO_PSK #ifndef OPENSSL_NO_PSK
if (type & SSL_PSK) { if (type & SSL_PSK) {
/* copy PSK identity hint */ /* copy PSK identity hint */
if (s->ctx->psk_identity_hint) { if (s->cert->psk_identity_hint) {
s2n(strlen(s->ctx->psk_identity_hint), p); s2n(strlen(s->cert->psk_identity_hint), p);
strncpy((char *)p, s->ctx->psk_identity_hint, strncpy((char *)p, s->cert->psk_identity_hint,
strlen(s->ctx->psk_identity_hint)); strlen(s->cert->psk_identity_hint));
p += strlen(s->ctx->psk_identity_hint); p += strlen(s->cert->psk_identity_hint);
} else { } else {
s2n(0, p); s2n(0, p);
} }

View File

@ -334,6 +334,12 @@ CERT *ssl_cert_dup(CERT *cert)
if (!custom_exts_copy(&ret->srv_ext, &cert->srv_ext)) if (!custom_exts_copy(&ret->srv_ext, &cert->srv_ext))
goto err; goto err;
if (cert->psk_identity_hint) {
ret->psk_identity_hint = BUF_strdup(cert->psk_identity_hint);
if (ret->psk_identity_hint == NULL)
goto err;
}
return (ret); return (ret);
err: err:
@ -402,6 +408,9 @@ void ssl_cert_free(CERT *c)
X509_STORE_free(c->chain_store); X509_STORE_free(c->chain_store);
custom_exts_free(&c->cli_ext); custom_exts_free(&c->cli_ext);
custom_exts_free(&c->srv_ext); custom_exts_free(&c->srv_ext);
#ifndef OPENSSL_NO_PSK
OPENSSL_free(c->psk_identity_hint);
#endif
OPENSSL_free(c); OPENSSL_free(c);
} }

View File

@ -1825,9 +1825,6 @@ void SSL_CTX_free(SSL_CTX *a)
#ifndef OPENSSL_NO_SRTP #ifndef OPENSSL_NO_SRTP
sk_SRTP_PROTECTION_PROFILE_free(a->srtp_profiles); sk_SRTP_PROTECTION_PROFILE_free(a->srtp_profiles);
#endif #endif
#ifndef OPENSSL_NO_PSK
OPENSSL_free(a->psk_identity_hint);
#endif
#ifndef OPENSSL_NO_SRP #ifndef OPENSSL_NO_SRP
SSL_CTX_SRP_CTX_free(a); SSL_CTX_SRP_CTX_free(a);
#endif #endif
@ -3007,13 +3004,13 @@ int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint)
SSL_R_DATA_LENGTH_TOO_LONG); SSL_R_DATA_LENGTH_TOO_LONG);
return 0; return 0;
} }
OPENSSL_free(ctx->psk_identity_hint); OPENSSL_free(ctx->cert->psk_identity_hint);
if (identity_hint != NULL) { if (identity_hint != NULL) {
ctx->psk_identity_hint = BUF_strdup(identity_hint); ctx->cert->psk_identity_hint = BUF_strdup(identity_hint);
if (ctx->psk_identity_hint == NULL) if (ctx->cert->psk_identity_hint == NULL)
return 0; return 0;
} else } else
ctx->psk_identity_hint = NULL; ctx->cert->psk_identity_hint = NULL;
return 1; return 1;
} }
@ -3022,20 +3019,17 @@ int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint)
if (s == NULL) if (s == NULL)
return 0; return 0;
if (s->session == NULL)
return 1; /* session not created yet, ignored */
if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN) { if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN) {
SSLerr(SSL_F_SSL_USE_PSK_IDENTITY_HINT, SSL_R_DATA_LENGTH_TOO_LONG); SSLerr(SSL_F_SSL_USE_PSK_IDENTITY_HINT, SSL_R_DATA_LENGTH_TOO_LONG);
return 0; return 0;
} }
OPENSSL_free(s->session->psk_identity_hint); OPENSSL_free(s->cert->psk_identity_hint);
if (identity_hint != NULL) { if (identity_hint != NULL) {
s->session->psk_identity_hint = BUF_strdup(identity_hint); s->cert->psk_identity_hint = BUF_strdup(identity_hint);
if (s->session->psk_identity_hint == NULL) if (s->cert->psk_identity_hint == NULL)
return 0; return 0;
} else } else
s->session->psk_identity_hint = NULL; s->cert->psk_identity_hint = NULL;
return 1; return 1;
} }

View File

@ -873,7 +873,6 @@ struct ssl_ctx_st {
void *tlsext_status_arg; void *tlsext_status_arg;
# ifndef OPENSSL_NO_PSK # ifndef OPENSSL_NO_PSK
char *psk_identity_hint;
unsigned int (*psk_client_callback) (SSL *ssl, const char *hint, unsigned int (*psk_client_callback) (SSL *ssl, const char *hint,
char *identity, char *identity,
unsigned int max_identity_len, unsigned int max_identity_len,
@ -1592,6 +1591,10 @@ typedef struct cert_st {
/* Security level */ /* Security level */
int sec_level; int sec_level;
void *sec_ex; void *sec_ex;
#ifndef OPENSSL_NO_PSK
/* If not NULL psk identity hint to use for servers */
char *psk_identity_hint;
#endif
int references; /* >1 only if SSL_copy_session_id is used */ int references; /* >1 only if SSL_copy_session_id is used */
} CERT; } CERT;