github.com/cloudflare/circl@v1.5.0/kem/frodo/frodo640shake/util.go (about)

     1  package frodo640shake
     2  
     3  func add(out *nbarByNbarU16, lhs *nbarByNbarU16, rhs *nbarByNbarU16) {
     4  	for i := 0; i < len(out); i++ {
     5  		out[i] = (lhs[i] + rhs[i]) & logQMask
     6  	}
     7  }
     8  
     9  func sub(out *nbarByNbarU16, lhs *nbarByNbarU16, rhs *nbarByNbarU16) {
    10  	for i := 0; i < len(out); i++ {
    11  		out[i] = (lhs[i] - rhs[i]) & logQMask
    12  	}
    13  }
    14  
    15  func pack(out []byte, in []uint16) {
    16  	j := 0
    17  	for i := 0; (i * 8) < len(in); i++ {
    18  		in0 := in[i*8] & logQMask
    19  		in1 := in[(i*8)+1] & logQMask
    20  		in2 := in[(i*8)+2] & logQMask
    21  		in3 := in[(i*8)+3] & logQMask
    22  		in4 := in[(i*8)+4] & logQMask
    23  		in5 := in[(i*8)+5] & logQMask
    24  		in6 := in[(i*8)+6] & logQMask
    25  		in7 := in[(i*8)+7] & logQMask
    26  
    27  		out[j] |= byte(in0 >> 7)
    28  		out[j+1] = (byte(in0&0x7F) << 1) | byte(in1>>14)
    29  
    30  		out[j+2] = byte(in1 >> 6)
    31  		out[j+3] = (byte(in1&0x3F) << 2) | byte(in2>>13)
    32  
    33  		out[j+4] = byte(in2 >> 5)
    34  		out[j+5] = (byte(in2&0x1F) << 3) | byte(in3>>12)
    35  
    36  		out[j+6] = byte(in3 >> 4)
    37  		out[j+7] = (byte(in3&0x0F) << 4) | byte(in4>>11)
    38  
    39  		out[j+8] = byte(in4 >> 3)
    40  		out[j+9] = (byte(in4&0x07) << 5) | byte(in5>>10)
    41  
    42  		out[j+10] = byte(in5 >> 2)
    43  		out[j+11] = (byte(in5&0x03) << 6) | byte(in6>>9)
    44  
    45  		out[j+12] = byte(in6 >> 1)
    46  		out[j+13] = (byte(in6&0x01) << 7) | byte(in7>>8)
    47  
    48  		out[j+14] = byte(in7)
    49  		j += 15
    50  	}
    51  }
    52  
    53  func unpack(out []uint16, in []byte) {
    54  	j := 0
    55  	for i := 0; (i * 15) < len(in); i++ {
    56  		in0 := in[i*15]
    57  		in1 := in[(i*15)+1]
    58  		in2 := in[(i*15)+2]
    59  		in3 := in[(i*15)+3]
    60  		in4 := in[(i*15)+4]
    61  		in5 := in[(i*15)+5]
    62  		in6 := in[(i*15)+6]
    63  		in7 := in[(i*15)+7]
    64  		in8 := in[(i*15)+8]
    65  		in9 := in[(i*15)+9]
    66  		in10 := in[(i*15)+10]
    67  		in11 := in[(i*15)+11]
    68  		in12 := in[(i*15)+12]
    69  		in13 := in[(i*15)+13]
    70  		in14 := in[(i*15)+14]
    71  
    72  		out[j] = (uint16(in0) << 7) | (uint16(in1&0xFE) >> 1)
    73  		out[j+1] = (uint16(in1&0x1) << 14) | (uint16(in2) << 6) | (uint16(in3&0xFC) >> 2)
    74  
    75  		out[j+2] = (uint16(in3&0x03) << 13) | (uint16(in4) << 5) | (uint16(in5&0xF8) >> 3)
    76  		out[j+3] = (uint16(in5&0x07) << 12) | (uint16(in6) << 4) | (uint16(in7&0xF0) >> 4)
    77  
    78  		out[j+4] = (uint16(in7&0x0F) << 11) | (uint16(in8) << 3) | (uint16(in9&0xE0) >> 5)
    79  		out[j+5] = (uint16(in9&0x1F) << 10) | (uint16(in10) << 2) | (uint16(in11&0xC0) >> 6)
    80  
    81  		out[j+6] = (uint16(in11&0x3F) << 9) | (uint16(in12) << 1) | (uint16(in13&0x80) >> 7)
    82  		out[j+7] = (uint16(in13&0x7F) << 8) | uint16(in14)
    83  		j += 8
    84  	}
    85  }
    86  
    87  func encodeMessage(out *nbarByNbarU16, msg *[messageSize]byte) {
    88  	extractedBitsMask := uint16((1 << extractedBits) - 1)
    89  	outPos := 0
    90  
    91  	for i := 0; (i * 2) < len(msg); i++ {
    92  		in := uint16(msg[i*2]) | (uint16(msg[(i*2)+1]) << 8)
    93  		for j := 0; j < (16 / extractedBits); j++ { // 16 = bit size of out[i]
    94  			out[outPos] = (in & extractedBitsMask) << (logQ - extractedBits)
    95  			outPos++
    96  
    97  			in >>= extractedBits
    98  		}
    99  	}
   100  }
   101  
   102  func decodeMessage(out *[messageSize]byte, msg *nbarByNbarU16) {
   103  	extractedBitsMask := uint16((1 << extractedBits) - 1)
   104  	msgPos := 0
   105  
   106  	for i := 0; i < len(out); i++ {
   107  		for j := 0; j < (8 / extractedBits); j++ {
   108  			temp := (msg[msgPos] & logQMask) + (1 << (logQ - extractedBits - 1))
   109  			temp >>= (logQ - extractedBits)
   110  			temp &= extractedBitsMask
   111  			out[i] |= byte(temp) << (j * extractedBits)
   112  			msgPos++
   113  		}
   114  	}
   115  }
   116  
   117  func mulAddSBPlusE(out *nbarByNbarU16, s []uint16, b *nByNbarU16, e []uint16) {
   118  	// Multiply by s on the left
   119  	// Inputs: b (N x N_BAR), s (N_BAR x N), e (N_BAR x N_BAR)
   120  	// Output: out = s*b + e (N_BAR x N_BAR)
   121  
   122  	for k := 0; k < paramNbar; k++ {
   123  		for i := 0; i < paramNbar; i++ {
   124  			out[k*paramNbar+i] = e[k*paramNbar+i]
   125  			for j := 0; j < paramN; j++ {
   126  				out[k*paramNbar+i] += s[k*paramN+j] * b[j*paramNbar+i]
   127  			}
   128  			out[k*paramNbar+i] = out[k*paramNbar+i] & logQMask
   129  		}
   130  	}
   131  }
   132  
   133  func mulBS(out *nbarByNbarU16, b *nbarByNU16, s *nByNbarU16) {
   134  	for i := 0; i < paramNbar; i++ {
   135  		for j := 0; j < paramNbar; j++ {
   136  			out[i*paramNbar+j] = 0
   137  			for k := 0; k < paramN; k++ {
   138  				out[i*paramNbar+j] += b[i*paramN+k] * s[j*paramN+k]
   139  			}
   140  			out[i*paramNbar+j] = out[i*paramNbar+j] & logQMask
   141  		}
   142  	}
   143  }
   144  
   145  func ctCompareU16(lhs []uint16, rhs []uint16) int {
   146  	// Compare lhs and rhs in constant time.
   147  	// Returns 0 if they are equal, 1 otherwise.
   148  	if len(lhs) != len(rhs) {
   149  		return 1
   150  	}
   151  
   152  	var v uint16
   153  
   154  	for i := range lhs {
   155  		v |= lhs[i] ^ rhs[i]
   156  	}
   157  
   158  	return int((v | -v) >> 15)
   159  }