Fix PSK identity hint handling.
authorDr. Stephen Henson <steve@openssl.org>
Mon, 14 Sep 2015 16:58:04 +0000 (17:58 +0100)
committerDr. Stephen Henson <steve@openssl.org>
Mon, 14 Sep 2015 18:52:27 +0000 (19:52 +0100)
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>
ssl/d1_srvr.c
ssl/s3_srvr.c
ssl/ssl_cert.c
ssl/ssl_lib.c
ssl/ssl_locl.h

index 555bbdfc1105cfd9d884b54ec88054c503b6dd4d..f56bf5adef9d4bbb7d1af5e4f6b33a11898ac6a2 100644 (file)
@@ -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)
index ec09840d5b73a96f57cb10d266b0e34c3d962840..e864ad158076cfaaef10f9d7c57fdad06629748f 100644 (file)
@@ -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);
             }
index 555b1d7d826b6006a7fbc8c3dcce3f89de1f2074..05a444745059980ec67abe3c33ecd7aa3fefdfbc 100644 (file)
@@ -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);
 }
 
index c5d4a8e2503ebe147e320ea7cf41de2e09c82dd9..28b71082ab37b54dd1578b135e9c8d6a2c7bec7c 100644 (file)
@@ -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;
 }
 
index 2539a4e344b12b37253d0e1b069a3e8374ff6d81..083ced392737abeb916b32db7a4d03777f4512b9 100644 (file)
@@ -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;