1#![cfg_attr(not(feature = "std"), no_std)]
4
5pub trait Modulus {
7 const Q: u32;
9
10 const N: usize;
12
13 const BARRETT_MU: u128 = 0;
16
17 const BARRETT_K: u32 = 0;
20}
21
22#[derive(Copy, Clone, Debug, Eq, PartialEq)]
28pub enum PostInvNtt {
29 Standard,
32 Montgomery,
35}
36
37pub trait NttModulus: Modulus {
39 const ZETA: u32;
41
42 const ZETAS: &'static [u32];
47
48 const N_INV: u32;
51
52 const MONT_R: u32;
54
55 const NEG_QINV: u32;
57
58 const PSIS: &'static [u32];
63
64 const INV_PSIS: &'static [u32];
68
69 const POST_INVNTT_MODE: PostInvNtt = PostInvNtt::Standard;
74}
75
76#[derive(Clone, Debug)]
78pub struct Kyber256Params;
79
80impl Modulus for Kyber256Params {
81 const Q: u32 = 3329;
82 const N: usize = 256;
83
84 const BARRETT_MU: u128 = 10_569_051_393;
88 const BARRETT_K: u32 = 45;
89}
90
91impl NttModulus for Kyber256Params {
92 const ZETA: u32 = 17; const ZETAS: &'static [u32] = &[];
95 const N_INV: u32 = 2385;
97 const MONT_R: u32 = 1353;
99 const NEG_QINV: u32 = 0x94570CFF;
101
102 const PSIS: &'static [u32] = &[];
104 const INV_PSIS: &'static [u32] = &[];
105
106 const POST_INVNTT_MODE: PostInvNtt = PostInvNtt::Standard;
108}
109
110#[derive(Clone, Debug)]
112pub struct Dilithium2Params;
113
114impl Modulus for Dilithium2Params {
115 const Q: u32 = 8380417; const N: usize = 256;
117
118 const BARRETT_MU: u128 = 4_299_165_187;
122 const BARRETT_K: u32 = 55;
123}
124
125const DILITHIUM_ZETAS: [u32; 255] = [
146 25847, 5771523, 7861508, 237124, 7602457, 7504169, 466468, 1826347, 2353451, 8021166, 6288512,
147 3119733, 5495562, 3111497, 2680103, 2725464, 1024112, 7300517, 3585928, 7830929, 7260833,
148 2619752, 6271868, 6262231, 4520680, 6980856, 5102745, 1757237, 8360995, 4010497, 280005,
149 2706023, 95776, 3077325, 3530437, 6718724, 4788269, 5842901, 3915439, 4519302, 5336701,
150 3574422, 5512770, 3539968, 8079950, 2348700, 7841118, 6681150, 6736599, 3505694, 4558682,
151 3507263, 6239768, 6779997, 3699596, 811944, 531354, 954230, 3881043, 3900724, 5823537, 2071892,
152 5582638, 4450022, 6851714, 4702672, 5339162, 6927966, 3475950, 2176455, 6795196, 7122806,
153 1939314, 4296819, 7380215, 5190273, 5223087, 4747489, 126922, 3412210, 7396998, 2147896,
154 2715295, 5412772, 4686924, 7969390, 5903370, 7709315, 7151892, 8357436, 7072248, 7998430,
155 1349076, 1852771, 6949987, 5037034, 264944, 508951, 3097992, 44288, 7280319, 904516, 3958618,
156 4656075, 8371839, 1653064, 5130689, 2389356, 8169440, 759969, 7063561, 189548, 4827145,
157 3159746, 6529015, 5971092, 8202977, 1315589, 1341330, 1285669, 6795489, 7567685, 6940675,
158 5361315, 4499357, 4751448, 3839961, 2091667, 3407706, 2316500, 3817976, 5037939, 2244091,
159 5933984, 4817955, 266997, 2434439, 7144689, 3513181, 4860065, 4621053, 7183191, 5187039,
160 900702, 1859098, 909542, 819034, 495491, 6767243, 8337157, 7857917, 7725090, 5257975, 2031748,
161 3207046, 4823422, 7855319, 7611795, 4784579, 342297, 286988, 5942594, 4108315, 3437287,
162 5038140, 1735879, 203044, 2842341, 2691481, 5790267, 1265009, 4055324, 1247620, 2486353,
163 1595974, 4613401, 1250494, 2635921, 4832145, 5386378, 1869119, 1903435, 7329447, 7047359,
164 1237275, 5062207, 6950192, 7929317, 1312455, 3306115, 6417775, 7100756, 1917081, 5834105,
165 7005614, 1500165, 777191, 2235880, 3406031, 7838005, 5548557, 6709241, 6533464, 5796124,
166 4656147, 594136, 4603424, 6366809, 2432395, 2454455, 8215696, 1957272, 3369112, 185531,
167 7173032, 5196991, 162844, 1616392, 3014001, 810149, 1652634, 4686184, 6581310, 5341501,
168 3523897, 3866901, 269760, 2213111, 7404533, 1717735, 472078, 7953734, 1723600, 6577327,
169 1910376, 6712985, 7276084, 8119771, 4546524, 5441381, 6144432, 7959518, 6094090, 183443,
170 7403526, 1612842, 4834730, 7826001, 3919660, 8332111, 7018208, 3937738, 1400424, 7534263,
171 1976782,
172];
173
174const DILITHIUM_PSIS: [u32; 256] = [
178 1, 4808194, 3765607, 3761513, 5178923, 5496691, 5234739, 5178987, 7778734, 3542485, 2682288,
179 2129892, 3764867, 7375178, 557458, 7159240, 5010068, 4317364, 2663378, 6705802, 4855975,
180 7946292, 676590, 7044481, 5152541, 1714295, 2453983, 1460718, 7737789, 4795319, 2815639,
181 2283733, 3602218, 3182878, 2740543, 4793971, 5269599, 2101410, 3704823, 1159875, 394148,
182 928749, 1095468, 4874037, 2071829, 4361428, 3241972, 2156050, 3415069, 1759347, 7562881,
183 4805951, 3756790, 6444618, 6663429, 4430364, 5483103, 3192354, 556856, 3870317, 2917338,
184 1853806, 3345963, 1858416, 3073009, 1277625, 5744944, 3852015, 4183372, 5157610, 5258977,
185 8106357, 2508980, 2028118, 1937570, 4564692, 2811291, 5396636, 7270901, 4158088, 1528066,
186 482649, 1148858, 5418153, 7814814, 169688, 2462444, 5046034, 4213992, 4892034, 1987814,
187 5183169, 1736313, 235407, 5130263, 3258457, 5801164, 1787943, 5989328, 6125690, 3482206,
188 4197502, 7080401, 6018354, 7062739, 2461387, 3035980, 621164, 3901472, 7153756, 2925816,
189 3374250, 1356448, 5604662, 2683270, 5601629, 4912752, 2312838, 7727142, 7921254, 348812,
190 8052569, 1011223, 6026202, 4561790, 6458164, 6143691, 1744507, 1753, 6444997, 5720892, 6924527,
191 2660408, 6600190, 8321269, 2772600, 1182243, 87208, 636927, 4415111, 4423672, 6084020, 5095502,
192 4663471, 8352605, 822541, 1009365, 5926272, 6400920, 1596822, 4423473, 4620952, 6695264,
193 4969849, 2678278, 4611469, 4829411, 635956, 8129971, 5925040, 4234153, 6607829, 2192938,
194 6653329, 2387513, 4768667, 8111961, 5199961, 3747250, 2296099, 1239911, 4541938, 3195676,
195 2642980, 1254190, 8368000, 2998219, 141835, 8291116, 2513018, 7025515, 613238, 7070156,
196 6161950, 7921677, 6458423, 4040196, 4908348, 2039144, 6500539, 7561656, 6201452, 6757063,
197 2105286, 6006015, 6346610, 586241, 7200804, 527981, 5637006, 6903432, 1994046, 2491325,
198 6987258, 507927, 7192532, 7655613, 6545891, 5346675, 8041997, 2647994, 3009748, 5767564,
199 4148469, 749577, 4357667, 3980599, 2569011, 6764887, 1723229, 1665318, 2028038, 1163598,
200 5011144, 3994671, 8368538, 7009900, 3020393, 3363542, 214880, 545376, 7609976, 3105558,
201 7277073, 508145, 7826699, 860144, 3430436, 140244, 6866265, 6195333, 3123762, 2358373, 6187330,
202 5365997, 6663603, 2926054, 7987710, 8077412, 3531229, 4405932, 4606686, 1900052, 7598542,
203 1054478, 7648983,
204];
205
206const DILITHIUM_INV_PSIS: [u32; 256] = [
209 1, 3572223, 4618904, 4614810, 3201430, 3145678, 2883726, 3201494, 1221177, 7822959, 1005239,
210 4615550, 6250525, 5698129, 4837932, 601683, 6096684, 5564778, 3585098, 642628, 6919699,
211 5926434, 6666122, 3227876, 1335936, 7703827, 434125, 3524442, 1674615, 5717039, 4063053,
212 3370349, 6522001, 5034454, 6526611, 5463079, 4510100, 7823561, 5188063, 2897314, 3950053,
213 1716988, 1935799, 4623627, 3574466, 817536, 6621070, 4965348, 6224367, 5138445, 4018989,
214 6308588, 3506380, 7284949, 7451668, 7986269, 7220542, 4675594, 6279007, 3110818, 3586446,
215 5639874, 5197539, 4778199, 6635910, 2236726, 1922253, 3818627, 2354215, 7369194, 327848,
216 8031605, 459163, 653275, 6067579, 3467665, 2778788, 5697147, 2775755, 7023969, 5006167,
217 5454601, 1226661, 4478945, 7759253, 5344437, 5919030, 1317678, 2362063, 1300016, 4182915,
218 4898211, 2254727, 2391089, 6592474, 2579253, 5121960, 3250154, 8145010, 6644104, 3197248,
219 6392603, 3488383, 4166425, 3334383, 5917973, 8210729, 565603, 2962264, 7231559, 7897768,
220 6852351, 4222329, 1109516, 2983781, 5569126, 3815725, 6442847, 6352299, 5871437, 274060,
221 3121440, 3222807, 4197045, 4528402, 2635473, 7102792, 5307408, 731434, 7325939, 781875,
222 6480365, 3773731, 3974485, 4849188, 303005, 392707, 5454363, 1716814, 3014420, 2193087,
223 6022044, 5256655, 2185084, 1514152, 8240173, 4949981, 7520273, 553718, 7872272, 1103344,
224 5274859, 770441, 7835041, 8165537, 5016875, 5360024, 1370517, 11879, 4385746, 3369273, 7216819,
225 6352379, 6715099, 6657188, 1615530, 5811406, 4399818, 4022750, 7630840, 4231948, 2612853,
226 5370669, 5732423, 338420, 3033742, 1834526, 724804, 1187885, 7872490, 1393159, 5889092,
227 6386371, 1476985, 2743411, 7852436, 1179613, 7794176, 2033807, 2374402, 6275131, 1623354,
228 2178965, 818761, 1879878, 6341273, 3472069, 4340221, 1921994, 458740, 2218467, 1310261,
229 7767179, 1354892, 5867399, 89301, 8238582, 5382198, 12417, 7126227, 5737437, 5184741, 3838479,
230 7140506, 6084318, 4633167, 3180456, 268456, 3611750, 5992904, 1727088, 6187479, 1772588,
231 4146264, 2455377, 250446, 7744461, 3551006, 3768948, 5702139, 3410568, 1685153, 3759465,
232 3956944, 6783595, 1979497, 2454145, 7371052, 7557876, 27812, 3716946, 3284915, 2296397,
233 3956745, 3965306, 7743490, 8293209, 7198174, 5607817, 59148, 1780227, 5720009, 1455890,
234 2659525, 1935420, 8378664,
235];
236
237#[derive(Clone, Debug)]
239pub struct DilithiumParams;
240
241impl Modulus for DilithiumParams {
242 const Q: u32 = 8380417; const N: usize = 256;
244
245 const BARRETT_MU: u128 = 4_299_165_187;
249 const BARRETT_K: u32 = 55;
250}
251
252impl NttModulus for DilithiumParams {
253 const ZETA: u32 = 1753; const ZETAS: &'static [u32] = &DILITHIUM_ZETAS;
259
260 const N_INV: u32 = 16_382;
265
266 const MONT_R: u32 = 4_193_792;
268
269 const NEG_QINV: u32 = 4_236_238_847;
273
274 const PSIS: &'static [u32] = &DILITHIUM_PSIS;
276 const INV_PSIS: &'static [u32] = &DILITHIUM_INV_PSIS;
277
278 const POST_INVNTT_MODE: PostInvNtt = PostInvNtt::Standard;
280}
281
282#[derive(Clone, Debug)]
285pub struct DilithiumParamsMont;
286
287impl Modulus for DilithiumParamsMont {
288 const Q: u32 = 8380417;
289 const N: usize = 256;
290 const BARRETT_MU: u128 = 4_299_165_187;
291 const BARRETT_K: u32 = 55;
292}
293
294impl NttModulus for DilithiumParamsMont {
295 const ZETA: u32 = 1753;
296 const ZETAS: &'static [u32] = &DILITHIUM_ZETAS;
297 const N_INV: u32 = 16_382;
298 const MONT_R: u32 = 4_193_792;
299 const NEG_QINV: u32 = 4_236_238_847;
300 const PSIS: &'static [u32] = &DILITHIUM_PSIS;
301 const INV_PSIS: &'static [u32] = &DILITHIUM_INV_PSIS;
302
303 const POST_INVNTT_MODE: PostInvNtt = PostInvNtt::Montgomery;
305}
306
307pub fn is_prime(q: u32) -> bool {
310 if q < 2 {
311 return false;
312 }
313 if q == 2 {
314 return true;
315 }
316 if q % 2 == 0 {
317 return false;
318 }
319
320 let sqrt_q = (q as f64).sqrt() as u32;
321 for i in (3..=sqrt_q).step_by(2) {
322 if q % i == 0 {
323 return false;
324 }
325 }
326 true
327}
328
329pub fn is_power_of_two(n: usize) -> bool {
331 n > 0 && (n & (n - 1)) == 0
332}
333
334#[cfg(test)]
335mod tests {
336 use super::*;
337
338 #[test]
339 fn test_kyber_params() {
340 assert_eq!(Kyber256Params::Q, 3329);
341 assert_eq!(Kyber256Params::N, 256);
342 assert!(is_prime(Kyber256Params::Q));
343 assert!(is_power_of_two(Kyber256Params::N));
344 assert_eq!(Kyber256Params::POST_INVNTT_MODE, PostInvNtt::Standard);
345 assert_eq!(Kyber256Params::BARRETT_MU, 10_569_051_393);
346 assert_eq!(Kyber256Params::BARRETT_K, 45);
347 }
348
349 #[test]
350 fn test_dilithium_params() {
351 assert_eq!(Dilithium2Params::Q, 8380417);
352 assert_eq!(Dilithium2Params::N, 256);
353 assert!(is_prime(Dilithium2Params::Q));
354 assert_eq!(Dilithium2Params::BARRETT_MU, 4_299_165_187);
355 assert_eq!(Dilithium2Params::BARRETT_K, 55);
356 }
357
358 #[test]
359 fn test_dilithium_general_params() {
360 assert_eq!(DilithiumParams::Q, 8380417);
361 assert_eq!(DilithiumParams::N, 256);
362 assert!(is_prime(DilithiumParams::Q));
363 assert!(is_power_of_two(DilithiumParams::N));
364 assert_eq!(DilithiumParams::POST_INVNTT_MODE, PostInvNtt::Standard);
366 assert_eq!(DilithiumParams::BARRETT_MU, 4_299_165_187);
367 assert_eq!(DilithiumParams::BARRETT_K, 55);
368 }
369
370 #[test]
371 fn test_dilithium_constant_calculations() {
372 let n_inv_std = 8_347_681u64; let r = DilithiumParams::MONT_R as u64;
378 let q = DilithiumParams::Q as u64;
379 let expected_n_inv = (n_inv_std * r) % q;
380 assert_eq!(expected_n_inv, 16_382);
381 assert_eq!(DilithiumParams::N_INV as u64, expected_n_inv);
382
383 let q_inv: u32 = 58728449; let neg_qinv = (1u64 << 32) - (q_inv as u64);
388 assert_eq!(neg_qinv, 4_236_238_847);
389 assert_eq!(DilithiumParams::NEG_QINV as u64, neg_qinv);
390 }
391
392 #[test]
393 fn test_zetas_in_montgomery_domain() {
394 assert_eq!(DilithiumParams::ZETAS[0], 25_847);
397
398 let zeta_128_std = 4808194u64; let mont_form = (zeta_128_std * DilithiumParams::MONT_R as u64) % DilithiumParams::Q as u64;
401 assert_eq!(mont_form as u32, 25_847);
402 }
403
404 #[test]
405 fn test_twist_factors() {
406 assert_eq!(DilithiumParams::PSIS.len(), 256);
408 assert_eq!(DilithiumParams::INV_PSIS.len(), 256);
409
410 assert_eq!(DilithiumParams::PSIS[0], 1);
412 assert_eq!(DilithiumParams::INV_PSIS[0], 1);
413
414 let q = DilithiumParams::Q as u64;
416 for i in 0..10 {
417 let psi = DilithiumParams::PSIS[i] as u64;
418 let inv_psi = DilithiumParams::INV_PSIS[i] as u64;
419 let product = (psi * inv_psi) % q;
420 assert_eq!(product, 1, "ψ[{}] * ψ^(-1)[{}] should equal 1", i, i);
421 }
422 }
423}