github.com/cloudflare/circl@v1.5.0/sign/internal/dilithium/poly.go (about) 1 package dilithium 2 3 // An element of our base ring R which are polynomials over Z_q modulo 4 // the equation Xᴺ = -1, where q=2²³ - 2¹³ + 1 and N=256. 5 // 6 // Coefficients aren't always reduced. See Normalize(). 7 type Poly [N]uint32 8 9 // Reduces each of the coefficients to <2q. 10 func (p *Poly) reduceLe2QGeneric() { 11 for i := uint(0); i < N; i++ { 12 p[i] = ReduceLe2Q(p[i]) 13 } 14 } 15 16 // Reduce each of the coefficients to <q. 17 func (p *Poly) normalizeGeneric() { 18 for i := uint(0); i < N; i++ { 19 p[i] = modQ(p[i]) 20 } 21 } 22 23 // Normalize the coefficients in this polynomial assuming they are already 24 // bounded by 2q. 25 func (p *Poly) normalizeAssumingLe2QGeneric() { 26 for i := 0; i < N; i++ { 27 p[i] = le2qModQ(p[i]) 28 } 29 } 30 31 // Sets p to a + b. Does not normalize polynomials. 32 func (p *Poly) addGeneric(a, b *Poly) { 33 for i := uint(0); i < N; i++ { 34 p[i] = a[i] + b[i] 35 } 36 } 37 38 // Sets p to a - b. 39 // 40 // Warning: assumes coefficients of b are less than 2q. 41 func (p *Poly) subGeneric(a, b *Poly) { 42 for i := uint(0); i < N; i++ { 43 p[i] = a[i] + (2*Q - b[i]) 44 } 45 } 46 47 // Checks whether the "supnorm" (see sec 2.1 of the spec) of p is equal 48 // or greater than the given bound. 49 // 50 // Requires the coefficients of p to be normalized. 51 func (p *Poly) exceedsGeneric(bound uint32) bool { 52 // Note that we are allowed to leak which coefficients break the bound, 53 // but not their sign. 54 for i := 0; i < N; i++ { 55 // The central. reps. of {0, 1, ..., (Q-1)/2, (Q+1)/2, ..., Q-1} 56 // are given by {0, 1, ..., (Q-1)/2, -(Q-1)/2, ..., -1} 57 // so their norms are {0, 1, ..., (Q-1)/2, (Q-1)/2, ..., 1}. 58 // We'll compute them in a different way though. 59 60 // Sets x to {(Q-1)/2, (Q-3)/2, ..., 0, -1, ..., -(Q-1)/2} 61 x := int32((Q-1)/2) - int32(p[i]) 62 // Sets x to {(Q-1)/2, (Q-3)/2, ..., 0, 0, ..., (Q-3)/2} 63 x ^= (x >> 31) 64 // Sets x to {0, 1, ..., (Q-1)/2, (Q-1)/2, ..., 1} 65 x = int32((Q-1)/2) - x 66 if uint32(x) >= bound { 67 return true 68 } 69 } 70 return false 71 } 72 73 // Splits p into p1 and p0 such that [i]p1 * 2ᴰ + [i]p0 = [i]p 74 // with -2ᴰ⁻¹ < [i]p0 ≤ 2ᴰ⁻¹. Returns p0 + Q and p1. 75 // 76 // Requires the coefficients of p to be normalized. 77 func (p *Poly) Power2Round(p0PlusQ, p1 *Poly) { 78 for i := 0; i < N; i++ { 79 p0PlusQ[i], p1[i] = power2round(p[i]) 80 } 81 } 82 83 // Sets p to the polynomial whose coefficients are the pointwise multiplication 84 // of those of a and b. The coefficients of p are bounded by 2q. 85 // 86 // Assumes a and b are in Montgomery form and that the pointwise product 87 // of each coefficient is below 2³² q. 88 func (p *Poly) mulHatGeneric(a, b *Poly) { 89 for i := 0; i < N; i++ { 90 p[i] = montReduceLe2Q(uint64(a[i]) * uint64(b[i])) 91 } 92 } 93 94 // Sets p to 2ᵈ q without reducing. 95 // 96 // So it requires the coefficients of p to be less than 2³²⁻ᴰ. 97 func (p *Poly) mulBy2toDGeneric(q *Poly) { 98 for i := 0; i < N; i++ { 99 p[i] = q[i] << D 100 } 101 }