From df6da24bda457b724ba3e894e6c329a9b93d536f Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Mon, 14 Sep 2015 17:58:04 +0100 Subject: [PATCH] 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 --- ssl/d1_srvr.c | 2 +- ssl/s3_srvr.c | 16 ++++++++-------- ssl/ssl_cert.c | 9 +++++++++ ssl/ssl_lib.c | 22 ++++++++-------------- ssl/ssl_locl.h | 5 ++++- 5 files changed, 30 insertions(+), 24 deletions(-) diff --git a/ssl/d1_srvr.c b/ssl/d1_srvr.c index 555bbdfc11..f56bf5adef 100644 --- a/ssl/d1_srvr.c +++ b/ssl/d1_srvr.c @@ -478,7 +478,7 @@ int dtls1_accept(SSL *s) * provided */ #ifndef OPENSSL_NO_PSK - || ((alg_k & SSL_kPSK) && s->ctx->psk_identity_hint) + || ((alg_k & SSL_kPSK) && s->cert->psk_identity_hint) #endif || (alg_k & SSL_kDHE) || (alg_k & SSL_kECDHE) diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index ec09840d5b..e864ad1580 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -444,7 +444,7 @@ int ssl3_accept(SSL *s) */ #ifndef OPENSSL_NO_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 */ || (alg_k & (SSL_PSK & (SSL_kDHEPSK | SSL_kECDHEPSK))) #endif @@ -1708,8 +1708,8 @@ int ssl3_send_server_key_exchange(SSL *s) * reserve size for record length and PSK identity hint */ n += 2; - if (s->ctx->psk_identity_hint) - n += strlen(s->ctx->psk_identity_hint); + if (s->cert->psk_identity_hint) + n += strlen(s->cert->psk_identity_hint); } /* Plain PSK or RSAPSK nothing to do */ if (type & (SSL_kPSK | SSL_kRSAPSK)) { @@ -1991,11 +1991,11 @@ int ssl3_send_server_key_exchange(SSL *s) #ifndef OPENSSL_NO_PSK if (type & SSL_PSK) { /* copy PSK identity hint */ - if (s->ctx->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); + if (s->cert->psk_identity_hint) { + s2n(strlen(s->cert->psk_identity_hint), p); + strncpy((char *)p, s->cert->psk_identity_hint, + strlen(s->cert->psk_identity_hint)); + p += strlen(s->cert->psk_identity_hint); } else { s2n(0, p); } diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c index 555b1d7d82..05a4447450 100644 --- a/ssl/ssl_cert.c +++ b/ssl/ssl_cert.c @@ -334,6 +334,12 @@ CERT *ssl_cert_dup(CERT *cert) if (!custom_exts_copy(&ret->srv_ext, &cert->srv_ext)) 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); err: @@ -402,6 +408,9 @@ void ssl_cert_free(CERT *c) X509_STORE_free(c->chain_store); custom_exts_free(&c->cli_ext); custom_exts_free(&c->srv_ext); +#ifndef OPENSSL_NO_PSK + OPENSSL_free(c->psk_identity_hint); +#endif OPENSSL_free(c); } diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index c5d4a8e250..28b71082ab 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -1825,9 +1825,6 @@ void SSL_CTX_free(SSL_CTX *a) #ifndef OPENSSL_NO_SRTP sk_SRTP_PROTECTION_PROFILE_free(a->srtp_profiles); #endif -#ifndef OPENSSL_NO_PSK - OPENSSL_free(a->psk_identity_hint); -#endif #ifndef OPENSSL_NO_SRP SSL_CTX_SRP_CTX_free(a); #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); return 0; } - OPENSSL_free(ctx->psk_identity_hint); + OPENSSL_free(ctx->cert->psk_identity_hint); if (identity_hint != NULL) { - ctx->psk_identity_hint = BUF_strdup(identity_hint); - if (ctx->psk_identity_hint == NULL) + ctx->cert->psk_identity_hint = BUF_strdup(identity_hint); + if (ctx->cert->psk_identity_hint == NULL) return 0; } else - ctx->psk_identity_hint = NULL; + ctx->cert->psk_identity_hint = NULL; return 1; } @@ -3022,20 +3019,17 @@ int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint) if (s == NULL) return 0; - if (s->session == NULL) - return 1; /* session not created yet, ignored */ - 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); return 0; } - OPENSSL_free(s->session->psk_identity_hint); + OPENSSL_free(s->cert->psk_identity_hint); if (identity_hint != NULL) { - s->session->psk_identity_hint = BUF_strdup(identity_hint); - if (s->session->psk_identity_hint == NULL) + s->cert->psk_identity_hint = BUF_strdup(identity_hint); + if (s->cert->psk_identity_hint == NULL) return 0; } else - s->session->psk_identity_hint = NULL; + s->cert->psk_identity_hint = NULL; return 1; } diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index 2539a4e344..083ced3927 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -873,7 +873,6 @@ struct ssl_ctx_st { void *tlsext_status_arg; # 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, @@ -1592,6 +1591,10 @@ typedef struct cert_st { /* Security level */ int sec_level; 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 */ } CERT; -- 2.25.1