Skip to content

Commit 2de0c77

Browse files
committed
RFC 9258 importer: remove pre-extracted EPSK option
Drop wolfSSL_external_psk_pre_extracted() and the associated psk_externalKeyPreExtracted state and derivation branch. It was a non-standard convenience not required by RFC 9258 (the import always performs epskx = HKDF-Extract(0, epsk)) and is not wanted for upstreaming. * Remove the public API and its prototype/documentation. * Remove the Arrays.psk_externalKeyPreExtracted bitfield. * DeriveImportedPsk()/DeriveImportedPreSharedKey() always HKDF-Extract. * Drop the pre-extracted handshake test case. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XRMrPoMWjro4shL6W2JHXw
1 parent f992fcb commit 2de0c77

5 files changed

Lines changed: 30 additions & 112 deletions

File tree

doc/dox_comments/header_files/ssl.h

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -15251,7 +15251,6 @@ void wolfSSL_set_psk_server_tls13_callback(WOLFSSL* ssl,
1525115251

1525215252
\sa wolfSSL_set_psk_client_importer_callback
1525315253
\sa wolfSSL_CTX_set_psk_server_importer_callback
15254-
\sa wolfSSL_external_psk_pre_extracted
1525515254
*/
1525615255
void wolfSSL_CTX_set_psk_client_importer_callback(WOLFSSL_CTX* ctx,
1525715256
wc_psk_client_importer_callback cb);
@@ -15276,7 +15275,6 @@ void wolfSSL_CTX_set_psk_client_importer_callback(WOLFSSL_CTX* ctx,
1527615275

1527715276
\sa wolfSSL_CTX_set_psk_client_importer_callback
1527815277
\sa wolfSSL_set_psk_server_importer_callback
15279-
\sa wolfSSL_external_psk_pre_extracted
1528015278
*/
1528115279
void wolfSSL_set_psk_client_importer_callback(WOLFSSL* ssl,
1528215280
wc_psk_client_importer_callback cb);
@@ -15307,7 +15305,6 @@ void wolfSSL_set_psk_client_importer_callback(WOLFSSL* ssl,
1530715305

1530815306
\sa wolfSSL_set_psk_server_importer_callback
1530915307
\sa wolfSSL_CTX_set_psk_client_importer_callback
15310-
\sa wolfSSL_external_psk_pre_extracted
1531115308
*/
1531215309
void wolfSSL_CTX_set_psk_server_importer_callback(WOLFSSL_CTX* ctx,
1531315310
wc_psk_server_importer_callback cb);
@@ -15332,38 +15329,10 @@ void wolfSSL_CTX_set_psk_server_importer_callback(WOLFSSL_CTX* ctx,
1533215329

1533315330
\sa wolfSSL_CTX_set_psk_server_importer_callback
1533415331
\sa wolfSSL_set_psk_client_importer_callback
15335-
\sa wolfSSL_external_psk_pre_extracted
1533615332
*/
1533715333
void wolfSSL_set_psk_server_importer_callback(WOLFSSL* ssl,
1533815334
wc_psk_server_importer_callback cb);
1533915335

15340-
/*!
15341-
\ingroup Setup
15342-
15343-
\brief This function marks whether the external PSK supplied by the importer
15344-
callback is already a pre-extracted pseudorandom key. When enabled, the
15345-
imported-PSK derivation skips the HKDF-Extract step (RFC 9258, Section 3.1).
15346-
Both peers must agree on this setting. Requires WOLFSSL_EXTERNAL_PSK_IMPORTER.
15347-
15348-
\return 0 on success.
15349-
\return BAD_FUNC_ARG when ssl is NULL.
15350-
15351-
\param [in,out] ssl a pointer to a WOLFSSL structure, created using
15352-
wolfSSL_new().
15353-
\param [in] opt non-zero to treat the external PSK as pre-extracted.
15354-
15355-
_Example_
15356-
\code
15357-
WOLFSSL* ssl;
15358-
...
15359-
wolfSSL_external_psk_pre_extracted(ssl, 1);
15360-
\endcode
15361-
15362-
\sa wolfSSL_set_psk_client_importer_callback
15363-
\sa wolfSSL_set_psk_server_importer_callback
15364-
*/
15365-
int wolfSSL_external_psk_pre_extracted(WOLFSSL* ssl, int opt);
15366-
1536715336
/*!
1536815337
\ingroup Setup
1536915338

src/tls13.c

Lines changed: 20 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,8 +1213,7 @@ static const byte derivedPskLabel[DERIVED_PSK_LABEL_SZ + 1] =
12131213
* (RFC 9258, Section 3.1). This core routine is independent of WOLFSSL state so
12141214
* it can be exercised directly with known-answer test vectors.
12151215
*
1216-
* epsk/epskSz External PSK base key (or a pre-extracted PRK).
1217-
* preExtracted Non-zero if epsk is already a PRK (skip HKDF-Extract).
1216+
* epsk/epskSz External PSK base key.
12181217
* importedIdentity Serialized ImportedIdentity (hashed as the context).
12191218
* importedIdentitySz Length of importedIdentity.
12201219
* importerHash Hash associated with the EPSK (e.g. WC_SHA256), used for
@@ -1231,10 +1230,9 @@ static const byte derivedPskLabel[DERIVED_PSK_LABEL_SZ + 1] =
12311230
* Returns 0 on success, otherwise a negative error.
12321231
*/
12331232
WOLFSSL_LOCAL int DeriveImportedPsk(const byte* epsk, word32 epskSz,
1234-
int preExtracted, const byte* importedIdentity,
1235-
word32 importedIdentitySz, int importerHash, byte targetKdfMac,
1236-
byte protocolMinor, int isDtls, byte* out, word32* outSz,
1237-
void* heap, int devId)
1233+
const byte* importedIdentity, word32 importedIdentitySz,
1234+
int importerHash, byte targetKdfMac, byte protocolMinor, int isDtls,
1235+
byte* out, word32* outSz, void* heap, int devId)
12381236
{
12391237
int ret;
12401238
const byte* protocol;
@@ -1357,28 +1355,19 @@ WOLFSSL_LOCAL int DeriveImportedPsk(const byte* epsk, word32 epskSz,
13571355
/* okm holds ipskx; prk holds epskx. Both are dedicated buffers so the
13581356
* HKDF input may safely alias the output buffer. */
13591357
PRIVATE_KEY_UNLOCK();
1360-
if (preExtracted) {
1361-
/* The external PSK is already a pseudorandom key (the result of an
1362-
* earlier HKDF-Extract), so derive ipskx directly with an
1363-
* HKDF-Expand-Label. */
1364-
ret = wc_HKDF_Expand_ex(importerHash, epsk, epskSz, hkdfLabel, idx,
1365-
okm, outputLen, heap, devId);
1366-
}
1367-
else {
1368-
/* epskx = HKDF-Extract(0, epsk) */
1369-
#if !defined(HAVE_FIPS) || \
1370-
(defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(6,0))
1371-
ret = wc_HKDF_Extract_ex(importerHash, NULL, 0, epsk, epskSz, prk,
1372-
heap, devId);
1373-
#else
1374-
ret = wc_HKDF_Extract(importerHash, NULL, 0, epsk, epskSz, prk);
1375-
#endif
1376-
if (ret == 0) {
1377-
/* ipskx = HKDF-Expand-Label(epskx, "derived psk",
1378-
* Hash(ImportedIdentity), L) */
1379-
ret = wc_HKDF_Expand_ex(importerHash, prk, (word32)hashSz,
1380-
hkdfLabel, idx, okm, outputLen, heap, devId);
1381-
}
1358+
/* epskx = HKDF-Extract(0, epsk) */
1359+
#if !defined(HAVE_FIPS) || \
1360+
(defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(6,0))
1361+
ret = wc_HKDF_Extract_ex(importerHash, NULL, 0, epsk, epskSz, prk,
1362+
heap, devId);
1363+
#else
1364+
ret = wc_HKDF_Extract(importerHash, NULL, 0, epsk, epskSz, prk);
1365+
#endif
1366+
if (ret == 0) {
1367+
/* ipskx = HKDF-Expand-Label(epskx, "derived psk",
1368+
* Hash(ImportedIdentity), L) */
1369+
ret = wc_HKDF_Expand_ex(importerHash, prk, (word32)hashSz,
1370+
hkdfLabel, idx, okm, outputLen, heap, devId);
13821371
}
13831372
PRIVATE_KEY_LOCK();
13841373

@@ -1424,10 +1413,9 @@ static int DeriveImportedPreSharedKey(WOLFSSL* ssl, PreSharedKey* psk,
14241413

14251414
keySz = ssl->arrays->psk_keySz;
14261415
ret = DeriveImportedPsk(ssl->arrays->psk_key, ssl->arrays->psk_keySz,
1427-
ssl->arrays->psk_externalKeyPreExtracted, psk->identity,
1428-
psk->identityLen, importerHash, psk->hmac, ssl->version.minor,
1429-
ssl->options.dtls, ssl->arrays->psk_key, &keySz, ssl->heap,
1430-
ssl->devId);
1416+
psk->identity, psk->identityLen, importerHash, psk->hmac,
1417+
ssl->version.minor, ssl->options.dtls, ssl->arrays->psk_key, &keySz,
1418+
ssl->heap, ssl->devId);
14311419
if (ret == 0)
14321420
ssl->arrays->psk_keySz = keySz;
14331421

@@ -15833,29 +15821,6 @@ const char* wolfSSL_get_cipher_name_by_hash(WOLFSSL* ssl, const char* hash)
1583315821
}
1583415822
return name;
1583515823
}
15836-
15837-
#if defined(WOLFSSL_EXTERNAL_PSK_IMPORTER)
15838-
/* Mark whether the external PSK provided by the importer callback is already a
15839-
* pre-extracted pseudorandom key. When set, the imported-PSK derivation skips
15840-
* the HKDF-Extract step (RFC 9258, Section 3.1).
15841-
*
15842-
* ssl The SSL/TLS object.
15843-
* opt Non-zero to treat the external PSK as pre-extracted.
15844-
* returns BAD_FUNC_ARG when ssl is NULL and 0 on success.
15845-
*/
15846-
int wolfSSL_external_psk_pre_extracted(WOLFSSL* ssl, int opt)
15847-
{
15848-
if (ssl == NULL)
15849-
return BAD_FUNC_ARG;
15850-
15851-
if (opt)
15852-
ssl->arrays->psk_externalKeyPreExtracted = 1;
15853-
else
15854-
ssl->arrays->psk_externalKeyPreExtracted = 0;
15855-
15856-
return 0;
15857-
}
15858-
#endif /* WOLFSSL_EXTERNAL_PSK_IMPORTER */
1585915824
#endif /* !NO_PSK */
1586015825

1586115826

tests/api.c

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30496,7 +30496,7 @@ static int test_psk_importer_server_cb(WOLFSSL* ssl, const unsigned char* id,
3049630496
/* Run a single TLS 1.3 handshake that authenticates with an imported external
3049730497
* PSK (RFC 9258), restricted to the given cipher suite. */
3049830498
static int test_tls13_external_psk_importer_one(const char* cipher,
30499-
int expectedSuite, int useContext, int preExtracted, int expectFail)
30499+
int expectedSuite, int useContext, int expectFail)
3050030500
{
3050130501
EXPECT_DECLS;
3050230502
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
@@ -30519,11 +30519,6 @@ static int test_tls13_external_psk_importer_one(const char* cipher,
3051930519
wolfSSL_set_psk_server_importer_callback(ssl_s,
3052030520
test_psk_importer_server_cb);
3052130521

30522-
if (preExtracted) {
30523-
ExpectIntEQ(wolfSSL_external_psk_pre_extracted(ssl_c, 1), 0);
30524-
ExpectIntEQ(wolfSSL_external_psk_pre_extracted(ssl_s, 1), 0);
30525-
}
30526-
3052730522
/* Restrict both sides to the suite under test (importer callback setup
3052830523
* rebuilds the suite list, so set the cipher list afterwards). */
3052930524
ExpectIntEQ(wolfSSL_set_cipher_list(ssl_c, cipher), WOLFSSL_SUCCESS);
@@ -30556,16 +30551,13 @@ static int test_tls13_external_psk_importer(void)
3055630551

3055730552
/* HKDF_SHA256 target_kdf, without and with an optional context. */
3055830553
ExpectIntEQ(test_tls13_external_psk_importer_one("TLS13-AES128-GCM-SHA256",
30559-
0x1301, 0, 0, 0), TEST_SUCCESS);
30560-
ExpectIntEQ(test_tls13_external_psk_importer_one("TLS13-AES128-GCM-SHA256",
30561-
0x1301, 1, 0, 0), TEST_SUCCESS);
30562-
/* Pre-extracted EPSK (HKDF-Extract is skipped during import). */
30554+
0x1301, 0, 0), TEST_SUCCESS);
3056330555
ExpectIntEQ(test_tls13_external_psk_importer_one("TLS13-AES128-GCM-SHA256",
30564-
0x1301, 1, 1, 0), TEST_SUCCESS);
30556+
0x1301, 1, 0), TEST_SUCCESS);
3056530557
#if defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256)
3056630558
/* HKDF_SHA384 target_kdf exercises the L = 48 derived-PSK length. */
3056730559
ExpectIntEQ(test_tls13_external_psk_importer_one("TLS13-AES256-GCM-SHA384",
30568-
0x1302, 1, 0, 0), TEST_SUCCESS);
30560+
0x1302, 1, 0), TEST_SUCCESS);
3056930561
#endif
3057030562

