github.com/cloudflare/circl@v1.5.0/sign/internal/dilithium/pack.go (about)

     1  package dilithium
     2  
     3  // Sets p to the polynomial whose coefficients are less than 1024 encoded
     4  // into buf (which must be of size PolyT1Size).
     5  //
     6  // p will be normalized.
     7  func (p *Poly) UnpackT1(buf []byte) {
     8  	j := 0
     9  	for i := 0; i < PolyT1Size; i += 5 {
    10  		p[j] = (uint32(buf[i]) | (uint32(buf[i+1]) << 8)) & 0x3ff
    11  		p[j+1] = (uint32(buf[i+1]>>2) | (uint32(buf[i+2]) << 6)) & 0x3ff
    12  		p[j+2] = (uint32(buf[i+2]>>4) | (uint32(buf[i+3]) << 4)) & 0x3ff
    13  		p[j+3] = (uint32(buf[i+3]>>6) | (uint32(buf[i+4]) << 2)) & 0x3ff
    14  		j += 4
    15  	}
    16  }
    17  
    18  // Writes p whose coefficients are in (-2ᵈ⁻¹, 2ᵈ⁻¹] into buf which
    19  // has to be of length at least PolyT0Size.
    20  //
    21  // Assumes that the coefficients are not normalized, but lie in the
    22  // range (q-2ᵈ⁻¹, q+2ᵈ⁻¹].
    23  func (p *Poly) PackT0(buf []byte) {
    24  	j := 0
    25  	for i := 0; i < PolyT0Size; i += 13 {
    26  		p0 := Q + (1 << (D - 1)) - p[j]
    27  		p1 := Q + (1 << (D - 1)) - p[j+1]
    28  		p2 := Q + (1 << (D - 1)) - p[j+2]
    29  		p3 := Q + (1 << (D - 1)) - p[j+3]
    30  		p4 := Q + (1 << (D - 1)) - p[j+4]
    31  		p5 := Q + (1 << (D - 1)) - p[j+5]
    32  		p6 := Q + (1 << (D - 1)) - p[j+6]
    33  		p7 := Q + (1 << (D - 1)) - p[j+7]
    34  
    35  		buf[i] = byte(p0 >> 0)
    36  		buf[i+1] = byte(p0>>8) | byte(p1<<5)
    37  		buf[i+2] = byte(p1 >> 3)
    38  		buf[i+3] = byte(p1>>11) | byte(p2<<2)
    39  		buf[i+4] = byte(p2>>6) | byte(p3<<7)
    40  		buf[i+5] = byte(p3 >> 1)
    41  		buf[i+6] = byte(p3>>9) | byte(p4<<4)
    42  		buf[i+7] = byte(p4 >> 4)
    43  		buf[i+8] = byte(p4>>12) | byte(p5<<1)
    44  		buf[i+9] = byte(p5>>7) | byte(p6<<6)
    45  		buf[i+10] = byte(p6 >> 2)
    46  		buf[i+11] = byte(p6>>10) | byte(p7<<3)
    47  		buf[i+12] = byte(p7 >> 5)
    48  		j += 8
    49  	}
    50  }
    51  
    52  // Sets p to the polynomial packed into buf by PackT0.
    53  //
    54  // The coefficients of p will not be normalized, but will lie
    55  // in (-2ᵈ⁻¹, 2ᵈ⁻¹].
    56  func (p *Poly) UnpackT0(buf []byte) {
    57  	j := 0
    58  	for i := 0; i < PolyT0Size; i += 13 {
    59  		p[j] = Q + (1 << (D - 1)) - ((uint32(buf[i]) |
    60  			(uint32(buf[i+1]) << 8)) & 0x1fff)
    61  		p[j+1] = Q + (1 << (D - 1)) - (((uint32(buf[i+1]) >> 5) |
    62  			(uint32(buf[i+2]) << 3) |
    63  			(uint32(buf[i+3]) << 11)) & 0x1fff)
    64  		p[j+2] = Q + (1 << (D - 1)) - (((uint32(buf[i+3]) >> 2) |
    65  			(uint32(buf[i+4]) << 6)) & 0x1fff)
    66  		p[j+3] = Q + (1 << (D - 1)) - (((uint32(buf[i+4]) >> 7) |
    67  			(uint32(buf[i+5]) << 1) |
    68  			(uint32(buf[i+6]) << 9)) & 0x1fff)
    69  		p[j+4] = Q + (1 << (D - 1)) - (((uint32(buf[i+6]) >> 4) |
    70  			(uint32(buf[i+7]) << 4) |
    71  			(uint32(buf[i+8]) << 12)) & 0x1fff)
    72  		p[j+5] = Q + (1 << (D - 1)) - (((uint32(buf[i+8]) >> 1) |
    73  			(uint32(buf[i+9]) << 7)) & 0x1fff)
    74  		p[j+6] = Q + (1 << (D - 1)) - (((uint32(buf[i+9]) >> 6) |
    75  			(uint32(buf[i+10]) << 2) |
    76  			(uint32(buf[i+11]) << 10)) & 0x1fff)
    77  		p[j+7] = Q + (1 << (D - 1)) - ((uint32(buf[i+11]) >> 3) |
    78  			(uint32(buf[i+12]) << 5))
    79  
    80  		j += 8
    81  	}
    82  }
    83  
    84  // Writes p whose coefficients are less than 1024 into buf, which must be
    85  // of size at least PolyT1Size .
    86  //
    87  // Assumes coefficients of p are normalized.
    88  func (p *Poly) PackT1(buf []byte) {
    89  	j := 0
    90  	for i := 0; i < PolyT1Size; i += 5 {
    91  		buf[i] = byte(p[j])
    92  		buf[i+1] = byte(p[j]>>8) | byte(p[j+1]<<2)
    93  		buf[i+2] = byte(p[j+1]>>6) | byte(p[j+2]<<4)
    94  		buf[i+3] = byte(p[j+2]>>4) | byte(p[j+3]<<6)
    95  		buf[i+4] = byte(p[j+3] >> 2)
    96  		j += 4
    97  	}
    98  }
    99  
   100  // Writes p whose coefficients are in [0, 16) to buf, which must be of
   101  // length N/2.
   102  func (p *Poly) packLe16Generic(buf []byte) {
   103  	j := 0
   104  	for i := 0; i < PolyLe16Size; i++ {
   105  		buf[i] = byte(p[j]) | byte(p[j+1]<<4)
   106  		j += 2
   107  	}
   108  }
   109  
   110  // Writes p with 60 non-zero coefficients {-1,1} to buf, which must have
   111  // length 40.
   112  func (p *Poly) PackB60(buf []byte) {
   113  	// We start with a mask of the non-zero positions of p (which is 32 bytes)
   114  	// and then append 60 packed bits, where a one indicates a negative
   115  	// coefficients.
   116  	var signs uint64
   117  	mask := uint64(1)
   118  	for i := 0; i < 32; i++ {
   119  		buf[i] = 0
   120  		for j := 0; j < 8; j++ {
   121  			if p[8*i+j] != 0 {
   122  				buf[i] |= 1 << uint(j)
   123  				if p[8*i+j] == Q-1 {
   124  					signs |= mask
   125  				}
   126  				mask <<= 1
   127  			}
   128  		}
   129  	}
   130  	for i := uint64(0); i < 8; i++ {
   131  		buf[i+32] = uint8(signs >> (8 * i))
   132  	}
   133  }
   134  
   135  // UnpackB60 sets p to the polynomial packed into buf with Poly.PackB60().
   136  //
   137  // Returns whether unpacking was successful.
   138  func (p *Poly) UnpackB60(buf []byte) bool {
   139  	*p = Poly{} // zero p
   140  	signs := (uint64(buf[32]) | (uint64(buf[33]) << 8) |
   141  		(uint64(buf[34]) << 16) | (uint64(buf[35]) << 24) |
   142  		(uint64(buf[36]) << 32) | (uint64(buf[37]) << 40) |
   143  		(uint64(buf[38]) << 48) | (uint64(buf[39]) << 56))
   144  	if signs>>60 != 0 {
   145  		return false // ensure unused bits are zero for strong unforgeability
   146  	}
   147  
   148  	for i := 0; i < 32; i++ {
   149  		for j := 0; j < 8; j++ {
   150  			if (buf[i]>>uint(j))&1 == 1 {
   151  				p[8*i+j] = 1
   152  				// Note 1 ^ (1 | (Q-1)) = Q-1 and (-1)&x = x
   153  				p[8*i+j] ^= uint32(-(signs & 1)) & (1 | (Q - 1))
   154  				signs >>= 1
   155  			}
   156  		}
   157  	}
   158  
   159  	return true
   160  }