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 }