github.com/emmansun/gmsm@v0.29.1/sm4/block.go (about)

     1  package sm4
     2  
     3  // [GM/T] SM4 GB/T 32907-2016
     4  
     5  import (
     6  	"encoding/binary"
     7  )
     8  
     9  // Encrypt one block from src into dst, using the expanded key xk.
    10  func encryptBlockGo(xk *[rounds]uint32, dst, src []byte) {
    11  	_ = src[15] // early bounds check
    12  
    13  	var b0, b1, b2, b3 uint32
    14  	b0 = binary.BigEndian.Uint32(src[0:4])
    15  	b1 = binary.BigEndian.Uint32(src[4:8])
    16  	b2 = binary.BigEndian.Uint32(src[8:12])
    17  	b3 = binary.BigEndian.Uint32(src[12:16])
    18  
    19  	// First round uses s-box directly and T transformation.
    20  	b0 ^= t(b1 ^ b2 ^ b3 ^ xk[0])
    21  	b1 ^= t(b2 ^ b3 ^ b0 ^ xk[1])
    22  	b2 ^= t(b3 ^ b0 ^ b1 ^ xk[2])
    23  	b3 ^= t(b0 ^ b1 ^ b2 ^ xk[3])
    24  
    25  	// Middle rounds (unroll loop) uses precomputed tables.
    26  	b0 ^= precompute_t(b1 ^ b2 ^ b3 ^ xk[4])
    27  	b1 ^= precompute_t(b2 ^ b3 ^ b0 ^ xk[5])
    28  	b2 ^= precompute_t(b3 ^ b0 ^ b1 ^ xk[6])
    29  	b3 ^= precompute_t(b0 ^ b1 ^ b2 ^ xk[7])
    30  
    31  	b0 ^= precompute_t(b1 ^ b2 ^ b3 ^ xk[8])
    32  	b1 ^= precompute_t(b2 ^ b3 ^ b0 ^ xk[9])
    33  	b2 ^= precompute_t(b3 ^ b0 ^ b1 ^ xk[10])
    34  	b3 ^= precompute_t(b0 ^ b1 ^ b2 ^ xk[11])
    35  
    36  	b0 ^= precompute_t(b1 ^ b2 ^ b3 ^ xk[12])
    37  	b1 ^= precompute_t(b2 ^ b3 ^ b0 ^ xk[13])
    38  	b2 ^= precompute_t(b3 ^ b0 ^ b1 ^ xk[14])
    39  	b3 ^= precompute_t(b0 ^ b1 ^ b2 ^ xk[15])
    40  
    41  	b0 ^= precompute_t(b1 ^ b2 ^ b3 ^ xk[16])
    42  	b1 ^= precompute_t(b2 ^ b3 ^ b0 ^ xk[17])
    43  	b2 ^= precompute_t(b3 ^ b0 ^ b1 ^ xk[18])
    44  	b3 ^= precompute_t(b0 ^ b1 ^ b2 ^ xk[19])
    45  
    46  	b0 ^= precompute_t(b1 ^ b2 ^ b3 ^ xk[20])
    47  	b1 ^= precompute_t(b2 ^ b3 ^ b0 ^ xk[21])
    48  	b2 ^= precompute_t(b3 ^ b0 ^ b1 ^ xk[22])
    49  	b3 ^= precompute_t(b0 ^ b1 ^ b2 ^ xk[23])
    50  
    51  	b0 ^= precompute_t(b1 ^ b2 ^ b3 ^ xk[24])
    52  	b1 ^= precompute_t(b2 ^ b3 ^ b0 ^ xk[25])
    53  	b2 ^= precompute_t(b3 ^ b0 ^ b1 ^ xk[26])
    54  	b3 ^= precompute_t(b0 ^ b1 ^ b2 ^ xk[27])
    55  
    56  	// Last round uses s-box directly and and T transformation to produce output.
    57  	b0 ^= t(b1 ^ b2 ^ b3 ^ xk[28])
    58  	b1 ^= t(b2 ^ b3 ^ b0 ^ xk[29])
    59  	b2 ^= t(b3 ^ b0 ^ b1 ^ xk[30])
    60  	b3 ^= t(b0 ^ b1 ^ b2 ^ xk[31])
    61  
    62  	_ = dst[15] // early bounds check
    63  	binary.BigEndian.PutUint32(dst[0:4], b3)
    64  	binary.BigEndian.PutUint32(dst[4:8], b2)
    65  	binary.BigEndian.PutUint32(dst[8:12], b1)
    66  	binary.BigEndian.PutUint32(dst[12:16], b0)
    67  }
    68  
    69  // Key expansion algorithm.
    70  func expandKeyGo(key []byte, enc, dec *[rounds]uint32) {
    71  	// Encryption key setup.
    72  	key = key[:KeySize]
    73  	var b0, b1, b2, b3 uint32
    74  	b0 = binary.BigEndian.Uint32(key[:4]) ^ fk[0]
    75  	b1 = binary.BigEndian.Uint32(key[4:8]) ^ fk[1]
    76  	b2 = binary.BigEndian.Uint32(key[8:12]) ^ fk[2]
    77  	b3 = binary.BigEndian.Uint32(key[12:16]) ^ fk[3]
    78  
    79  	b0 = b0 ^ t2(b1^b2^b3^ck[0])
    80  	enc[0], dec[31] = b0, b0
    81  	b1 = b1 ^ t2(b2^b3^b0^ck[1])
    82  	enc[1], dec[30] = b1, b1
    83  	b2 = b2 ^ t2(b3^b0^b1^ck[2])
    84  	enc[2], dec[29] = b2, b2
    85  	b3 = b3 ^ t2(b0^b1^b2^ck[3])
    86  	enc[3], dec[28] = b3, b3
    87  
    88  	b0 = b0 ^ t2(b1^b2^b3^ck[4])
    89  	enc[4], dec[27] = b0, b0
    90  	b1 = b1 ^ t2(b2^b3^b0^ck[5])
    91  	enc[5], dec[26] = b1, b1
    92  	b2 = b2 ^ t2(b3^b0^b1^ck[6])
    93  	enc[6], dec[25] = b2, b2
    94  	b3 = b3 ^ t2(b0^b1^b2^ck[7])
    95  	enc[7], dec[24] = b3, b3
    96  
    97  	b0 = b0 ^ t2(b1^b2^b3^ck[8])
    98  	enc[8], dec[23] = b0, b0
    99  	b1 = b1 ^ t2(b2^b3^b0^ck[9])
   100  	enc[9], dec[22] = b1, b1
   101  	b2 = b2 ^ t2(b3^b0^b1^ck[10])
   102  	enc[10], dec[21] = b2, b2
   103  	b3 = b3 ^ t2(b0^b1^b2^ck[11])
   104  	enc[11], dec[20] = b3, b3
   105  
   106  	b0 = b0 ^ t2(b1^b2^b3^ck[12])
   107  	enc[12], dec[19] = b0, b0
   108  	b1 = b1 ^ t2(b2^b3^b0^ck[13])
   109  	enc[13], dec[18] = b1, b1
   110  	b2 = b2 ^ t2(b3^b0^b1^ck[14])
   111  	enc[14], dec[17] = b2, b2
   112  	b3 = b3 ^ t2(b0^b1^b2^ck[15])
   113  	enc[15], dec[16] = b3, b3
   114  
   115  	b0 = b0 ^ t2(b1^b2^b3^ck[16])
   116  	enc[16], dec[15] = b0, b0
   117  	b1 = b1 ^ t2(b2^b3^b0^ck[17])
   118  	enc[17], dec[14] = b1, b1
   119  	b2 = b2 ^ t2(b3^b0^b1^ck[18])
   120  	enc[18], dec[13] = b2, b2
   121  	b3 = b3 ^ t2(b0^b1^b2^ck[19])
   122  	enc[19], dec[12] = b3, b3
   123  
   124  	b0 = b0 ^ t2(b1^b2^b3^ck[20])
   125  	enc[20], dec[11] = b0, b0
   126  	b1 = b1 ^ t2(b2^b3^b0^ck[21])
   127  	enc[21], dec[10] = b1, b1
   128  	b2 = b2 ^ t2(b3^b0^b1^ck[22])
   129  	enc[22], dec[9] = b2, b2
   130  	b3 = b3 ^ t2(b0^b1^b2^ck[23])
   131  	enc[23], dec[8] = b3, b3
   132  
   133  	b0 = b0 ^ t2(b1^b2^b3^ck[24])
   134  	enc[24], dec[7] = b0, b0
   135  	b1 = b1 ^ t2(b2^b3^b0^ck[25])
   136  	enc[25], dec[6] = b1, b1
   137  	b2 = b2 ^ t2(b3^b0^b1^ck[26])
   138  	enc[26], dec[5] = b2, b2
   139  	b3 = b3 ^ t2(b0^b1^b2^ck[27])
   140  	enc[27], dec[4] = b3, b3
   141  
   142  	b0 = b0 ^ t2(b1^b2^b3^ck[28])
   143  	enc[28], dec[3] = b0, b0
   144  	b1 = b1 ^ t2(b2^b3^b0^ck[29])
   145  	enc[29], dec[2] = b1, b1
   146  	b2 = b2 ^ t2(b3^b0^b1^ck[30])
   147  	enc[30], dec[1] = b2, b2
   148  	b3 = b3 ^ t2(b0^b1^b2^ck[31])
   149  	enc[31], dec[0] = b3, b3
   150  }
   151  
   152  // T
   153  func t(in uint32) uint32 {
   154  	var b uint32
   155  
   156  	b = uint32(sbox[in&0xff])
   157  	b |= uint32(sbox[in>>8&0xff]) << 8
   158  	b |= uint32(sbox[in>>16&0xff]) << 16
   159  	b |= uint32(sbox[in>>24&0xff]) << 24
   160  
   161  	// L
   162  	return b ^ (b<<2 | b>>30) ^ (b<<10 | b>>22) ^ (b<<18 | b>>14) ^ (b<<24 | b>>8)
   163  }
   164  
   165  // T'
   166  func t2(in uint32) uint32 {
   167  	var b uint32
   168  
   169  	b = uint32(sbox[in&0xff])
   170  	b |= uint32(sbox[in>>8&0xff]) << 8
   171  	b |= uint32(sbox[in>>16&0xff]) << 16
   172  	b |= uint32(sbox[in>>24&0xff]) << 24
   173  
   174  	// L2
   175  	return b ^ (b<<13 | b>>19) ^ (b<<23 | b>>9)
   176  }
   177  
   178  func precompute_t(in uint32) uint32 {
   179  	return sbox_t0[in>>24&0xff] ^
   180  		sbox_t1[in>>16&0xff] ^
   181  		sbox_t2[in>>8&0xff] ^
   182  		sbox_t3[in&0xff]
   183  }