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.
 
 
 

81 lines
2.2 KiB

  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 "encoding/binary"
  7. //go:noescape
  8. func chacha20Poly1305Open(dst []byte, key []uint32, src, ad []byte) bool
  9. //go:noescape
  10. func chacha20Poly1305Seal(dst []byte, key []uint32, src, ad []byte)
  11. //go:noescape
  12. func haveSSSE3() bool
  13. var canUseASM bool
  14. func init() {
  15. canUseASM = haveSSSE3()
  16. }
  17. // setupState writes a ChaCha20 input matrix to state. See
  18. // https://tools.ietf.org/html/rfc7539#section-2.3.
  19. func setupState(state *[16]uint32, key *[32]byte, nonce []byte) {
  20. state[0] = 0x61707865
  21. state[1] = 0x3320646e
  22. state[2] = 0x79622d32
  23. state[3] = 0x6b206574
  24. state[4] = binary.LittleEndian.Uint32(key[:4])
  25. state[5] = binary.LittleEndian.Uint32(key[4:8])
  26. state[6] = binary.LittleEndian.Uint32(key[8:12])
  27. state[7] = binary.LittleEndian.Uint32(key[12:16])
  28. state[8] = binary.LittleEndian.Uint32(key[16:20])
  29. state[9] = binary.LittleEndian.Uint32(key[20:24])
  30. state[10] = binary.LittleEndian.Uint32(key[24:28])
  31. state[11] = binary.LittleEndian.Uint32(key[28:32])
  32. state[12] = 0
  33. state[13] = binary.LittleEndian.Uint32(nonce[:4])
  34. state[14] = binary.LittleEndian.Uint32(nonce[4:8])
  35. state[15] = binary.LittleEndian.Uint32(nonce[8:12])
  36. }
  37. func (c *chacha20poly1305) seal(dst, nonce, plaintext, additionalData []byte) []byte {
  38. if !canUseASM {
  39. return c.sealGeneric(dst, nonce, plaintext, additionalData)
  40. }
  41. var state [16]uint32
  42. setupState(&state, &c.key, nonce)
  43. ret, out := sliceForAppend(dst, len(plaintext)+16)
  44. chacha20Poly1305Seal(out[:], state[:], plaintext, additionalData)
  45. return ret
  46. }
  47. func (c *chacha20poly1305) open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
  48. if !canUseASM {
  49. return c.openGeneric(dst, nonce, ciphertext, additionalData)
  50. }
  51. var state [16]uint32
  52. setupState(&state, &c.key, nonce)
  53. ciphertext = ciphertext[:len(ciphertext)-16]
  54. ret, out := sliceForAppend(dst, len(ciphertext))
  55. if !chacha20Poly1305Open(out, state[:], ciphertext, additionalData) {
  56. for i := range out {
  57. out[i] = 0
  58. }
  59. return nil, errOpen
  60. }
  61. return ret, nil
  62. }