From f76105a93b6536468dc41423bf7c1cf00b200a9a Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Thu, 17 Mar 2022 09:31:25 +1000 Subject: [PATCH] TLS 1.3 PSK: multiple ids for a cipher suite When WOLFSSL_PSK_MULTI_ID_PER_CS is defined, multiple identities can be returned for a cipher suite. The first byte of the identity is the count of identites that have been seen so far for the cipher suite. --- src/tls.c | 45 ++++++++++++++++++++++++++++++--------------- src/tls13.c | 7 +++++++ wolfssl/test.h | 8 ++++++++ 3 files changed, 45 insertions(+), 15 deletions(-) diff --git a/src/tls.c b/src/tls.c index 719ccfa3c..5c3267786 100644 --- a/src/tls.c +++ b/src/tls.c @@ -11086,11 +11086,13 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) #ifndef WOLFSSL_PSK_ONE_ID if (ssl->options.client_psk_cs_cb != NULL) { int i; - ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0'; for (i = 0; i < ssl->suites->suiteSz; i += 2) { byte cipherSuite0 = ssl->suites->suites[i + 0]; byte cipherSuite = ssl->suites->suites[i + 1]; unsigned int keySz; + #ifdef WOLFSSL_PSK_MULTI_ID_PER_CS + int cnt = 0; + #endif #ifdef HAVE_NULL_CIPHER if (cipherSuite0 == ECC_BYTE) { @@ -11104,21 +11106,34 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) if (cipherSuite0 != TLS13_BYTE) continue; - keySz = ssl->options.client_psk_cs_cb( - ssl, ssl->arrays->server_hint, - ssl->arrays->client_identity, MAX_PSK_ID_LEN, - ssl->arrays->psk_key, MAX_PSK_KEY_LEN, - GetCipherNameInternal(cipherSuite0, cipherSuite)); - if (keySz > 0) { - ssl->arrays->psk_keySz = keySz; - ret = TLSX_PreSharedKey_Use(ssl, - (byte*)ssl->arrays->client_identity, - (word16)XSTRLEN(ssl->arrays->client_identity), 0, - SuiteMac(ssl->suites->suites + i), - cipherSuite0, cipherSuite, 0, NULL); - if (ret != 0) - return ret; + #ifdef WOLFSSL_PSK_MULTI_ID_PER_CS + do { + ssl->arrays->client_identity[0] = cnt; + #endif + + ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0'; + keySz = ssl->options.client_psk_cs_cb( + ssl, ssl->arrays->server_hint, + ssl->arrays->client_identity, MAX_PSK_ID_LEN, + ssl->arrays->psk_key, MAX_PSK_KEY_LEN, + GetCipherNameInternal(cipherSuite0, cipherSuite)); + if (keySz > 0) { + ssl->arrays->psk_keySz = keySz; + ret = TLSX_PreSharedKey_Use(ssl, + (byte*)ssl->arrays->client_identity, + (word16)XSTRLEN(ssl->arrays->client_identity), + 0, SuiteMac(ssl->suites->suites + i), + cipherSuite0, cipherSuite, 0, NULL); + if (ret != 0) + return ret; + #ifdef WOLFSSL_PSK_MULTI_ID_PER_CS + cnt++; + #endif + } + #ifdef WOLFSSL_PSK_MULTI_ID_PER_CS } + while (keySz > 0); + #endif } usingPSK = 1; diff --git a/src/tls13.c b/src/tls13.c index b92a0c882..cb85b8498 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -73,6 +73,10 @@ * Check for alerts during the handshake in the event of an error. * WOLFSSL_NO_CLIENT_CERT_ERROR * Requires client to set a client certificate + * WOLFSSL_PSK_MULTI_ID_PER_CS + * When multiple PSK identities are available for the same cipher suite. + * Sets the first byte of the client identity to the count of identites + * that have been seen so far for the cipher suite. */ #ifdef HAVE_CONFIG_H @@ -2845,6 +2849,9 @@ static int SetupPskKey(WOLFSSL* ssl, PreSharedKey* psk, int clientHello) else #endif /* OPENSSL_EXTRA */ if (ssl->options.client_psk_cs_cb != NULL) { + #ifdef WOLFSSL_PSK_MULTI_ID_PER_CS + ssl->arrays->client_identity[0] = 0; + #endif /* Lookup key again for next identity. */ ssl->arrays->psk_keySz = ssl->options.client_psk_cs_cb( ssl, ssl->arrays->server_hint, diff --git a/wolfssl/test.h b/wolfssl/test.h index d0abe2dfd..984b6da69 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -2411,6 +2411,14 @@ static WC_INLINE unsigned int my_psk_client_cs_cb(WOLFSSL* ssl, (void)hint; (void)key_max_len; +#ifdef WOLFSSL_PSK_MULTI_ID_PER_CS + /* Multiple calls for each cipher suite. First identity byte indicates the + * number of identites seen so far for cipher suite. */ + if (identity[0] != 0) { + return 0; + } +#endif + /* see internal.h MAX_PSK_ID_LEN for PSK identity limit */ XSTRNCPY(identity, kIdentityStr, id_max_len); XSTRNCAT(identity, ciphersuite + XSTRLEN(ciphersuite) - 6, id_max_len);