Skip to content

Commit 3ca90c7

Browse files
committed
Extended API
Signed-off-by: Matthias J. Kannwischer <[email protected]>
1 parent e319849 commit 3ca90c7

File tree

4 files changed

+374
-141
lines changed

4 files changed

+374
-141
lines changed

mlkem/indcpa.c

Lines changed: 55 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,15 @@
2020
* This is to facilitate building multiple instances
2121
* of mlkem-native (e.g. with varying security levels)
2222
* within a single compilation unit. */
23-
#define mlk_pack_pk MLK_ADD_LEVEL(mlk_pack_pk)
2423
#define mlk_unpack_pk MLK_ADD_LEVEL(mlk_unpack_pk)
25-
#define mlk_pack_sk MLK_ADD_LEVEL(mlk_pack_sk)
2624
#define mlk_unpack_sk MLK_ADD_LEVEL(mlk_unpack_sk)
2725
#define mlk_pack_ciphertext MLK_ADD_LEVEL(mlk_pack_ciphertext)
2826
#define mlk_unpack_ciphertext MLK_ADD_LEVEL(mlk_unpack_ciphertext)
2927
#define mlk_matvec_mul MLK_ADD_LEVEL(mlk_matvec_mul)
3028
/* End of level namespacing */
3129

3230
/*************************************************
33-
* Name: mlk_pack_pk
31+
* Name: mlk_indcpa_marshal_pk
3432
*
3533
* Description: Serialize the public key as concatenation of the
3634
* serialized vector of polynomials pk
@@ -45,16 +43,18 @@
4543
* Implements [FIPS 203, Algorithm 13 (K-PKE.KeyGen), L19]
4644
*
4745
**************************************************/
48-
static void mlk_pack_pk(uint8_t r[MLKEM_INDCPA_PUBLICKEYBYTES], mlk_polyvec *pk,
49-
const uint8_t seed[MLKEM_SYMBYTES])
46+
MLK_INTERNAL_API
47+
void mlk_indcpa_marshal_pk(uint8_t pk[MLKEM_INDCPA_PUBLICKEYBYTES],
48+
const mlk_indcpa_public_key *pks)
5049
{
51-
mlk_assert_bound_2d(pk, MLKEM_K, MLKEM_N, 0, MLKEM_Q);
52-
mlk_polyvec_tobytes(r, pk);
53-
memcpy(r + MLKEM_POLYVECBYTES, seed, MLKEM_SYMBYTES);
50+
mlk_assert_bound_2d(pks->pkpv, MLKEM_K, MLKEM_N, 0, MLKEM_Q);
51+
mlk_polyvec_tobytes(pk, &pks->pkpv);
52+
memcpy(pk + MLKEM_POLYVECBYTES, pks->seed, MLKEM_SYMBYTES);
5453
}
5554

