Skip to content

Commit 1b1b085

Browse files
Merge pull request #9822 from SparkiDev/mlkem_decap_h_set
ML-KEM decapsulate: check for H
2 parents 2064ff4 + 8a75e7d commit 1b1b085

2 files changed

Lines changed: 78 additions & 37 deletions

File tree

wolfcrypt/src/wc_mlkem.c

Lines changed: 55 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -950,6 +950,55 @@ static int mlkemkey_encapsulate(MlKemKey* key, const byte* m, byte* r, byte* c)
950950
}
951951
#endif
952952

953+
#if !defined(WOLFSSL_MLKEM_NO_ENCAPSULATE) || \
954+
!defined(WOLFSSL_MLKEM_NO_DECAPSULATE)
955+
static int wc_mlkemkey_check_h(MlKemKey* key)
956+
{
957+
int ret = 0;
958+
959+
/* If public hash (h) is not stored against key, calculate it
960+
* (fields set explicitly instead of using decode).
961+
* Step 1: ... H(ek)...
962+
*/
963+
if ((key->flags & MLKEM_FLAG_H_SET) == 0) {
964+
#ifndef WOLFSSL_NO_MALLOC
965+
byte* pubKey = NULL;
966+
word32 pubKeyLen;
967+
#else
968+
byte pubKey[WC_ML_KEM_MAX_PUBLIC_KEY_SIZE];
969+
word32 pubKeyLen;
970+
#endif
971+
972+
/* Determine how big an encoded public key will be. */
973+
ret = wc_KyberKey_PublicKeySize(key, &pubKeyLen);
974+
if (ret == 0) {
975+
#ifndef WOLFSSL_NO_MALLOC
976+
/* Allocate dynamic memory for encoded public key. */
977+
pubKey = (byte*)XMALLOC(pubKeyLen, key->heap,
978+
DYNAMIC_TYPE_TMP_BUFFER);
979+
if (pubKey == NULL) {
980+
ret = MEMORY_E;
981+
}
982+
}
983+
if (ret == 0) {
984+
#endif
985+
/* Encode public key - h is hash of encoded public key. */
986+
ret = wc_KyberKey_EncodePublicKey(key, pubKey, pubKeyLen);
987+
}
988+
#ifndef WOLFSSL_NO_MALLOC
989+
/* Dispose of encoded public key. */
990+
XFREE(pubKey, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
991+
#endif
992+
}
993+
if ((ret == 0) && ((key->flags & MLKEM_FLAG_H_SET) == 0)) {
994+
/* Implementation issue if h not cached and flag set. */
995+
ret = BAD_STATE_E;
996+
}
997+
998+
return ret;
999+
}
1000+
#endif
1001+
9531002
#ifndef WOLFSSL_MLKEM_NO_ENCAPSULATE
9541003
/**
9551004
* Encapsulate with random number generator and derive secret.
@@ -1084,43 +1133,8 @@ int wc_MlKemKey_EncapsulateWithRandom(MlKemKey* key, unsigned char* c,
10841133
}
10851134
#endif
10861135

1087-
/* If public hash (h) is not stored against key, calculate it
1088-
* (fields set explicitly instead of using decode).
1089-
* Step 1: ... H(ek)...
1090-
*/
1091-
if ((ret == 0) && ((key->flags & MLKEM_FLAG_H_SET) == 0)) {
1092-
#ifndef WOLFSSL_NO_MALLOC
1093-
byte* pubKey = NULL;
1094-
word32 pubKeyLen;
1095-
#else
1096-
byte pubKey[WC_ML_KEM_MAX_PUBLIC_KEY_SIZE];
1097-
word32 pubKeyLen = WC_ML_KEM_MAX_PUBLIC_KEY_SIZE;
1098-
#endif
1099-
1100-
#ifndef WOLFSSL_NO_MALLOC
1101-
/* Determine how big an encoded public key will be. */
1102-
ret = wc_KyberKey_PublicKeySize(key, &pubKeyLen);
1103-
if (ret == 0) {
1104-
/* Allocate dynamic memory for encoded public key. */
1105-
pubKey = (byte*)XMALLOC(pubKeyLen, key->heap,
1106-
DYNAMIC_TYPE_TMP_BUFFER);
1107-
if (pubKey == NULL) {
1108-
ret = MEMORY_E;
1109-
}
1110-
}
1111-
if (ret == 0) {
1112-
#endif
1113-
/* Encode public key - h is hash of encoded public key. */
1114-
ret = wc_KyberKey_EncodePublicKey(key, pubKey, pubKeyLen);
1115-
#ifndef WOLFSSL_NO_MALLOC
1116-
}
1117-
/* Dispose of encoded public key. */
1118-
XFREE(pubKey, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
1119-
#endif
1120-
}
1121-
if ((ret == 0) && ((key->flags & MLKEM_FLAG_H_SET) == 0)) {
1122-
/* Implementation issue if h not cached and flag set. */
1123-
ret = BAD_STATE_E;
1136+
if (ret == 0) {
1137+
ret = wc_mlkemkey_check_h(key);
11241138
}
11251139

11261140
#ifdef WOLFSSL_MLKEM_KYBER
@@ -1487,6 +1501,10 @@ int wc_MlKemKey_Decapsulate(MlKemKey* key, unsigned char* ss,
14871501
/* Decapsulate the cipher text. */
14881502
ret = mlkemkey_decapsulate(key, msg, ct);
14891503
}
1504+
if (ret == 0) {
1505+
/* Check we have H, hash of public, set. */
1506+
ret = wc_mlkemkey_check_h(key);
1507+
}
14901508
if (ret == 0) {
14911509
/* Hash message into seed buffer. */
14921510
ret = MLKEM_HASH_G(&key->hash, msg, WC_ML_KEM_SYM_SZ, key->h,

wolfcrypt/test/test.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42962,6 +42962,29 @@ static wc_test_ret_t mlkem512_kat(void)
4296242962

4296342963
if (XMEMCMP(ss_dec, ml_kem_512_ss, sizeof(ml_kem_512_ss)) != 0)
4296442964
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
42965+
42966+
#ifndef WOLFSSL_MLKEM_NO_MAKE_KEY
42967+
wc_MlKemKey_Free(key);
42968+
XMEMSET(key, 0, sizeof(MlKemKey));
42969+
key_inited = 0;
42970+
ret = wc_MlKemKey_Init(key, WC_ML_KEM_512, HEAP_HINT, devId);
42971+
if (ret != 0)
42972+
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
42973+
else
42974+
key_inited = 1;
42975+
ret = wc_MlKemKey_MakeKeyWithRandom(key, kyber512_rand,
42976+
sizeof(kyber512_rand));
42977+
if (ret != 0)
42978+
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
42979+
42980+
ret = wc_MlKemKey_Decapsulate(key, ss_dec, ml_kem_512_ct,
42981+
sizeof(ml_kem_512_ct));
42982+
if (ret != 0)
42983+
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
42984+
42985+
if (XMEMCMP(ss_dec, ml_kem_512_ss, sizeof(ml_kem_512_ss)) != 0)
42986+
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
42987+
#endif
4296542988
#else
4296642989
(void)ml_kem_512_ct;
4296742990
(void)ml_kem_512_ss;

0 commit comments

Comments
 (0)