@@ -23,19 +23,36 @@ void polyvec_matrix_expand(polyvecl mat[MLDSA_K],
23
23
MLD_ALIGN uint8_t seed_ext [4 ][MLD_ALIGN_UP (MLDSA_SEEDBYTES + 2 )];
24
24
25
25
for (j = 0 ; j < 4 ; j ++ )
26
+ __loop__ (
27
+ assigns (j , object_whole (seed_ext ))
28
+ invariant (j <= 4 )
29
+ )
26
30
{
27
31
memcpy (seed_ext [j ], rho , MLDSA_SEEDBYTES );
28
32
}
29
-
30
33
/* Sample 4 matrix entries a time. */
31
34
for (i = 0 ; i < (MLDSA_K * MLDSA_L / 4 ) * 4 ; i += 4 )
35
+ __loop__ (
36
+ assigns (i , j , object_whole (seed_ext ), memory_slice (mat , MLDSA_K * sizeof (polyvecl )))
37
+ invariant (i <= (MLDSA_K * MLDSA_L / 4 ) * 4 && i % 4 == 0 )
38
+ /* vectors 0 .. i / MLDSA_L are completely sampled */
39
+ invariant (forall (k1 , 0 , i / MLDSA_L , forall (l1 , 0 , MLDSA_L ,
40
+ array_bound (mat [k1 ].vec [l1 ].coeffs , 0 , MLDSA_N , 0 , MLDSA_Q ))))
41
+ /* last vector is sampled up to i % MLDSA_L */
42
+ invariant (forall (k2 , i / MLDSA_L , i / MLDSA_L + 1 , forall (l2 , 0 , i % MLDSA_L ,
43
+ array_bound (mat [k2 ].vec [l2 ].coeffs , 0 , MLDSA_N , 0 , MLDSA_Q ))))
44
+ )
32
45
{
33
- uint8_t x , y ;
46
+ poly tmpvec [ 4 ] ;
34
47
35
48
for (j = 0 ; j < 4 ; j ++ )
49
+ __loop__ (
50
+ assigns (j , object_whole (seed_ext ))
51
+ invariant (j <= 4 )
52
+ )
36
53
{
37
- x = (i + j ) / MLDSA_L ;
38
- y = (i + j ) % MLDSA_L ;
54
+ uint8_t x = (i + j ) / MLDSA_L ;
55
+ uint8_t y = (i + j ) % MLDSA_L ;
39
56
40
57
seed_ext [j ][MLDSA_SEEDBYTES + 0 ] = y ;
41
58
seed_ext [j ][MLDSA_SEEDBYTES + 1 ] = x ;
@@ -48,20 +65,43 @@ void polyvec_matrix_expand(polyvecl mat[MLDSA_K],
48
65
* does not introduce any padding here. Need to refactor the data type to
49
66
* polymat as in mlkem-native.
50
67
*/
51
- poly_uniform_4x (& mat [(i ) / MLDSA_L ].vec [(i ) % MLDSA_L ], seed_ext );
68
+
69
+ /* Full struct assignment from local variables to simplify proof */
70
+ /* TODO: eliminate once CBMC resolves
71
+ * https://github.com/diffblue/cbmc/issues/8617 */
72
+ poly_uniform_4x (tmpvec , seed_ext );
73
+ mat [i / MLDSA_L ].vec [i % MLDSA_L ] = tmpvec [0 ];
74
+ mat [(i + 1 ) / MLDSA_L ].vec [(i + 1 ) % MLDSA_L ] = tmpvec [1 ];
75
+ mat [(i + 2 ) / MLDSA_L ].vec [(i + 2 ) % MLDSA_L ] = tmpvec [2 ];
76
+ mat [(i + 3 ) / MLDSA_L ].vec [(i + 3 ) % MLDSA_L ] = tmpvec [3 ];
52
77
}
53
78
54
79
/* For MLDSA_K=6, MLDSA_L=5, process the last two entries individually */
55
80
while (i < MLDSA_K * MLDSA_L )
81
+ __loop__ (
82
+ assigns (i , object_whole (seed_ext ), memory_slice (mat , MLDSA_K * sizeof (polyvecl )))
83
+ invariant (i <= MLDSA_K * MLDSA_L )
84
+ /* vectors 0 .. i / MLDSA_L are completely sampled */
85
+ invariant (forall (k1 , 0 , i / MLDSA_L , forall (l1 , 0 , MLDSA_L ,
86
+ array_bound (mat [k1 ].vec [l1 ].coeffs , 0 , MLDSA_N , 0 , MLDSA_Q ))))
87
+ /* last vector is sampled up to i % MLDSA_L */
88
+ invariant (forall (k2 , i / MLDSA_L , i / MLDSA_L + 1 , forall (l2 , 0 , i % MLDSA_L ,
89
+ array_bound (mat [k2 ].vec [l2 ].coeffs , 0 , MLDSA_N , 0 , MLDSA_Q ))))
90
+ )
56
91
{
57
- uint8_t x , y ;
58
- x = i / MLDSA_L ;
59
- y = i % MLDSA_L ;
92
+ poly tmp ;
93
+ uint8_t x = i / MLDSA_L ;
94
+ uint8_t y = i % MLDSA_L ;
60
95
61
96
seed_ext [0 ][MLDSA_SEEDBYTES + 0 ] = y ;
62
97
seed_ext [0 ][MLDSA_SEEDBYTES + 1 ] = x ;
63
98
64
- poly_uniform (& mat [i / MLDSA_L ].vec [i % MLDSA_L ], seed_ext [0 ]);
99
+
100
+ /* Full struct assignment from local variables to simplify proof */
101
+ /* TODO: eliminate once CBMC resolves
102
+ * https://github.com/diffblue/cbmc/issues/8617 */
103
+ poly_uniform (& tmp , seed_ext [0 ]);
104
+ mat [i / MLDSA_L ].vec [i % MLDSA_L ] = tmp ;
65
105
66
106
i ++ ;
67
107
}
0 commit comments