code wiki / (root) / nx_kyber_poly_tomont_wasm.nx

nx_kyber_poly_tomont_wasm.nx source

↩ module page · 61 lines · 1961 B

1// nx_kyber_poly_tomont_wasm.nx -- Convert polynomial to Montgomery form. 2// 3// After polyvec_basemul_acc_montgomery (= nx_kyber_poly_basemul_acc), 4// each coefficient is in the "x * R^{-1} mod q" form because every 5// fqmul multiplied by R^{-1}. poly_tomont multiplies by R^2 mod q 6// (= 1353) and then applies montgomery_reduce, which has the effect of 7// multiplying the polynomial by R -- canceling the R^{-1} factor and 8// restoring CANONICAL representation. 9// 10// Per PQClean's poly_tomont(): 11// const int16_t f = (1ULL << 32) % KYBER_Q; // = 1353 12// for each coef c: c = montgomery_reduce(c * f); 13// 14// Used immediately after basemul_acc inside K-PKE keygen/encrypt to put 15// the accumulated polynomial back into canonical form so it can be added 16// to canonical-form e/e1/e2/mu polynomials without mixing representations. 17// 18// API: 19// nx_kyber_poly_tomont(poly) -> i64 20// 21// license_tier: INDEPENDENT_REDERIVE 22// genealogy_id: international-research-sources/nist/fips_203 23// lineage_id: nishi_kyber_poly_tomont_wasm_q1 24// safe_shift_audit: no 64-bit rotations in this module 25 26const KYBER_Q: i64 = 3329 27const KYBER_QINV: i64 = 62209 28const KYBER_N: i64 = 256 29const KYBER_F: i64 = 1353 // (2^32) mod q 30 31func _pload(p: *u8, i: i64) -> i64 { 32 let lo: i64 = p[i * 2] 33 let hi: i64 = p[i * 2 + 1] 34 let raw: i64 = lo | (hi << 8) 35 if raw >= 32768 { return raw - 65536 } 36 return raw 37} 38 39func _pstore(p: *u8, i: i64, v: i64) -> i64 { 40 var vv: i64 = v 41 if vv < 0 { vv = vv + 65536 } 42 p[i * 2] = vv & 0xff 43 p[i * 2 + 1] = (vv >> 8) & 0xff 44 return 0 45} 46 47func _mont(a: i64) -> i64 { 48 var u: i64 = (a * KYBER_QINV) & 0xffff 49 if u >= 32768 { u = u - 65536 } 50 return (a - u * KYBER_Q) >> 16 51} 52 53func nx_kyber_poly_tomont(poly: *u8) -> i64 { 54 var i: i64 = 0 55 while i < KYBER_N { 56 let c: i64 = _pload(poly, i) 57 _pstore(poly, i, _mont(c * KYBER_F)) 58 i = i + 1 59 } 60 return 0 61}