]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
lib/psk: Add gnutls_psk_allocate_{client,server}_credentials2
authorHannes Reinecke <hare@suse.de>
Fri, 14 Mar 2025 11:31:13 +0000 (12:31 +0100)
committerDaiki Ueno <ueno@gnu.org>
Thu, 24 Jul 2025 21:49:03 +0000 (06:49 +0900)
Add new functions gnutls_psk_allocate_client_credentials2() and
gnutls_psk_allocate_server_credentials2() which allow to specify
the hash algorithm for the PSK. This fixes a bug in the current
implementation where the binder is always calculated with SHA256.

Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Daiki Ueno <ueno@gnu.org>
NEWS
devel/libgnutls.abignore
devel/symbols.last
doc/Makefile.am
doc/manpages/Makefile.am
lib/ext/pre_shared_key.c
lib/includes/gnutls/gnutls.h.in
lib/libgnutls.map
lib/psk.c

diff --git a/NEWS b/NEWS
index 4469a926014e2123854e7b350c57e980013638a7..545a81d1722e694fd12da2b56da3609d1f9a2082 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,18 @@ Copyright (C) 2000-2016 Free Software Foundation, Inc.
 Copyright (C) 2013-2019 Nikos Mavrogiannopoulos
 See the end for copying conditions.
 
+* Version 3.8.11 (unreleased)
+
+** libgnutls: MAC algorithms for PSK binders is now configurable
+   The previous implementation assumed HMAC-SHA256 to calculate the
+   PSK binders. With the new gnutls_psk_allocate_client_credentials2()
+   and gnutls_psk_allocate_server_credentials2() functions, the
+   application can use other MAC algorithms such as HMAC-SHA384.
+
+** API and ABI modifications:
+gnutls_psk_allocate_client_credentials2: New function
+gnutls_psk_allocate_server_credentials2: New function
+
 * Version 3.8.10 (released 2025-07-08)
 
 ** libgnutls: Fix NULL pointer dereference when 2nd Client Hello omits PSK
index 64df9b2de7b003853cb1174b4e3b5aafcd878d8c..7048f2682a934049cded8ac4ddd29662a4b3ff0f 100644 (file)
@@ -73,4 +73,10 @@ name = drbg_aes_reseed
 
 [suppress_type]
 name = gnutls_cipher_algorithm_t
-changed_enumerators = GNUTLS_CIPHER_AES_128_CFB, GNUTLS_CIPHER_AES_192_CFB, GNUTLS_CIPHER_AES_256_CFB
\ No newline at end of file
+changed_enumerators = GNUTLS_CIPHER_AES_128_CFB, GNUTLS_CIPHER_AES_192_CFB, GNUTLS_CIPHER_AES_256_CFB
+
+[suppress_function]
+name = gnutls_psk_allocate_client_credentials2
+
+[suppress_function]
+name = gnutls_psk_allocate_server_credentials2
index d4c1b1ac190c057c13ce388de507ae03193caee9..5e5ccfc48bebcc88871183a345a091e95f52e219 100644 (file)
@@ -17,6 +17,7 @@ GNUTLS_3_7_3@GNUTLS_3_7_3
 GNUTLS_3_7_4@GNUTLS_3_7_4
 GNUTLS_3_7_5@GNUTLS_3_7_5
 GNUTLS_3_7_7@GNUTLS_3_7_7
+GNUTLS_3_8_11@GNUTLS_3_8_11
 GNUTLS_3_8_1@GNUTLS_3_8_1
 GNUTLS_3_8_2@GNUTLS_3_8_2
 GNUTLS_3_8_4@GNUTLS_3_8_4
@@ -686,7 +687,9 @@ gnutls_protocol_get_name@GNUTLS_3_4
 gnutls_protocol_get_version@GNUTLS_3_4
 gnutls_protocol_list@GNUTLS_3_4
 gnutls_protocol_set_enabled@GNUTLS_3_7_3
+gnutls_psk_allocate_client_credentials2@GNUTLS_3_8_11
 gnutls_psk_allocate_client_credentials@GNUTLS_3_4
+gnutls_psk_allocate_server_credentials2@GNUTLS_3_8_11
 gnutls_psk_allocate_server_credentials@GNUTLS_3_4
 gnutls_psk_client_get_hint@GNUTLS_3_4
 gnutls_psk_format_imported_identity@GNUTLS_3_8_1
index 7f70b65815aec2b378885f2dfbbe470a820c02f9..b1cd4f10470210ef0ee5861e0ac6cf162e1833a7 100644 (file)
@@ -1779,8 +1779,12 @@ FUNCS += functions/gnutls_protocol_set_enabled
 FUNCS += functions/gnutls_protocol_set_enabled.short
 FUNCS += functions/gnutls_psk_allocate_client_credentials
 FUNCS += functions/gnutls_psk_allocate_client_credentials.short
