Commit df6da24b authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

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: default avatarMatt Caswell <matt@openssl.org>
parent aabd4923
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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)
+8 −8
Original line number Diff line number Diff line
@@ -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);
            }
+9 −0
Original line number Diff line number Diff line
@@ -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);
}

+8 −14
Original line number Diff line number Diff line
@@ -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;
}

+4 −1
Original line number Diff line number Diff line
@@ -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;