Skip to content

Commit 50f28d9

Browse files
committed
fix for wc_DhAgree public key validation
Reported by: Nicholas Carlini <npc@anthropic.com>
1 parent 0c9b639 commit 50f28d9

2 files changed

Lines changed: 75 additions & 1 deletion

File tree

tests/api.c

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34686,6 +34686,78 @@ static int test_sniffer_chain_input_overflow(void)
3468634686
}
3468734687
#endif /* WOLFSSL_SNIFFER && WOLFSSL_SNIFFER_CHAIN_INPUT */
3468834688

34689+
/* Test: wc_DhAgree must reject p-1 as peer public key.
34690+
* ffdhe2048 p ends with ...FFFFFFFFFFFFFFFF so p-1 ends ...FFFFFFFFFFFFFFFE */
34691+
static int test_DhAgree_rejects_p_minus_1(void)
34692+
{
34693+
EXPECT_DECLS;
34694+
#if !defined(HAVE_SELFTEST) && !defined(NO_DH) && \
34695+
defined(HAVE_FFDHE_2048) && !defined(WOLFSSL_NO_MALLOC) && \
34696+
(!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
34697+
DhKey key;
34698+
WC_RNG rng;
34699+
byte priv[256], pub[256], agree[256];
34700+
word32 privSz = sizeof(priv), pubSz = sizeof(pub), agreeSz;
34701+
34702+
/* ffdhe2048 p - copied from wolfcrypt/src/dh.c dh_ffdhe2048_p.
34703+
* p ends with 0xFF*8 so p-1 ends with ...0xFE */
34704+
static const byte ffdhe2048_p[256] = {
34705+
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
34706+
0xAD,0xF8,0x54,0x58,0xA2,0xBB,0x4A,0x9A,
34707+
0xAF,0xDC,0x56,0x20,0x27,0x3D,0x3C,0xF1,
34708+
0xD8,0xB9,0xC5,0x83,0xCE,0x2D,0x36,0x95,
34709+
0xA9,0xE1,0x36,0x41,0x14,0x64,0x33,0xFB,
34710+
0xCC,0x93,0x9D,0xCE,0x24,0x9B,0x3E,0xF9,
34711+
0x7D,0x2F,0xE3,0x63,0x63,0x0C,0x75,0xD8,
34712+
0xF6,0x81,0xB2,0x02,0xAE,0xC4,0x61,0x7A,
34713+
0xD3,0xDF,0x1E,0xD5,0xD5,0xFD,0x65,0x61,
34714+
0x24,0x33,0xF5,0x1F,0x5F,0x06,0x6E,0xD0,
34715+
0x85,0x63,0x65,0x55,0x3D,0xED,0x1A,0xF3,
34716+
0xB5,0x57,0x13,0x5E,0x7F,0x57,0xC9,0x35,
34717+
0x98,0x4F,0x0C,0x70,0xE0,0xE6,0x8B,0x77,
34718+
0xE2,0xA6,0x89,0xDA,0xF3,0xEF,0xE8,0x72,
34719+
0x1D,0xF1,0x58,0xA1,0x36,0xAD,0xE7,0x35,
34720+
0x30,0xAC,0xCA,0x4F,0x48,0x3A,0x79,0x7A,
34721+
0xBC,0x0A,0xB1,0x82,0xB3,0x24,0xFB,0x61,
34722+
0xD1,0x08,0xA9,0x4B,0xB2,0xC8,0xE3,0xFB,
34723+
0xB9,0x6A,0xDA,0xB7,0x60,0xD7,0xF4,0x68,
34724+
0x1D,0x4F,0x42,0xA3,0xDE,0x39,0x4D,0xF4,
34725+
0xAE,0x56,0xED,0xE7,0x63,0x72,0xBB,0x19,
34726+
0x0B,0x07,0xA7,0xC8,0xEE,0x0A,0x6D,0x70,
34727+
0x9E,0x02,0xFC,0xE1,0xCD,0xF7,0xE2,0xEC,
34728+
0xC0,0x34,0x04,0xCD,0x28,0x34,0x2F,0x61,
34729+
0x91,0x72,0xFE,0x9C,0xE9,0x85,0x83,0xFF,
34730+
0x8E,0x4F,0x12,0x32,0xEE,0xF2,0x81,0x83,
34731+
0xC3,0xFE,0x3B,0x1B,0x4C,0x6F,0xAD,0x73,
34732+
0x3B,0xB5,0xFC,0xBC,0x2E,0xC2,0x20,0x05,
34733+
0xC5,0x8E,0xF1,0x83,0x7D,0x16,0x83,0xB2,
34734+
0xC6,0xF3,0x4A,0x26,0xC1,0xB2,0xEF,0xFA,
34735+
0x88,0x6B,0x42,0x38,0x61,0x28,0x5C,0x97,
34736+
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
34737+
};
34738+
byte pMinus1[256];
34739+
34740+
ExpectIntEQ(wc_InitRng(&rng), 0);
34741+
ExpectIntEQ(wc_InitDhKey(&key), 0);
34742+
ExpectIntEQ(wc_DhSetNamedKey(&key, WC_FFDHE_2048), 0);
34743+
ExpectIntEQ(wc_DhGenerateKeyPair(&key, &rng, priv, &privSz,
34744+
pub, &pubSz), 0);
34745+
34746+
/* Construct p-1: last byte FF -> FE */
34747+
XMEMCPY(pMinus1, ffdhe2048_p, sizeof(ffdhe2048_p));
34748+
pMinus1[255] -= 1;
34749+
34750+
/* wc_DhAgree must reject p-1 */
34751+
agreeSz = sizeof(agree);
34752+
ExpectIntNE(wc_DhAgree(&key, agree, &agreeSz, priv, privSz,
34753+
pMinus1, sizeof(pMinus1)), 0);
34754+
34755+
wc_FreeDhKey(&key);
34756+
wc_FreeRng(&rng);
34757+
#endif
34758+
return EXPECT_RESULT();
34759+
}
34760+
3468934761
TEST_CASE testCases[] = {
3469034762
TEST_DECL(test_fileAccess),
3469134763

@@ -35500,6 +35572,7 @@ TEST_CASE testCases[] = {
3550035572
TEST_DECL(test_ocsp_responder),
3550135573
TEST_TLS_DECLS,
3550235574
TEST_DECL(test_wc_DhSetNamedKey),
35575+
TEST_DECL(test_DhAgree_rejects_p_minus_1),
3550335576

3550435577
#if defined(WOLFSSL_SNIFFER) && defined(WOLFSSL_SNIFFER_CHAIN_INPUT)
3550535578
TEST_DECL(test_sniffer_chain_input_overflow),

wolfcrypt/src/dh.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2030,12 +2030,13 @@ static int wc_DhAgree_Sync(DhKey* key, byte* agree, word32* agreeSz,
20302030
WOLFSSL_MSG("wc_DhAgree wc_DhCheckPrivKey failed");
20312031
return DH_CHECK_PRIV_E;
20322032
}
2033+
#endif
20332034

2035+
/* Always validate peer public key (2 <= y <= p-2) per SP 800-56A */
20342036
if (wc_DhCheckPubKey(key, otherPub, pubSz) != 0) {
20352037
WOLFSSL_MSG("wc_DhAgree wc_DhCheckPubKey failed");
20362038
return DH_CHECK_PUB_E;
20372039
}
2038-
#endif
20392040

20402041
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC)
20412042
y = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);

0 commit comments

Comments
 (0)