git.sr.ht/~pingoo/stdx@v0.0.0-20240218134121-094174641f6e/crypto/chacha/hchacha20_generic.go (about) 1 package chacha 2 3 import ( 4 "encoding/binary" 5 "math/bits" 6 ) 7 8 // calls to binary.LittleEndian.Uint32 and quarterRound are inlined 9 func hChaCha20Generic(out *[32]byte, nonce *[16]byte, key *[32]byte) { 10 x0, x1, x2, x3 := chachaConstants[0], chachaConstants[1], chachaConstants[2], chachaConstants[3] 11 x4 := binary.LittleEndian.Uint32(key[0:4]) 12 x5 := binary.LittleEndian.Uint32(key[4:8]) 13 x6 := binary.LittleEndian.Uint32(key[8:12]) 14 x7 := binary.LittleEndian.Uint32(key[12:16]) 15 x8 := binary.LittleEndian.Uint32(key[16:20]) 16 x9 := binary.LittleEndian.Uint32(key[20:24]) 17 x10 := binary.LittleEndian.Uint32(key[24:28]) 18 x11 := binary.LittleEndian.Uint32(key[28:32]) 19 x12 := binary.LittleEndian.Uint32(nonce[0:4]) 20 x13 := binary.LittleEndian.Uint32(nonce[4:8]) 21 x14 := binary.LittleEndian.Uint32(nonce[8:12]) 22 x15 := binary.LittleEndian.Uint32(nonce[12:16]) 23 24 for i := 0; i < 10; i++ { 25 // Diagonal round. 26 x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12) 27 x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13) 28 x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14) 29 x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15) 30 31 // Column round. 32 x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15) 33 x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12) 34 x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13) 35 x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14) 36 } 37 38 // _ = out[31] // bounds check elimination hint 39 binary.LittleEndian.PutUint32(out[0:4], x0) 40 binary.LittleEndian.PutUint32(out[4:8], x1) 41 binary.LittleEndian.PutUint32(out[8:12], x2) 42 binary.LittleEndian.PutUint32(out[12:16], x3) 43 binary.LittleEndian.PutUint32(out[16:20], x12) 44 binary.LittleEndian.PutUint32(out[20:24], x13) 45 binary.LittleEndian.PutUint32(out[24:28], x14) 46 binary.LittleEndian.PutUint32(out[28:32], x15) 47 } 48 49 func quarterRound(a, b, c, d uint32) (uint32, uint32, uint32, uint32) { 50 a += b 51 d ^= a 52 d = bits.RotateLeft32(d, 16) 53 c += d 54 b ^= c 55 b = bits.RotateLeft32(b, 12) 56 a += b 57 d ^= a 58 d = bits.RotateLeft32(d, 8) 59 c += d 60 b ^= c 61 b = bits.RotateLeft32(b, 7) 62 return a, b, c, d 63 }