+FUNCS += functions/gnutls_psk_allocate_client_credentials2
+FUNCS += functions/gnutls_psk_allocate_client_credentials2.short
 FUNCS += functions/gnutls_psk_allocate_server_credentials
 FUNCS += functions/gnutls_psk_allocate_server_credentials.short
+FUNCS += functions/gnutls_psk_allocate_server_credentials2
+FUNCS += functions/gnutls_psk_allocate_server_credentials2.short
 FUNCS += functions/gnutls_psk_client_get_hint
 FUNCS += functions/gnutls_psk_client_get_hint.short
 FUNCS += functions/gnutls_psk_format_imported_identity
index b2867bc2a67306435af9b286f06dddc14dd7d2bd..598724a90b545831d9d6d879ae37fe8e40d6f6d0 100644 (file)
@@ -735,7 +735,9 @@ APIMANS += gnutls_protocol_get_version.3
 APIMANS += gnutls_protocol_list.3
 APIMANS += gnutls_protocol_set_enabled.3
 APIMANS += gnutls_psk_allocate_client_credentials.3
+APIMANS += gnutls_psk_allocate_client_credentials2.3
 APIMANS += gnutls_psk_allocate_server_credentials.3
+APIMANS += gnutls_psk_allocate_server_credentials2.3
 APIMANS += gnutls_psk_client_get_hint.3
 APIMANS += gnutls_psk_format_imported_identity.3
 APIMANS += gnutls_psk_free_client_credentials.3