3057130563
#if defined(WOLFSSL_SHA384)
@@ -30574,15 +30566,15 @@ static int test_tls13_external_psk_importer(void)
3057430566
* target KDF (RFC 9258 Section 3.1). */
3057530567
test_psk_importer_hash = WC_SHA384;
3057630568
ExpectIntEQ(test_tls13_external_psk_importer_one("TLS13-AES128-GCM-SHA256",
30577-
0x1301, 1, 0, 0), TEST_SUCCESS);
30569+
0x1301, 1, 0), TEST_SUCCESS);
3057830570
test_psk_importer_hash = WC_SHA256;
3057930571
#endif
3058030572

3058130573
/* Negative: server derives a different imported PSK -> binder mismatch
3058230574
* -> handshake must fail. */
3058330575
test_psk_importer_server_wrong_key = 1;
3058430576
ExpectIntEQ(test_tls13_external_psk_importer_one("TLS13-AES128-GCM-SHA256",
30585-
0x1301, 1, 0, 1), TEST_SUCCESS);
30577+
0x1301, 1, 1), TEST_SUCCESS);
3058630578
test_psk_importer_server_wrong_key = 0;
3058730579

3058830580
return EXPECT_RESULT();
@@ -30733,7 +30725,7 @@ static int test_tls13_psk_importer_kat_one(const byte* ctx, word16 ctxLen,
3073330725

3073430726
/* Derived imported PSK (ipskx) matches the independent vector. */
3073530727
ExpectIntEQ(DeriveImportedPsk(test_kat_epsk, (word32)sizeof(test_kat_epsk),
30736-
0, expII, expIISz, importerHash, targetKdfMac, TLSv1_3_MINOR, 0, out,
30728+
expII, expIISz, importerHash, targetKdfMac, TLSv1_3_MINOR, 0, out,
3073730729
&outSz, NULL, INVALID_DEVID), 0);
3073830730
ExpectIntEQ((int)outSz, (int)expIpskSz);
3073930731
ExpectIntEQ(XMEMCMP(out, expIpsk, expIpskSz), 0);

wolfssl/internal.h

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3874,10 +3874,9 @@ WOLFSSL_LOCAL int TLSX_PreSharedKey_ParseImportedIdentity(byte* input,
38743874
word16 length, byte** id, word16* id_len, byte** ctx,word16* ctx_len,
38753875
byte* hkdf, ProtocolVersion* protocol);
38763876
WOLFSSL_LOCAL int DeriveImportedPsk(const byte* epsk, word32 epskSz,
3877-
int preExtracted, const byte* importedIdentity,
3878-
word32 importedIdentitySz, int importerHash, byte targetKdfMac,
3879-
byte protocolMinor, int isDtls, byte* out, word32* outSz,
3880-
void* heap, int devId);
3877+
const byte* importedIdentity, word32 importedIdentitySz,
3878+
int importerHash, byte targetKdfMac, byte protocolMinor, int isDtls,
3879+
byte* out, word32* outSz, void* heap, int devId);
38813880
#endif
38823881
#endif /* HAVE_SESSION_TICKET || !NO_PSK */
38833882

