chacha20poly1305_amd64.go 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. // Copyright 2016 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. // +build go1.7,amd64,!gccgo,!appengine
  5. package chacha20poly1305
  6. import (
  7. "encoding/binary"
  8. "golang.org/x/crypto/internal/subtle"
  9. "golang.org/x/sys/cpu"
  10. )
  11. //go:noescape
  12. func chacha20Poly1305Open(dst []byte, key []uint32, src, ad []byte) bool
  13. //go:noescape
  14. func chacha20Poly1305Seal(dst []byte, key []uint32, src, ad []byte)
  15. var (
  16. useAVX2 = cpu.X86.HasAVX2 && cpu.X86.HasBMI2
  17. )
  18. // setupState writes a ChaCha20 input matrix to state. See
  19. // https://tools.ietf.org/html/rfc7539#section-2.3.
  20. func setupState(state *[16]uint32, key *[8]uint32, nonce []byte) {
  21. state[0] = 0x61707865
  22. state[1] = 0x3320646e
  23. state[2] = 0x79622d32
  24. state[3] = 0x6b206574
  25. state[4] = key[0]
  26. state[5] = key[1]
  27. state[6] = key[2]
  28. state[7] = key[3]
  29. state[8] = key[4]
  30. state[9] = key[5]
  31. state[10] = key[6]
  32. state[11] = key[7]
  33. state[12] = 0
  34. state[13] = binary.LittleEndian.Uint32(nonce[:4])
  35. state[14] = binary.LittleEndian.Uint32(nonce[4:8])
  36. state[15] = binary.LittleEndian.Uint32(nonce[8:12])
  37. }
  38. func (c *chacha20poly1305) seal(dst, nonce, plaintext, additionalData []byte) []byte {
  39. if !cpu.X86.HasSSSE3 {
  40. return c.sealGeneric(dst, nonce, plaintext, additionalData)
  41. }
  42. var state [16]uint32
  43. setupState(&state, &c.key, nonce)
  44. ret, out := sliceForAppend(dst, len(plaintext)+16)
  45. if subtle.InexactOverlap(out, plaintext) {
  46. panic("chacha20poly1305: invalid buffer overlap")
  47. }
  48. chacha20Poly1305Seal(out[:], state[:], plaintext, additionalData)
  49. return ret
  50. }
  51. func (c *chacha20poly1305) open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
  52. if !cpu.X86.HasSSSE3 {
  53. return c.openGeneric(dst, nonce, ciphertext, additionalData)
  54. }
  55. var state [16]uint32
  56. setupState(&state, &c.key, nonce)
  57. ciphertext = ciphertext[:len(ciphertext)-16]
  58. ret, out := sliceForAppend(dst, len(ciphertext))
  59. if subtle.InexactOverlap(out, ciphertext) {
  60. panic("chacha20poly1305: invalid buffer overlap")
  61. }
  62. if !chacha20Poly1305Open(out, state[:], ciphertext, additionalData) {
  63. for i := range out {
  64. out[i] = 0
  65. }
  66. return nil, errOpen
  67. }
  68. return ret, nil
  69. }