index 2cb83e6707746fff36f5bcf8dd7152d8f0fa1893..d709efa74bc6ac0d5454ffd6ec2f4ba92bbec379 100644 (file)
@@ -827,7 +827,9 @@ static int server_recv_params(gnutls_session_t session,
        struct timespec ticket_creation_time = { 0, 0 };
        enum binder_type binder_type;
        bool refuse_early_data = false;
+       gnutls_mac_algorithm_t mac = GNUTLS_MAC_SHA384;
 
+retry_binder:
        ret = _gnutls13_psk_ext_parser_init(&psk_parser, data, len);
        if (ret < 0) {
                /* No PSKs advertised by client */
@@ -885,6 +887,8 @@ static int server_recv_params(gnutls_session_t session,
                        uint8_t ipsk[MAX_HASH_SIZE];
 
                        prf = pskcred->binder_algo;
+                       if (prf->id == GNUTLS_MAC_UNKNOWN)
+                               prf = _gnutls_mac_to_entry(mac);
 
                        /* this fails only on configuration errors; as such we always
                         * return its error code in that case */
@@ -974,6 +978,15 @@ static int server_recv_params(gnutls_session_t session,
 
        if (_gnutls_mac_get_algo_len(prf) != binder_recvd.size ||
            gnutls_memcmp(binder_value, binder_recvd.data, binder_recvd.size)) {
+               /*
+                * Older clients will always use SHA256 as binder algorithm
+                * even for SHA384 PSKs, so we need to retry with SHA256
+                * to calculate the correct binder value for those.
+                */
+               if (prf->id == GNUTLS_MAC_UNKNOWN && mac == GNUTLS_MAC_SHA384) {
+                       mac = GNUTLS_MAC_SHA256;
+                       goto retry_binder;
+               }
                gnutls_assert();
                ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
                goto fail;
index 076fe2ebd087a380fe2b3c9883ee5c362d0698a7..cd7dceaaa428f19d3913e2064812f7b2d4e08b3a 100644 (file)
@@ -2595,6 +2595,9 @@ typedef enum gnutls_psk_key_flags {
 
 void gnutls_psk_free_client_credentials(gnutls_psk_client_credentials_t sc);
 int gnutls_psk_allocate_client_credentials(gnutls_psk_client_credentials_t *sc);
+int gnutls_psk_allocate_client_credentials2(gnutls_psk_client_credentials_t *sc,
+                                           gnutls_mac_algorithm_t mac);
+
 int gnutls_psk_set_client_credentials(gnutls_psk_client_credentials_t res,
                                      const char *username,
                                      const gnutls_datum_t *key,
@@ -2606,6 +2609,8 @@ int gnutls_psk_set_client_credentials2(gnutls_psk_client_credentials_t res,
 
 void gnutls_psk_free_server_credentials(gnutls_psk_server_credentials_t sc);
 int gnutls_psk_allocate_server_credentials(gnutls_psk_server_credentials_t *sc);
+int gnutls_psk_allocate_server_credentials2(gnutls_psk_server_credentials_t *sc,
+                                           gnutls_mac_algorithm_t mac);
 int gnutls_psk_set_server_credentials_file(gnutls_psk_server_credentials_t res,
                                           const char *password_file);
 
index c2366833d025f8568a3ad25be0f1c86fec126c9a..c74c8569ddc20b71c9a941970b9ed3bdc7b15e10 100644 (file)
@@ -1450,6 +1450,15 @@ GNUTLS_3_8_6
        *;
 } GNUTLS_3_8_4;
 
+GNUTLS_3_8_11
+{
+ global:
+       gnutls_psk_allocate_client_credentials2;
+       gnutls_psk_allocate_server_credentials2;
+ local:
+       *;
+} GNUTLS_3_8_6;
+
 GNUTLS_FIPS140_3_4 {
   global:
        gnutls_cipher_self_test;
index c548c6b001490b08c575c0e5e2c4661a54059f7a..06cf5b03d1edea69a195de3d1ee52b9f24fea5fd 100644 (file)
--- a/lib/psk.c
+++ b/lib/psk.c
@@ -61,13 +61,34 @@ void gnutls_psk_free_client_credentials(gnutls_psk_client_credentials_t sc)
  **/
 int gnutls_psk_allocate_client_credentials(gnutls_psk_client_credentials_t *sc)
 {
+       /* TLS 1.3 - Default binder HMAC algorithm is SHA-256 */
+       return gnutls_psk_allocate_client_credentials2(sc, GNUTLS_MAC_SHA256);
+}
+
+/**
+ * gnutls_psk_allocate_client_credentials2:
+ * @sc: is a pointer to a #gnutls_psk_client_credentials_t type.
+ * @mac: encryption algorithm to use
+ *
+ * Allocate a gnutls_psk_client_credentials_t structure and initializes
+ * the HMAC binder algorithm to @mac.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
+ *   an error code is returned.
+ **/
+int gnutls_psk_allocate_client_credentials2(gnutls_psk_client_credentials_t *sc,
+                                           gnutls_mac_algorithm_t mac)
+{
+       /* TLS 1.3 - Only SHA-256 and SHA-384 are allowed */
+       if (mac != GNUTLS_MAC_SHA256 && mac != GNUTLS_MAC_SHA384)
+               return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
        *sc = gnutls_calloc(1, sizeof(psk_client_credentials_st));
 
        if (*sc == NULL)
                return GNUTLS_E_MEMORY_ERROR;
 
-       /* TLS 1.3 - Default binder HMAC algorithm is SHA-256 */
-       (*sc)->binder_algo = _gnutls_mac_to_entry(GNUTLS_MAC_SHA256);
+       (*sc)->binder_algo = _gnutls_mac_to_entry(mac);
        return 0;
 }
 
@@ -203,13 +224,40 @@ void gnutls_psk_free_server_credentials(gnutls_psk_server_credentials_t sc)
  **/
 int gnutls_psk_allocate_server_credentials(gnutls_psk_server_credentials_t *sc)
 {
+       /* TLS 1.3 - Default binder HMAC algorithm is SHA-256 */
+       return gnutls_psk_allocate_server_credentials2(sc, GNUTLS_MAC_SHA256);
+}
+
+/**
+ * gnutls_psk_allocate_server_credentials2:
+ * @sc: is a pointer to a #gnutls_psk_server_credentials_t type.
+ * @mac: encryption algorithm to use
+ *
+ * Allocate a gnutls_psk_server_credentials_t structure and initializes
+ * the HMAC binder algorithm to @mac. If @mac is set to GNUTLS_MAC_UNKNOWN
+ * both possible algorithms SHA384 and SHA256 are applied to find a matching
+ * binder value.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
+ *   an error code is returned.
+ **/
+int gnutls_psk_allocate_server_credentials2(gnutls_psk_server_credentials_t *sc,
+                                           gnutls_mac_algorithm_t mac)
+{
+       /*
+        * TLS 1.3 - Only SHA-256 and SHA-384 are allowed;
+        * additionally allow GNUTLS_MAC_UNKNOWN for autodetection.
+        */
+       if (mac != GNUTLS_MAC_SHA256 && mac != GNUTLS_MAC_SHA384 &&
+           mac != GNUTLS_MAC_UNKNOWN)
+               return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
        *sc = gnutls_calloc(1, sizeof(psk_server_cred_st));
 
        if (*sc == NULL)
                return GNUTLS_E_MEMORY_ERROR;
 
-       /* TLS 1.3 - Default binder HMAC algorithm is SHA-256 */
-       (*sc)->binder_algo = _gnutls_mac_to_entry(GNUTLS_MAC_SHA256);
+       (*sc)->binder_algo = _gnutls_mac_to_entry(mac);
        return 0;
 }