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  }