@@ -5417,9 +5416,6 @@ typedef struct Arrays {
54175416
char client_identity[MAX_PSK_ID_LEN + NULL_TERM_LEN];
54185417
char server_hint[MAX_PSK_ID_LEN + NULL_TERM_LEN];
54195418
byte psk_key[MAX_PSK_KEY_LEN];
5420-
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_EXTERNAL_PSK_IMPORTER)
5421-
byte psk_externalKeyPreExtracted:1;
5422-
#endif /* WOLFSSL_TLS13 && WOLFSSL_EXTERNAL_PSK_IMPORTER */
54235419
#endif /* HAVE_SESSION_TICKET || !NO_PSK */
54245420
byte clientRandom[RAN_LEN];
54255421
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)

wolfssl/ssl.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3355,10 +3355,6 @@ enum { /* ssl Constants */
33553355
#ifdef WOLFSSL_TLS13
33563356
WOLFSSL_API const char* wolfSSL_get_cipher_name_by_hash(WOLFSSL* ssl,
33573357
const char* hash);
3358-
3359-
#ifdef WOLFSSL_EXTERNAL_PSK_IMPORTER
3360-
WOLFSSL_API int wolfSSL_external_psk_pre_extracted(WOLFSSL* ssl, int opt);
3361-
#endif
33623358
#endif
33633359
#endif /* NO_PSK */
33643360

0 commit comments

Comments
 (0)