20
20
* This is to facilitate building multiple instances
21
21
* of mlkem-native (e.g. with varying security levels)
22
22
* within a single compilation unit. */
23
- #define mlk_pack_pk MLK_ADD_LEVEL(mlk_pack_pk)
24
23
#define mlk_unpack_pk MLK_ADD_LEVEL(mlk_unpack_pk)
25
- #define mlk_pack_sk MLK_ADD_LEVEL(mlk_pack_sk)
26
24
#define mlk_unpack_sk MLK_ADD_LEVEL(mlk_unpack_sk)
27
25
#define mlk_pack_ciphertext MLK_ADD_LEVEL(mlk_pack_ciphertext)
28
26
#define mlk_unpack_ciphertext MLK_ADD_LEVEL(mlk_unpack_ciphertext)
29
27
#define mlk_matvec_mul MLK_ADD_LEVEL(mlk_matvec_mul)
30
28
/* End of level namespacing */
31
29
32
30
/*************************************************
33
- * Name: mlk_pack_pk
31
+ * Name: mlk_indcpa_marshal_pk
34
32
*
35
33
* Description: Serialize the public key as concatenation of the
36
34
* serialized vector of polynomials pk
45
43
* Implements [FIPS 203, Algorithm 13 (K-PKE.KeyGen), L19]
46
44
*
47
45
**************************************************/
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 )
50
49
{
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 );
54
53
}
55
54
55
+
56
56
/*************************************************
57
- * Name: mlk_unpack_pk
57
+ * Name: mlk_indcpa_parse_pk
58
58
*
59
59
* Description: De-serialize public key from a byte array;
60
60
* approximate inverse of mlk_pack_pk
@@ -69,11 +69,13 @@ static void mlk_pack_pk(uint8_t r[MLKEM_INDCPA_PUBLICKEYBYTES], mlk_polyvec *pk,
69
69
* Implements [FIPS 203, Algorithm 14 (K-PKE.Encrypt), L2-3]
70
70
*
71
71
**************************************************/
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 ])
74
75
{
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 );
77
79
78
80
/* NOTE: If a modulus check was conducted on the PK, we know at this
79
81
* 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],
82
84
}
83
85
84
86
/*************************************************
85
- * Name: mlk_pack_sk
87
+ * Name: mlk_indcpa_marshal_sk
86
88
*
87
89
* Description: Serialize the secret key
88
90
*
@@ -94,14 +96,16 @@ static void mlk_unpack_pk(mlk_polyvec *pk, uint8_t seed[MLKEM_SYMBYTES],
94
96
* Implements [FIPS 203, Algorithm 13 (K-PKE.KeyGen), L20]
95
97
*
96
98
**************************************************/
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 )
98
102
{
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 );
101
105
}
102
106
103
107
/*************************************************
104
- * Name: mlk_unpack_sk
108
+ * Name: mlk_indcpa_parse_sk
105
109
*
106
110
* Description: De-serialize the secret key; inverse of mlk_pack_sk
107
111
*
@@ -114,10 +118,11 @@ static void mlk_pack_sk(uint8_t r[MLKEM_INDCPA_SECRETKEYBYTES], mlk_polyvec *sk)
114
118
* Implements [FIPS 203, Algorithm 15 (K-PKE.Decrypt), L5]
115
119
*
116
120
**************************************************/
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 ])
119
124
{
120
- mlk_polyvec_frombytes (sk , packedsk );
125
+ mlk_polyvec_frombytes (& sks -> skpv , sk );
121
126
}
122
127
123
128
/*************************************************
@@ -179,6 +184,24 @@ __contract__(
179
184
ensures (array_bound (data , 0 , MLKEM_N , 0 , MLKEM_Q ))) { ((void )data ); }
180
185
#endif /* MLK_USE_NATIVE_NTT_CUSTOM_ORDER */
181
186
187
+ static void transpose_matrix (mlk_polyvec a [MLKEM_K ])
188
+ {
189
+ unsigned int i , j , k ;
190
+ int16_t t ;
191
+ for (i = 0 ; i < MLKEM_K ; i ++ )
192
+ {
193
+ for (j = i + 1 ; j < MLKEM_K ; j ++ )
194
+ {
195
+ for (k = 0 ; k < MLKEM_N ; k ++ )
196
+ {
197
+ t = a [i ].vec [j ].coeffs [k ];
198
+ a [i ].vec [j ].coeffs [k ] = a [j ].vec [i ].coeffs [k ];
199
+ a [j ].vec [i ].coeffs [k ] = t ;
200
+ }
201
+ }
202
+ }
203
+ }
204
+
182
205
/* Reference: `gen_matrix()` in the reference implementation.
183
206
* - We use a special subroutine to generate 4 polynomials
184
207
* at a time, to be able to leverage batched Keccak-f1600
@@ -332,14 +355,14 @@ __contract__(
332
355
* - We include buffer zeroization.
333
356
*/
334
357
MLK_INTERNAL_API
335
- void mlk_indcpa_keypair_derand (uint8_t pk [ MLKEM_INDCPA_PUBLICKEYBYTES ] ,
336
- uint8_t sk [ MLKEM_INDCPA_SECRETKEYBYTES ] ,
358
+ void mlk_indcpa_keypair_derand (mlk_indcpa_public_key * pk ,
359
+ mlk_indcpa_secret_key * sk ,
337
360
const uint8_t coins [MLKEM_SYMBYTES ])
338
361
{
339
362
MLK_ALIGN uint8_t buf [2 * MLKEM_SYMBYTES ];
340
363
const uint8_t * publicseed = buf ;
341
364
const uint8_t * noiseseed = buf + MLKEM_SYMBYTES ;
342
- mlk_polyvec a [ MLKEM_K ], e , pkpv , skpv ;
365
+ mlk_polyvec e ;
343
366
mlk_polyvec_mulcache skpv_cache ;
344
367
345
368
MLK_ALIGN uint8_t coins_with_domain_separator [MLKEM_SYMBYTES + 1 ];
@@ -357,51 +380,54 @@ void mlk_indcpa_keypair_derand(uint8_t pk[MLKEM_INDCPA_PUBLICKEYBYTES],
357
380
*/
358
381
MLK_CT_TESTING_DECLASSIFY (publicseed , MLKEM_SYMBYTES );
359
382
360
- mlk_gen_matrix (a , publicseed , 0 /* no transpose */ );
383
+ mlk_gen_matrix (pk -> at , publicseed , 0 /* no transpose */ );
361
384
362
385
#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 );
386
+ mlk_poly_getnoise_eta1_4x (sk -> skpv .vec + 0 , sk -> skpv .vec + 1 , e .vec + 0 ,
387
+ e . vec + 1 , noiseseed , 0 , 1 , 2 , 3 );
365
388
#elif MLKEM_K == 3
366
389
/*
367
390
* Only the first three output buffers are needed.
368
391
* The laster parameter is a dummy that's overwritten later.
369
392
*/
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 */ );
393
+ mlk_poly_getnoise_eta1_4x (sk -> skpv .vec + 0 , sk -> skpv .vec + 1 ,
394
+ sk -> skpv . vec + 2 , pk -> pkpv .vec + 0 /* irrelevant */ ,
395
+ noiseseed , 0 , 1 , 2 , 0xFF /* irrelevant */ );
373
396
/* Same here */
374
397
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 */ );
398
+ pk -> pkpv .vec + 0 /* irrelevant */ , noiseseed , 3 , 4 ,
399
+ 5 , 0xFF /* irrelevant */ );
377
400
#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 );
401
+ mlk_poly_getnoise_eta1_4x (sk -> skpv .vec + 0 , sk -> skpv .vec + 1 ,
402
+ sk -> skpv .vec + 2 , sk -> skpv .vec + 3 , noiseseed , 0 , 1 ,
403
+ 2 , 3 );
380
404
mlk_poly_getnoise_eta1_4x (e .vec + 0 , e .vec + 1 , e .vec + 2 , e .vec + 3 ,
381
405
noiseseed , 4 , 5 , 6 , 7 );
382
406
#endif
383
407
384
- mlk_polyvec_ntt (& skpv );
408
+ mlk_polyvec_ntt (& sk -> skpv );
385
409
mlk_polyvec_ntt (& e );
386
410
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 );
411
+ mlk_polyvec_mulcache_compute (& skpv_cache , & sk -> skpv );
412
+ mlk_matvec_mul (& pk -> pkpv , pk -> at , & sk -> skpv , & skpv_cache );
413
+ mlk_polyvec_tomont (& pk -> pkpv );
414
+
415
+ mlk_polyvec_add (& pk -> pkpv , & e );
416
+ mlk_polyvec_reduce (& pk -> pkpv );
417
+ mlk_polyvec_reduce (& sk -> skpv );
418
+ memcpy (pk -> seed , publicseed , MLKEM_SYMBYTES );
419
+ /**
420
+ * TODO: We can eliminate this by moving the transpose into the matvec_mul
421
+ * Then we can also eliminate the flag from the from the gen_matrix function
422
+ */
423
+ transpose_matrix (pk -> at );
394
424
395
- mlk_pack_sk (sk , & skpv );
396
- mlk_pack_pk (pk , & pkpv , publicseed );
397
425
398
426
/* Specification: Partially implements
399
427
* [FIPS 203, Section 3.3, Destruction of intermediate values] */
400
428
mlk_zeroize (buf , sizeof (buf ));
401
429
mlk_zeroize (coins_with_domain_separator , sizeof (coins_with_domain_separator ));
402
- mlk_zeroize (a , sizeof (a ));
403
430
mlk_zeroize (& e , sizeof (e ));
404
- mlk_zeroize (& skpv , sizeof (skpv ));
405
431
mlk_zeroize (& skpv_cache , sizeof (skpv_cache ));
406
432
}
407
433
@@ -416,27 +442,14 @@ void mlk_indcpa_keypair_derand(uint8_t pk[MLKEM_INDCPA_PUBLICKEYBYTES],
416
442
MLK_INTERNAL_API
417
443
void mlk_indcpa_enc (uint8_t c [MLKEM_INDCPA_BYTES ],
418
444
const uint8_t m [MLKEM_INDCPA_MSGBYTES ],
419
- const uint8_t pk [ MLKEM_INDCPA_PUBLICKEYBYTES ] ,
445
+ const mlk_indcpa_public_key * pk ,
420
446
const uint8_t coins [MLKEM_SYMBYTES ])
421
447
{
422
- MLK_ALIGN uint8_t seed [MLKEM_SYMBYTES ];
423
- mlk_polyvec sp , pkpv , ep , at [MLKEM_K ], b ;
448
+ mlk_polyvec sp , ep , b ;
424
449
mlk_poly v , k , epp ;
425
450
mlk_polyvec_mulcache sp_cache ;
426
-
427
- mlk_unpack_pk (& pkpv , seed , pk );
428
451
mlk_poly_frommsg (& k , m );
429
452
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
-
440
453
#if MLKEM_K == 2
441
454
mlk_poly_getnoise_eta1122_4x (sp .vec + 0 , sp .vec + 1 , ep .vec + 0 , ep .vec + 1 ,
442
455
coins , 0 , 1 , 2 , 3 );
@@ -462,8 +475,8 @@ void mlk_indcpa_enc(uint8_t c[MLKEM_INDCPA_BYTES],
462
475
mlk_polyvec_ntt (& sp );
463
476
464
477
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 );
478
+ mlk_matvec_mul (& b , pk -> at , & sp , & sp_cache );
479
+ mlk_polyvec_basemul_acc_montgomery_cached (& v , & pk -> pkpv , & sp , & sp_cache );
467
480
468
481
mlk_polyvec_invntt_tomont (& b );
469
482
mlk_poly_invntt_tomont (& v );
@@ -479,12 +492,10 @@ void mlk_indcpa_enc(uint8_t c[MLKEM_INDCPA_BYTES],
479
492
480
493
/* Specification: Partially implements
481
494
* [FIPS 203, Section 3.3, Destruction of intermediate values] */
482
- mlk_zeroize (seed , sizeof (seed ));
483
495
mlk_zeroize (& sp , sizeof (sp ));
484
496
mlk_zeroize (& sp_cache , sizeof (sp_cache ));
485
497
mlk_zeroize (& b , sizeof (b ));
486
498
mlk_zeroize (& v , sizeof (v ));
487
- mlk_zeroize (at , sizeof (at ));
488
499
mlk_zeroize (& k , sizeof (k ));
489
500
mlk_zeroize (& ep , sizeof (ep ));
490
501
mlk_zeroize (& epp , sizeof (epp ));
@@ -496,18 +507,17 @@ void mlk_indcpa_enc(uint8_t c[MLKEM_INDCPA_BYTES],
496
507
MLK_INTERNAL_API
497
508
void mlk_indcpa_dec (uint8_t m [MLKEM_INDCPA_MSGBYTES ],
498
509
const uint8_t c [MLKEM_INDCPA_BYTES ],
499
- const uint8_t sk [ MLKEM_INDCPA_SECRETKEYBYTES ] )
510
+ const mlk_indcpa_secret_key * sk )
500
511
{
501
- mlk_polyvec b , skpv ;
512
+ mlk_polyvec b ;
502
513
mlk_poly v , sb ;
503
514
mlk_polyvec_mulcache b_cache ;
504
515
505
516
mlk_unpack_ciphertext (& b , & v , c );
506
- mlk_unpack_sk (& skpv , sk );
507
517
508
518
mlk_polyvec_ntt (& b );
509
519
mlk_polyvec_mulcache_compute (& b_cache , & b );
510
- mlk_polyvec_basemul_acc_montgomery_cached (& sb , & skpv , & b , & b_cache );
520
+ mlk_polyvec_basemul_acc_montgomery_cached (& sb , & sk -> skpv , & b , & b_cache );
511
521
mlk_poly_invntt_tomont (& sb );
512
522
513
523
mlk_poly_sub (& v , & sb );
@@ -517,7 +527,6 @@ void mlk_indcpa_dec(uint8_t m[MLKEM_INDCPA_MSGBYTES],
517
527
518
528
/* Specification: Partially implements
519
529
* [FIPS 203, Section 3.3, Destruction of intermediate values] */
520
- mlk_zeroize (& skpv , sizeof (skpv ));
521
530
mlk_zeroize (& b , sizeof (b ));
522
531
mlk_zeroize (& b_cache , sizeof (b_cache ));
523
532
mlk_zeroize (& v , sizeof (v ));
@@ -526,9 +535,7 @@ void mlk_indcpa_dec(uint8_t m[MLKEM_INDCPA_MSGBYTES],
526
535
527
536
/* To facilitate single-compilation-unit (SCU) builds, undefine all macros.
528
537
* Don't modify by hand -- this is auto-generated by scripts/autogen. */
529
- #undef mlk_pack_pk
530
538
#undef mlk_unpack_pk
531
- #undef mlk_pack_sk
532
539
#undef mlk_unpack_sk
533
540
#undef mlk_pack_ciphertext
534
541
#undef mlk_unpack_ciphertext
0 commit comments