diff --git a/examples/client/client.c b/examples/client/client.c index be6367d84..c75d2ca46 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -1637,6 +1637,9 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if (usePsk) { #ifndef NO_PSK wolfSSL_CTX_set_psk_client_callback(ctx, my_psk_client_cb); + #ifdef WOLFSSL_TLS13 + wolfSSL_CTX_set_psk_client_tls13_callback(ctx, my_psk_client_tls13_cb); + #endif if (cipherList == NULL) { const char *defaultCipherList; #if defined(HAVE_AESGCM) && !defined(NO_DH) diff --git a/examples/server/server.c b/examples/server/server.c index 0b8064ede..1c8c1fcc2 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -1135,6 +1135,9 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) if (usePsk || usePskPlus) { #ifndef NO_PSK SSL_CTX_set_psk_server_callback(ctx, my_psk_server_cb); + #ifdef WOLFSSL_TLS13 + wolfSSL_CTX_set_psk_server_tls13_callback(ctx, my_psk_server_tls13_cb); + #endif if (sendPskIdentityHint == 1) SSL_CTX_use_psk_identity_hint(ctx, "cyassl server"); diff --git a/src/internal.c b/src/internal.c index 97f7bebc5..a324a89bd 100644 --- a/src/internal.c +++ b/src/internal.c @@ -4219,6 +4219,10 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) ssl->options.havePSK = ctx->havePSK; ssl->options.client_psk_cb = ctx->client_psk_cb; ssl->options.server_psk_cb = ctx->server_psk_cb; +#ifdef WOLFSSL_TLS13 + ssl->options.client_psk_tls13_cb = ctx->client_psk_tls13_cb; + ssl->options.server_psk_tls13_cb = ctx->server_psk_tls13_cb; +#endif #endif /* NO_PSK */ #ifdef WOLFSSL_EARLY_DATA if (ssl->options.side == WOLFSSL_SERVER_END) @@ -15989,6 +15993,24 @@ const char* wolfSSL_get_cipher_name_iana(WOLFSSL* ssl) return GetCipherNameIana(ssl->options.cipherSuite0, ssl->options.cipherSuite); } +int GetCipherSuiteFromName(const char* name, byte* cipherSuite0, + byte* cipherSuite) +{ + int ret = BAD_FUNC_ARG; + int i; + unsigned long len = (unsigned long)XSTRLEN(name); + + for (i = 0; i < GetCipherNamesSize(); i++) { + if (XSTRNCMP(name, cipher_names[i].name, len) == 0) { + *cipherSuite0 = cipher_names[i].cipherSuite0; + *cipherSuite = cipher_names[i].cipherSuite; + ret = 0; + break; + } + } + + return ret; +} /** Set the enabled cipher suites. @@ -16075,8 +16097,12 @@ int SetCipherList(WOLFSSL_CTX* ctx, Suites* suites, const char* list) * suites don't necessarily have RSA in the name. */ #ifdef WOLFSSL_TLS13 if (XSTRSTR(name, "TLS13")) { + #ifndef NO_RSA haveRSAsig = 1; + #endif + #if defined(HAVE_ECC) || defined(HAVE_ED25519) haveECDSAsig = 1; + #endif } else #endif diff --git a/src/tls13.c b/src/tls13.c index 179a932a9..fa7f1ad5f 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -2359,18 +2359,32 @@ static int SetupPskKey(WOLFSSL* ssl, PreSharedKey* psk) #endif #ifndef NO_PSK if (!psk->resumption) { + const char* cipherName = NULL; + byte cipherSuite0 = TLS13_BYTE, cipherSuite = WOLFSSL_DEF_PSK_CIPHER; + /* Get the pre-shared key. */ - ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl, - (char *)psk->identity, ssl->arrays->client_identity, - MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN); + if (ssl->options.client_psk_tls13_cb != NULL) { + ssl->arrays->psk_keySz = ssl->options.client_psk_tls13_cb(ssl, + (char *)psk->identity, ssl->arrays->client_identity, + MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN, + &cipherName); + if (GetCipherSuiteFromName(cipherName, &cipherSuite0, + &cipherSuite) != 0) { + return PSK_KEY_ERROR; + } + } + else { + ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl, + (char *)psk->identity, ssl->arrays->client_identity, + MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN); + } if (ssl->arrays->psk_keySz == 0 || - ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { + ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { return PSK_KEY_ERROR; } - /* TODO: Callback should be able to specify ciphersuite. */ - if (psk->cipherSuite0 != TLS13_BYTE || - psk->cipherSuite != WOLFSSL_DEF_PSK_CIPHER) { + if (psk->cipherSuite0 != cipherSuite0 || + psk->cipherSuite != cipherSuite) { return PSK_KEY_ERROR; } } @@ -2534,7 +2548,9 @@ int SendTls13ClientHello(WOLFSSL* ssl) return ret; #ifdef WOLFSSL_EARLY_DATA #ifndef NO_PSK - if (!ssl->options.resuming && ssl->options.client_psk_cb == NULL) + if (!ssl->options.resuming && + ssl->options.client_psk_tls13_cb == NULL && + ssl->options.client_psk_cb == NULL) #else if (!ssl->options.resuming) #endif @@ -3263,6 +3279,11 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, int pskCnt = 0; TLSX* extEarlyData; #endif +#ifndef NO_PSK + const char* cipherName = NULL; + byte cipherSuite0 = TLS13_BYTE; + byte cipherSuite = WOLFSSL_DEF_PSK_CIPHER; +#endif WOLFSSL_ENTER("DoPreSharedKeys"); @@ -3371,16 +3392,22 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, else #endif #ifndef NO_PSK - if (ssl->options.server_psk_cb != NULL && - (ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl, + if ((ssl->options.server_psk_tls13_cb != NULL && + (ssl->arrays->psk_keySz = ssl->options.server_psk_tls13_cb(ssl, ssl->arrays->client_identity, ssl->arrays->psk_key, - MAX_PSK_KEY_LEN)) != 0) { + MAX_PSK_KEY_LEN, &cipherName)) != 0 && + GetCipherSuiteFromName(cipherName, &cipherSuite0, + &cipherSuite) == 0) || + (ssl->options.server_psk_cb != NULL && + (ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl, + ssl->arrays->client_identity, ssl->arrays->psk_key, + MAX_PSK_KEY_LEN)) != 0)) { if (ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) return PSK_KEY_ERROR; - /* TODO: Callback should be able to specify ciphersuite. */ - suite[0] = TLS13_BYTE; - suite[1] = WOLFSSL_DEF_PSK_CIPHER; + /* Check whether PSK ciphersuite is in SSL. */ + suite[0] = cipherSuite0; + suite[1] = cipherSuite; if (!FindSuite(ssl, suite)) { current = current->next; continue; @@ -3393,9 +3420,9 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, if (current->ticketAge != ssl->session.ticketAdd) return PSK_KEY_ERROR; - /* Check whether PSK ciphersuite is in SSL. */ - ssl->options.cipherSuite0 = TLS13_BYTE; - ssl->options.cipherSuite = WOLFSSL_DEF_PSK_CIPHER; + /* Set PSK ciphersuite into SSL. */ + ssl->options.cipherSuite0 = cipherSuite0; + ssl->options.cipherSuite = cipherSuite; ret = SetCipherSpecs(ssl); if (ret != 0) return ret; @@ -7936,6 +7963,85 @@ int wolfSSL_set_groups(WOLFSSL* ssl, int* groups, int count) return WOLFSSL_SUCCESS; } +#ifndef NO_PSK +void wolfSSL_CTX_set_psk_client_tls13_callback(WOLFSSL_CTX* ctx, + wc_psk_client_tls13_callback cb) +{ + WOLFSSL_ENTER("SSL_CTX_set_psk_client_tls13_callback"); + + if (ctx == NULL) + return; + + ctx->havePSK = 1; + ctx->client_psk_tls13_cb = cb; +} + + +void wolfSSL_set_psk_client_tls13_callback(WOLFSSL* ssl, + wc_psk_client_tls13_callback cb) +{ + byte haveRSA = 1; + int keySz = 0; + + WOLFSSL_ENTER("SSL_set_psk_client_tls13_callback"); + + if (ssl == NULL) + return; + + ssl->options.havePSK = 1; + ssl->options.client_psk_tls13_cb = cb; + + #ifdef NO_RSA + haveRSA = 0; + #endif + #ifndef NO_CERTS + keySz = ssl->buffers.keySz; + #endif + InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE, + ssl->options.haveDH, ssl->options.haveNTRU, + ssl->options.haveECDSAsig, ssl->options.haveECC, + ssl->options.haveStaticECC, ssl->options.side); +} + + +void wolfSSL_CTX_set_psk_server_tls13_callback(WOLFSSL_CTX* ctx, + wc_psk_server_tls13_callback cb) +{ + WOLFSSL_ENTER("SSL_CTX_set_psk_server_tls13_callback"); + if (ctx == NULL) + return; + ctx->havePSK = 1; + ctx->server_psk_tls13_cb = cb; +} + + +void wolfSSL_set_psk_server_tls13_callback(WOLFSSL* ssl, + wc_psk_server_tls13_callback cb) +{ + byte haveRSA = 1; + int keySz = 0; + + WOLFSSL_ENTER("SSL_set_psk_server_tls13_callback"); + if (ssl == NULL) + return; + + ssl->options.havePSK = 1; + ssl->options.server_psk_tls13_cb = cb; + + #ifdef NO_RSA + haveRSA = 0; + #endif + #ifndef NO_CERTS + keySz = ssl->buffers.keySz; + #endif + InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE, + ssl->options.haveDH, ssl->options.haveNTRU, + ssl->options.haveECDSAsig, ssl->options.haveECC, + ssl->options.haveStaticECC, ssl->options.side); +} +#endif + + #ifndef NO_WOLFSSL_SERVER /* The server accepting a connection from a client. * The protocol version is expecting to be TLS v1.3. diff --git a/tests/api.c b/tests/api.c index 734636784..3d7e56bfd 100644 --- a/tests/api.c +++ b/tests/api.c @@ -751,7 +751,11 @@ static int test_wolfSSL_CTX_use_certificate_chain_file_format(void) const char* server_chain_der = "./certs/server-cert-chain.der"; WOLFSSL_CTX* ctx; +#ifndef NO_WOLFSSL_CLIENT ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method()); +#else + ctx = wolfSSL_CTX_new(wolfTLSv1_2_server_method()); +#endif AssertNotNull(ctx); AssertIntEQ(wolfSSL_CTX_use_certificate_chain_file_format(ctx, @@ -981,7 +985,7 @@ static void test_wolfSSL_SetTmpDH_buffer(void) static void test_wolfSSL_SetMinMaxDhKey_Sz(void) { -#if !defined(NO_CERTS) && !defined(NO_DH) && !defined(NO_WOLFSSL_CLIENT) +#if !defined(NO_CERTS) && !defined(NO_DH) && !defined(NO_WOLFSSL_SERVER) WOLFSSL_CTX *ctx, *ctx2; WOLFSSL *ssl, *ssl2; diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 8e83773d4..63998c68d 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1730,6 +1730,13 @@ WOLFSSL_LOCAL int SetCipherList(WOLFSSL_CTX*, Suites*, const char* list); unsigned int, unsigned char*, unsigned int); typedef unsigned int (*wc_psk_server_callback)(WOLFSSL*, const char*, unsigned char*, unsigned int); +#ifdef WOLFSSL_TLS13 + typedef unsigned int (*wc_psk_client_tls13_callback)(WOLFSSL*, const char*, + char*, unsigned int, unsigned char*, unsigned int, + const char**); + typedef unsigned int (*wc_psk_server_tls13_callback)(WOLFSSL*, const char*, + unsigned char*, unsigned int, const char**); +#endif #endif /* PSK_TYPES_DEFINED */ #if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SESSION_EXPORT) && \ !defined(WOLFSSL_DTLS_EXPORT_TYPES) @@ -2557,6 +2564,10 @@ struct WOLFSSL_CTX { byte havePSK; /* psk key set by user */ wc_psk_client_callback client_psk_cb; /* client callback */ wc_psk_server_callback server_psk_cb; /* server callback */ +#ifdef WOLFSSL_TLS13 + wc_psk_client_tls13_callback client_psk_tls13_cb; /* client callback */ + wc_psk_server_tls13_callback server_psk_tls13_cb; /* server callback */ +#endif char server_hint[MAX_PSK_ID_LEN + NULL_TERM_LEN]; #endif /* HAVE_SESSION_TICKET || !NO_PSK */ #ifdef WOLFSSL_TLS13 @@ -3108,6 +3119,10 @@ typedef struct Options { #ifndef NO_PSK wc_psk_client_callback client_psk_cb; wc_psk_server_callback server_psk_cb; +#ifdef WOLFSSL_TLS13 + wc_psk_client_tls13_callback client_psk_tls13_cb; /* client callback */ + wc_psk_server_tls13_callback server_psk_tls13_cb; /* server callback */ +#endif #endif /* NO_PSK */ #ifdef OPENSSL_EXTRA unsigned long mask; /* store SSL_OP_ flags */ @@ -4151,6 +4166,8 @@ WOLFSSL_LOCAL const char* GetCipherNameInternal(const byte cipherSuite0, const b WOLFSSL_LOCAL const char* GetCipherNameIana(const byte cipherSuite0, const byte cipherSuite); WOLFSSL_LOCAL const char* wolfSSL_get_cipher_name_internal(WOLFSSL* ssl); WOLFSSL_LOCAL const char* wolfSSL_get_cipher_name_iana(WOLFSSL* ssl); +WOLFSSL_LOCAL int GetCipherSuiteFromName(const char* name, byte* cipherSuite0, + byte* cipherSuite); enum encrypt_side { ENCRYPT_SIDE_ONLY = 1, diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 21e77df97..bbe6ae910 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -1369,6 +1369,14 @@ enum { /* ssl Constants */ wc_psk_client_callback); WOLFSSL_API void wolfSSL_set_psk_client_callback(WOLFSSL*, wc_psk_client_callback); +#ifdef WOLFSSL_TLS13 + typedef unsigned int (*wc_psk_client_tls13_callback)(WOLFSSL*, const char*, + char*, unsigned int, unsigned char*, unsigned int, const char**); + WOLFSSL_API void wolfSSL_CTX_set_psk_client_tls13_callback(WOLFSSL_CTX*, + wc_psk_client_tls13_callback); + WOLFSSL_API void wolfSSL_set_psk_client_tls13_callback(WOLFSSL*, + wc_psk_client_tls13_callback); +#endif WOLFSSL_API const char* wolfSSL_get_psk_identity_hint(const WOLFSSL*); WOLFSSL_API const char* wolfSSL_get_psk_identity(const WOLFSSL*); @@ -1382,6 +1390,14 @@ enum { /* ssl Constants */ wc_psk_server_callback); WOLFSSL_API void wolfSSL_set_psk_server_callback(WOLFSSL*, wc_psk_server_callback); +#ifdef WOLFSSL_TLS13 + typedef unsigned int (*wc_psk_server_tls13_callback)(WOLFSSL*, const char*, + unsigned char*, unsigned int, const char**); + WOLFSSL_API void wolfSSL_CTX_set_psk_server_tls13_callback(WOLFSSL_CTX*, + wc_psk_server_tls13_callback); + WOLFSSL_API void wolfSSL_set_psk_server_tls13_callback(WOLFSSL*, + wc_psk_server_tls13_callback); +#endif #define PSK_TYPES_DEFINED #endif /* NO_PSK */ diff --git a/wolfssl/test.h b/wolfssl/test.h index 5c26e1446..eb307c6aa 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -1184,6 +1184,58 @@ static WC_INLINE unsigned int my_psk_server_cb(WOLFSSL* ssl, const char* identit } } + +static WC_INLINE unsigned int my_psk_client_tls13_cb(WOLFSSL* ssl, + const char* hint, char* identity, unsigned int id_max_len, + unsigned char* key, unsigned int key_max_len, const char** ciphersuite) +{ + int i; + int b = 0x01; + + (void)ssl; + (void)hint; + (void)key_max_len; + + /* see internal.h MAX_PSK_ID_LEN for PSK identity limit */ + strncpy(identity, kIdentityStr, id_max_len); + + for (i = 0; i < 32; i++, b += 0x22) { + if (b >= 0x100) + b = 0x01; + key[i] = b; + } + + *ciphersuite = "TLS13-AES128-GCM-SHA256"; + + return 32; /* length of key in octets or 0 for error */ +} + + +static WC_INLINE unsigned int my_psk_server_tls13_cb(WOLFSSL* ssl, + const char* identity, unsigned char* key, unsigned int key_max_len, + const char** ciphersuite) +{ + int i; + int b = 0x01; + + (void)ssl; + (void)key_max_len; + + /* see internal.h MAX_PSK_ID_LEN for PSK identity limit */ + if (strncmp(identity, kIdentityStr, strlen(kIdentityStr)) != 0) + return 0; + + for (i = 0; i < 32; i++, b += 0x22) { + if (b >= 0x100) + b = 0x01; + key[i] = b; + } + + *ciphersuite = "TLS13-AES128-GCM-SHA256"; + + return 32; /* length of key in octets or 0 for error */ +} + #endif /* NO_PSK */