55+
5656
/*************************************************
57-
* Name: mlk_unpack_pk
57+
* Name: mlk_indcpa_parse_pk
5858
*
5959
* Description: De-serialize public key from a byte array;
6060
* approximate inverse of mlk_pack_pk
@@ -69,11 +69,13 @@ static void mlk_pack_pk(uint8_t r[MLKEM_INDCPA_PUBLICKEYBYTES], mlk_polyvec *pk,
6969
* Implements [FIPS 203, Algorithm 14 (K-PKE.Encrypt), L2-3]
7070
*
7171
**************************************************/
72-
static void mlk_unpack_pk(mlk_polyvec *pk, uint8_t seed[MLKEM_SYMBYTES],
73-
const uint8_t packedpk[MLKEM_INDCPA_PUBLICKEYBYTES])
72+
MLK_INTERNAL_API
73+
void mlk_indcpa_parse_pk(mlk_indcpa_public_key *pks,
74+
const uint8_t pk[MLKEM_INDCPA_PUBLICKEYBYTES])
7475
{
75-
mlk_polyvec_frombytes(pk, packedpk);
76-
memcpy(seed, packedpk + MLKEM_POLYVECBYTES, MLKEM_SYMBYTES);
76+
mlk_polyvec_frombytes(&pks->pkpv, pk);
77+
memcpy(pks->seed, pk + MLKEM_POLYVECBYTES, MLKEM_SYMBYTES);
78+
mlk_gen_matrix(pks->at, pks->seed, 1);
7779

7880
/* NOTE: If a modulus check was conducted on the PK, we know at this
7981
* point that the coefficients of `pk` are unsigned canonical. The
@@ -82,7 +84,7 @@ static void mlk_unpack_pk(mlk_polyvec *pk, uint8_t seed[MLKEM_SYMBYTES],
8284
}
8385

8486
/*************************************************
85-
* Name: mlk_pack_sk
87+
* Name: mlk_indcpa_marshal_sk
8688
*
8789
* Description: Serialize the secret key
8890
*
@@ -94,14 +96,16 @@ static void mlk_unpack_pk(mlk_polyvec *pk, uint8_t seed[MLKEM_SYMBYTES],
9496
* Implements [FIPS 203, Algorithm 13 (K-PKE.KeyGen), L20]
9597
*
9698
**************************************************/
97-
static void mlk_pack_sk(uint8_t r[MLKEM_INDCPA_SECRETKEYBYTES], mlk_polyvec *sk)
99+
MLK_INTERNAL_API
100+
void mlk_indcpa_marshal_sk(uint8_t sk[MLKEM_INDCPA_SECRETKEYBYTES],
101+
const mlk_indcpa_secret_key *sks)
98102
{
99-
mlk_assert_bound_2d(sk, MLKEM_K, MLKEM_N, 0, MLKEM_Q);
100-
mlk_polyvec_tobytes(r, sk);
103+
mlk_assert_bound_2d(&sks->skpv, MLKEM_K, MLKEM_N, 0, MLKEM_Q);
104+
mlk_polyvec_tobytes(sk, &sks->skpv);
101105
}
102106

103107
/*************************************************
104-
* Name: mlk_unpack_sk
108+
* Name: mlk_indcpa_parse_sk
105109
*
106110
* Description: De-serialize the secret key; inverse of mlk_pack_sk
107111
*
@@ -114,10 +118,11 @@ static void mlk_pack_sk(uint8_t r[MLKEM_INDCPA_SECRETKEYBYTES], mlk_polyvec *sk)
114118
* Implements [FIPS 203, Algorithm 15 (K-PKE.Decrypt), L5]
115119
*
116120
**************************************************/
117-
static void mlk_unpack_sk(mlk_polyvec *sk,
118-
const uint8_t packedsk[MLKEM_INDCPA_SECRETKEYBYTES])
121+
MLK_INTERNAL_API
122+
void mlk_indcpa_parse_sk(mlk_indcpa_secret_key *sks,
123+
const uint8_t sk[MLKEM_INDCPA_SECRETKEYBYTES])
119124
{
120-
mlk_polyvec_frombytes(sk, packedsk);
125+
mlk_polyvec_frombytes(&sks->skpv, sk);
121126
}
122127

123128
/*************************************************
@@ -332,14 +337,14 @@ __contract__(
332337
* - We include buffer zeroization.
333338
*/
334339
MLK_INTERNAL_API
335-
void mlk_indcpa_keypair_derand(uint8_t pk[MLKEM_INDCPA_PUBLICKEYBYTES],
336-
uint8_t sk[MLKEM_INDCPA_SECRETKEYBYTES],
340+
void mlk_indcpa_keypair_derand(mlk_indcpa_public_key *pk,
341+
mlk_indcpa_secret_key *sk,
337342
const uint8_t coins[MLKEM_SYMBYTES])
338343
{
339344
MLK_ALIGN uint8_t buf[2 * MLKEM_SYMBYTES];
340345
const uint8_t *publicseed = buf;
341346
const uint8_t *noiseseed = buf + MLKEM_SYMBYTES;
342-
mlk_polyvec a[MLKEM_K], e, pkpv, skpv;
347+
mlk_polyvec e;
343348
mlk_polyvec_mulcache skpv_cache;
344349

345350
MLK_ALIGN uint8_t coins_with_domain_separator[MLKEM_SYMBYTES + 1];
@@ -357,51 +362,48 @@ void mlk_indcpa_keypair_derand(uint8_t pk[MLKEM_INDCPA_PUBLICKEYBYTES],
357362
*/
358363
MLK_CT_TESTING_DECLASSIFY(publicseed, MLKEM_SYMBYTES);
359364

360-
mlk_gen_matrix(a, publicseed, 0 /* no transpose */);
365+
mlk_gen_matrix(pk->at, publicseed, 0 /* no transpose */);
361366

362367
#if MLKEM_K == 2
363-
mlk_poly_getnoise_eta1_4x(skpv.vec + 0, skpv.vec + 1, e.vec + 0, e.vec + 1,
364-
noiseseed, 0, 1, 2, 3);
368+
mlk_poly_getnoise_eta1_4x(sk->skpv.vec + 0, sk->skpv.vec + 1, e.vec + 0,
369+
e.vec + 1, noiseseed, 0, 1, 2, 3);
365370
#elif MLKEM_K == 3
366371
/*
367372
* Only the first three output buffers are needed.
368373
* The laster parameter is a dummy that's overwritten later.
369374
*/
370-
mlk_poly_getnoise_eta1_4x(skpv.vec + 0, skpv.vec + 1, skpv.vec + 2,
371-
pkpv.vec + 0 /* irrelevant */, noiseseed, 0, 1, 2,
372-
0xFF /* irrelevant */);
375+
mlk_poly_getnoise_eta1_4x(sk->skpv.vec + 0, sk->skpv.vec + 1,
376+
sk->skpv.vec + 2, pk->pkpv.vec + 0 /* irrelevant */,
377+
noiseseed, 0, 1, 2, 0xFF /* irrelevant */);
373378
/* Same here */
374379
mlk_poly_getnoise_eta1_4x(e.vec + 0, e.vec + 1, e.vec + 2,
375-
pkpv.vec + 0 /* irrelevant */, noiseseed, 3, 4, 5,
376-
0xFF /* irrelevant */);
380+
pk->pkpv.vec + 0 /* irrelevant */, noiseseed, 3, 4,
381+
5, 0xFF /* irrelevant */);
377382
#elif MLKEM_K == 4
378-
mlk_poly_getnoise_eta1_4x(skpv.vec + 0, skpv.vec + 1, skpv.vec + 2,
379-
skpv.vec + 3, noiseseed, 0, 1, 2, 3);
383+
mlk_poly_getnoise_eta1_4x(sk->skpv.vec + 0, sk->skpv.vec + 1,
384+
sk->skpv.vec + 2, sk->skpv.vec + 3, noiseseed, 0, 1,
385+
2, 3);
380386
mlk_poly_getnoise_eta1_4x(e.vec + 0, e.vec + 1, e.vec + 2, e.vec + 3,
381387
noiseseed, 4, 5, 6, 7);
382388
#endif
383389

384-
mlk_polyvec_ntt(&skpv);
390+
mlk_polyvec_ntt(&sk->skpv);
385391
mlk_polyvec_ntt(&e);
386392

387-
mlk_polyvec_mulcache_compute(&skpv_cache, &skpv);
388-
mlk_matvec_mul(&pkpv, a, &skpv, &skpv_cache);
389-
mlk_polyvec_tomont(&pkpv);
390-
391-
mlk_polyvec_add(&pkpv, &e);
392-
mlk_polyvec_reduce(&pkpv);
393-
mlk_polyvec_reduce(&skpv);
393+
mlk_polyvec_mulcache_compute(&skpv_cache, &sk->skpv);
394+
mlk_matvec_mul(&pk->pkpv, pk->at, &sk->skpv, &skpv_cache);
395+
mlk_polyvec_tomont(&pk->pkpv);
394396

395-
mlk_pack_sk(sk, &skpv);
396-
mlk_pack_pk(pk, &pkpv, publicseed);
397+
mlk_polyvec_add(&pk->pkpv, &e);
398+
mlk_polyvec_reduce(&pk->pkpv);
399+
mlk_polyvec_reduce(&sk->skpv);
400+
memcpy(pk->seed, publicseed, MLKEM_SYMBYTES);
397401

398402
/* Specification: Partially implements
399403
* [FIPS 203, Section 3.3, Destruction of intermediate values] */
400404
mlk_zeroize(buf, sizeof(buf));
401405
mlk_zeroize(coins_with_domain_separator, sizeof(coins_with_domain_separator));
402-
mlk_zeroize(a, sizeof(a));
403406
mlk_zeroize(&e, sizeof(e));
404-
mlk_zeroize(&skpv, sizeof(skpv));
405407
mlk_zeroize(&skpv_cache, sizeof(skpv_cache));
406408
}
407409

@@ -416,27 +418,14 @@ void mlk_indcpa_keypair_derand(uint8_t pk[MLKEM_INDCPA_PUBLICKEYBYTES],
416418
MLK_INTERNAL_API
417419
void mlk_indcpa_enc(uint8_t c[MLKEM_INDCPA_BYTES],
418420
const uint8_t m[MLKEM_INDCPA_MSGBYTES],
419-
const uint8_t pk[MLKEM_INDCPA_PUBLICKEYBYTES],
421+
const mlk_indcpa_public_key *pk,
420422
const uint8_t coins[MLKEM_SYMBYTES])
421423
{
422-
MLK_ALIGN uint8_t seed[MLKEM_SYMBYTES];
423-
mlk_polyvec sp, pkpv, ep, at[MLKEM_K], b;
424+
mlk_polyvec sp, ep, b;
424425
mlk_poly v, k, epp;
425426
mlk_polyvec_mulcache sp_cache;
426-
427-
mlk_unpack_pk(&pkpv, seed, pk);
428427
mlk_poly_frommsg(&k, m);
429428

430-
/*
431-
* Declassify the public seed.
432-
* Required to use it in conditional-branches in rejection sampling.
433-
* This is needed because in re-encryption the publicseed originated from sk
434-
* which is marked undefined.
435-
*/
436-
MLK_CT_TESTING_DECLASSIFY(seed, MLKEM_SYMBYTES);
437-
438-
mlk_gen_matrix(at, seed, 1 /* transpose */);
439-
440429
#if MLKEM_K == 2
441430
mlk_poly_getnoise_eta1122_4x(sp.vec + 0, sp.vec + 1, ep.vec + 0, ep.vec + 1,
442431
coins, 0, 1, 2, 3);
@@ -462,8 +451,8 @@ void mlk_indcpa_enc(uint8_t c[MLKEM_INDCPA_BYTES],
462451
mlk_polyvec_ntt(&sp);
463452

464453
mlk_polyvec_mulcache_compute(&sp_cache, &sp);
465-
mlk_matvec_mul(&b, at, &sp, &sp_cache);
466-
mlk_polyvec_basemul_acc_montgomery_cached(&v, &pkpv, &sp, &sp_cache);
454+
mlk_matvec_mul(&b, pk->at, &sp, &sp_cache);
455+
mlk_polyvec_basemul_acc_montgomery_cached(&v, &pk->pkpv, &sp, &sp_cache);
467456

468457
mlk_polyvec_invntt_tomont(&b);
469458
mlk_poly_invntt_tomont(&v);
@@ -479,12 +468,10 @@ void mlk_indcpa_enc(uint8_t c[MLKEM_INDCPA_BYTES],
479468

480469
/* Specification: Partially implements
481470
* [FIPS 203, Section 3.3, Destruction of intermediate values] */
482-
mlk_zeroize(seed, sizeof(seed));
483471
mlk_zeroize(&sp, sizeof(sp));
484472
mlk_zeroize(&sp_cache, sizeof(sp_cache));
485473
mlk_zeroize(&b, sizeof(b));
486474
mlk_zeroize(&v, sizeof(v));
487-
mlk_zeroize(at, sizeof(at));
488475
mlk_zeroize(&k, sizeof(k));
489476
mlk_zeroize(&ep, sizeof(ep));
490477
mlk_zeroize(&epp, sizeof(epp));
@@ -496,18 +483,17 @@ void mlk_indcpa_enc(uint8_t c[MLKEM_INDCPA_BYTES],
496483
MLK_INTERNAL_API
497484
void mlk_indcpa_dec(uint8_t m[MLKEM_INDCPA_MSGBYTES],
498485
const uint8_t c[MLKEM_INDCPA_BYTES],
499-
const uint8_t sk[MLKEM_INDCPA_SECRETKEYBYTES])
486+
const mlk_indcpa_secret_key *sk)
500487
{
501-
mlk_polyvec b, skpv;
488+
mlk_polyvec b;
502489
mlk_poly v, sb;
503490
mlk_polyvec_mulcache b_cache;
504491

505492
mlk_unpack_ciphertext(&b, &v, c);
506-
mlk_unpack_sk(&skpv, sk);
507493

508494
mlk_polyvec_ntt(&b);
509495
mlk_polyvec_mulcache_compute(&b_cache, &b);
510-
mlk_polyvec_basemul_acc_montgomery_cached(&sb, &skpv, &b, &b_cache);
496+
mlk_polyvec_basemul_acc_montgomery_cached(&sb, &sk->skpv, &b, &b_cache);
511497
mlk_poly_invntt_tomont(&sb);
512498

513499
mlk_poly_sub(&v, &sb);
@@ -517,7 +503,6 @@ void mlk_indcpa_dec(uint8_t m[MLKEM_INDCPA_MSGBYTES],
517503

518504
/* Specification: Partially implements
519505
* [FIPS 203, Section 3.3, Destruction of intermediate values] */
520-
mlk_zeroize(&skpv, sizeof(skpv));
521506
mlk_zeroize(&b, sizeof(b));
522507
mlk_zeroize(&b_cache, sizeof(b_cache));
523508
mlk_zeroize(&v, sizeof(v));
@@ -526,9 +511,7 @@ void mlk_indcpa_dec(uint8_t m[MLKEM_INDCPA_MSGBYTES],
526511

527512
/* To facilitate single-compilation-unit (SCU) builds, undefine all macros.
528513
* Don't modify by hand -- this is auto-generated by scripts/autogen. */
529-
#undef mlk_pack_pk
530514
#undef mlk_unpack_pk
531-
#undef mlk_pack_sk
532515
#undef mlk_unpack_sk
533516
#undef mlk_pack_ciphertext
534517
#undef mlk_unpack_ciphertext

mlkem/indcpa.h

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,34 @@
1010
#include "common.h"
1111
#include "poly_k.h"
1212

13+
typedef struct
14+
{
15+
mlk_polyvec skpv;
16+
} mlk_indcpa_secret_key;
17+
18+
typedef struct
19+
{
20+
mlk_polyvec at[MLKEM_K]; /* transposed matrix */
21+
mlk_polyvec pkpv;
22+
uint8_t seed[MLKEM_SYMBYTES];
23+
} mlk_indcpa_public_key;
24+
25+
MLK_INTERNAL_API
26+
void mlk_indcpa_marshal_pk(uint8_t pk[MLKEM_INDCPA_PUBLICKEYBYTES],
27+
const mlk_indcpa_public_key *pks);
28+
29+
MLK_INTERNAL_API
30+
void mlk_indcpa_parse_pk(mlk_indcpa_public_key *pks,
31+
const uint8_t pk[MLKEM_INDCPA_PUBLICKEYBYTES]);
32+
33+
MLK_INTERNAL_API
34+
void mlk_indcpa_marshal_sk(uint8_t sk[MLKEM_INDCPA_SECRETKEYBYTES],
35+
const mlk_indcpa_secret_key *sks);
36+
37+
MLK_INTERNAL_API
38+
void mlk_indcpa_parse_sk(mlk_indcpa_secret_key *sks,
39+
const uint8_t sk[MLKEM_INDCPA_SECRETKEYBYTES]);
40+
1341
#define mlk_gen_matrix MLK_NAMESPACE_K(gen_matrix)
1442
/*************************************************
1543
* Name: mlk_gen_matrix
@@ -58,12 +86,12 @@ __contract__(
5886
*
5987
**************************************************/
6088
MLK_INTERNAL_API
61-
void mlk_indcpa_keypair_derand(uint8_t pk[MLKEM_INDCPA_PUBLICKEYBYTES],
62-
uint8_t sk[MLKEM_INDCPA_SECRETKEYBYTES],
89+
void mlk_indcpa_keypair_derand(mlk_indcpa_public_key *pk,
90+
mlk_indcpa_secret_key *sk,
6391
const uint8_t coins[MLKEM_SYMBYTES])
6492
__contract__(
65-
requires(memory_no_alias(pk, MLKEM_INDCPA_PUBLICKEYBYTES))
66-
requires(memory_no_alias(sk, MLKEM_INDCPA_SECRETKEYBYTES))
93+
requires(memory_no_alias(pk, sizeof(mlk_indcpa_public_key)))
94+
requires(memory_no_alias(sk, sizeof(mlk_indcpa_secret_key)))
6795
requires(memory_no_alias(coins, MLKEM_SYMBYTES))
6896
assigns(object_whole(pk))
6997
assigns(object_whole(sk))
@@ -92,12 +120,12 @@ __contract__(
92120
MLK_INTERNAL_API
93121
void mlk_indcpa_enc(uint8_t c[MLKEM_INDCPA_BYTES],
94122
const uint8_t m[MLKEM_INDCPA_MSGBYTES],
95-
const uint8_t pk[MLKEM_INDCPA_PUBLICKEYBYTES],
123+
const mlk_indcpa_public_key *pk,
96124
const uint8_t coins[MLKEM_SYMBYTES])
97125
__contract__(
98126
requires(memory_no_alias(c, MLKEM_INDCPA_BYTES))
99127
requires(memory_no_alias(m, MLKEM_INDCPA_MSGBYTES))
100-
requires(memory_no_alias(pk, MLKEM_INDCPA_PUBLICKEYBYTES))
128+
requires(memory_no_alias(pk, sizeof(mlk_indcpa_public_key)))
101129
requires(memory_no_alias(coins, MLKEM_SYMBYTES))
102130
assigns(object_whole(c))
103131
);
@@ -122,11 +150,11 @@ __contract__(
122150
MLK_INTERNAL_API
123151
void mlk_indcpa_dec(uint8_t m[MLKEM_INDCPA_MSGBYTES],
124152
const uint8_t c[MLKEM_INDCPA_BYTES],
125-
const uint8_t sk[MLKEM_INDCPA_SECRETKEYBYTES])
153+
const mlk_indcpa_secret_key *sk)
126154
__contract__(
127155
requires(memory_no_alias(c, MLKEM_INDCPA_BYTES))
128156
requires(memory_no_alias(m, MLKEM_INDCPA_MSGBYTES))
129-
requires(memory_no_alias(sk, MLKEM_INDCPA_SECRETKEYBYTES))
157+
requires(memory_no_alias(sk, sizeof(mlk_indcpa_secret_key)))
130158
assigns(object_whole(m))
131159
);
132160

0 commit comments

Comments
 (0)