You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

183 line
6.5 KiB

  1. // Copyright 2009 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // This Go implementation is derived in part from the reference
  5. // ANSI C implementation, which carries the following notice:
  6. //
  7. // rijndael-alg-fst.c
  8. //
  9. // @version 3.0 (December 2000)
  10. //
  11. // Optimised ANSI C code for the Rijndael cipher (now AES)
  12. //
  13. // @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
  14. // @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
  15. // @author Paulo Barreto <paulo.barreto@terra.com.br>
  16. //
  17. // This code is hereby placed in the public domain.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
  20. // OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  21. // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  22. // ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
  23. // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  24. // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  25. // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  26. // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  27. // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  28. // OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  29. // EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. //
  31. // See FIPS 197 for specification, and see Daemen and Rijmen's Rijndael submission
  32. // for implementation details.
  33. // https://csrc.nist.gov/csrc/media/publications/fips/197/final/documents/fips-197.pdf
  34. // https://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf
  35. package aes
  36. import (
  37. "encoding/binary"
  38. )
  39. // Encrypt one block from src into dst, using the expanded key xk.
  40. func encryptBlockGo(xk []uint32, dst, src []byte) {
  41. _ = src[15] // early bounds check
  42. s0 := binary.BigEndian.Uint32(src[0:4])
  43. s1 := binary.BigEndian.Uint32(src[4:8])
  44. s2 := binary.BigEndian.Uint32(src[8:12])
  45. s3 := binary.BigEndian.Uint32(src[12:16])
  46. // First round just XORs input with key.
  47. s0 ^= xk[0]
  48. s1 ^= xk[1]
  49. s2 ^= xk[2]
  50. s3 ^= xk[3]
  51. // Middle rounds shuffle using tables.
  52. // Number of rounds is set by length of expanded key.
  53. nr := len(xk)/4 - 2 // - 2: one above, one more below
  54. k := 4
  55. var t0, t1, t2, t3 uint32
  56. for r := 0; r < nr; r++ {
  57. t0 = xk[k+0] ^ te0[uint8(s0>>24)] ^ te1[uint8(s1>>16)] ^ te2[uint8(s2>>8)] ^ te3[uint8(s3)]
  58. t1 = xk[k+1] ^ te0[uint8(s1>>24)] ^ te1[uint8(s2>>16)] ^ te2[uint8(s3>>8)] ^ te3[uint8(s0)]
  59. t2 = xk[k+2] ^ te0[uint8(s2>>24)] ^ te1[uint8(s3>>16)] ^ te2[uint8(s0>>8)] ^ te3[uint8(s1)]
  60. t3 = xk[k+3] ^ te0[uint8(s3>>24)] ^ te1[uint8(s0>>16)] ^ te2[uint8(s1>>8)] ^ te3[uint8(s2)]
  61. k += 4
  62. s0, s1, s2, s3 = t0, t1, t2, t3
  63. }
  64. // Last round uses s-box directly and XORs to produce output.
  65. s0 = uint32(sbox0[t0>>24])<<24 | uint32(sbox0[t1>>16&0xff])<<16 | uint32(sbox0[t2>>8&0xff])<<8 | uint32(sbox0[t3&0xff])
  66. s1 = uint32(sbox0[t1>>24])<<24 | uint32(sbox0[t2>>16&0xff])<<16 | uint32(sbox0[t3>>8&0xff])<<8 | uint32(sbox0[t0&0xff])
  67. s2 = uint32(sbox0[t2>>24])<<24 | uint32(sbox0[t3>>16&0xff])<<16 | uint32(sbox0[t0>>8&0xff])<<8 | uint32(sbox0[t1&0xff])
  68. s3 = uint32(sbox0[t3>>24])<<24 | uint32(sbox0[t0>>16&0xff])<<16 | uint32(sbox0[t1>>8&0xff])<<8 | uint32(sbox0[t2&0xff])
  69. s0 ^= xk[k+0]
  70. s1 ^= xk[k+1]
  71. s2 ^= xk[k+2]
  72. s3 ^= xk[k+3]
  73. _ = dst[15] // early bounds check
  74. binary.BigEndian.PutUint32(dst[0:4], s0)
  75. binary.BigEndian.PutUint32(dst[4:8], s1)
  76. binary.BigEndian.PutUint32(dst[8:12], s2)
  77. binary.BigEndian.PutUint32(dst[12:16], s3)
  78. }
  79. // Decrypt one block from src into dst, using the expanded key xk.
  80. func decryptBlockGo(xk []uint32, dst, src []byte) {
  81. _ = src[15] // early bounds check
  82. s0 := binary.BigEndian.Uint32(src[0:4])
  83. s1 := binary.BigEndian.Uint32(src[4:8])
  84. s2 := binary.BigEndian.Uint32(src[8:12])
  85. s3 := binary.BigEndian.Uint32(src[12:16])
  86. // First round just XORs input with key.
  87. s0 ^= xk[0]
  88. s1 ^= xk[1]
  89. s2 ^= xk[2]
  90. s3 ^= xk[3]
  91. // Middle rounds shuffle using tables.
  92. // Number of rounds is set by length of expanded key.
  93. nr := len(xk)/4 - 2 // - 2: one above, one more below
  94. k := 4
  95. var t0, t1, t2, t3 uint32
  96. for r := 0; r < nr; r++ {
  97. t0 = xk[k+0] ^ td0[uint8(s0>>24)] ^ td1[uint8(s3>>16)] ^ td2[uint8(s2>>8)] ^ td3[uint8(s1)]
  98. t1 = xk[k+1] ^ td0[uint8(s1>>24)] ^ td1[uint8(s0>>16)] ^ td2[uint8(s3>>8)] ^ td3[uint8(s2)]
  99. t2 = xk[k+2] ^ td0[uint8(s2>>24)] ^ td1[uint8(s1>>16)] ^ td2[uint8(s0>>8)] ^ td3[uint8(s3)]
  100. t3 = xk[k+3] ^ td0[uint8(s3>>24)] ^ td1[uint8(s2>>16)] ^ td2[uint8(s1>>8)] ^ td3[uint8(s0)]
  101. k += 4
  102. s0, s1, s2, s3 = t0, t1, t2, t3
  103. }
  104. // Last round uses s-box directly and XORs to produce output.
  105. s0 = uint32(sbox1[t0>>24])<<24 | uint32(sbox1[t3>>16&0xff])<<16 | uint32(sbox1[t2>>8&0xff])<<8 | uint32(sbox1[t1&0xff])
  106. s1 = uint32(sbox1[t1>>24])<<24 | uint32(sbox1[t0>>16&0xff])<<16 | uint32(sbox1[t3>>8&0xff])<<8 | uint32(sbox1[t2&0xff])
  107. s2 = uint32(sbox1[t2>>24])<<24 | uint32(sbox1[t1>>16&0xff])<<16 | uint32(sbox1[t0>>8&0xff])<<8 | uint32(sbox1[t3&0xff])
  108. s3 = uint32(sbox1[t3>>24])<<24 | uint32(sbox1[t2>>16&0xff])<<16 | uint32(sbox1[t1>>8&0xff])<<8 | uint32(sbox1[t0&0xff])
  109. s0 ^= xk[k+0]
  110. s1 ^= xk[k+1]
  111. s2 ^= xk[k+2]
  112. s3 ^= xk[k+3]
  113. _ = dst[15] // early bounds check
  114. binary.BigEndian.PutUint32(dst[0:4], s0)
  115. binary.BigEndian.PutUint32(dst[4:8], s1)
  116. binary.BigEndian.PutUint32(dst[8:12], s2)
  117. binary.BigEndian.PutUint32(dst[12:16], s3)
  118. }
  119. // Apply sbox0 to each byte in w.
  120. func subw(w uint32) uint32 {
  121. return uint32(sbox0[w>>24])<<24 |
  122. uint32(sbox0[w>>16&0xff])<<16 |
  123. uint32(sbox0[w>>8&0xff])<<8 |
  124. uint32(sbox0[w&0xff])
  125. }
  126. // Rotate
  127. func rotw(w uint32) uint32 { return w<<8 | w>>24 }
  128. // Key expansion algorithm. See FIPS-197, Figure 11.
  129. // Their rcon[i] is our powx[i-1] << 24.
  130. func expandKeyGo(key []byte, enc, dec []uint32) {
  131. // Encryption key setup.
  132. var i int
  133. nk := len(key) / 4
  134. for i = 0; i < nk; i++ {
  135. enc[i] = binary.BigEndian.Uint32(key[4*i:])
  136. }
  137. for ; i < len(enc); i++ {
  138. t := enc[i-1]
  139. if i%nk == 0 {
  140. t = subw(rotw(t)) ^ (uint32(powx[i/nk-1]) << 24)
  141. } else if nk > 6 && i%nk == 4 {
  142. t = subw(t)
  143. }
  144. enc[i] = enc[i-nk] ^ t
  145. }
  146. // Derive decryption key from encryption key.
  147. // Reverse the 4-word round key sets from enc to produce dec.
  148. // All sets but the first and last get the MixColumn transform applied.
  149. if dec == nil {
  150. return
  151. }
  152. n := len(enc)
  153. for i := 0; i < n; i += 4 {
  154. ei := n - i - 4
  155. for j := 0; j < 4; j++ {
  156. x := enc[ei+j]
  157. if i > 0 && i+4 < n {
  158. x = td0[sbox0[x>>24]] ^ td1[sbox0[x>>16&0xff]] ^ td2[sbox0[x>>8&0xff]] ^ td3[sbox0[x&0xff]]
  159. }
  160. dec[i+j] = x
  161. }
  162. }
  163. }