aes.go 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. // Copyright (c) 2017 Yawning Angel <yawning at schwanenlied dot me>
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining
  4. // a copy of this software and associated documentation files (the
  5. // "Software"), to deal in the Software without restriction, including
  6. // without limitation the rights to use, copy, modify, merge, publish,
  7. // distribute, sublicense, and/or sell copies of the Software, and to
  8. // permit persons to whom the Software is furnished to do so, subject to
  9. // the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be
  12. // included in all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  15. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  16. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  17. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  18. // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  19. // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  20. // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21. // SOFTWARE.
  22. // Package bsaes is a pure-Go bitsliced constant time AES implementation.
  23. package bsaes
  24. import (
  25. "crypto/aes"
  26. "crypto/cipher"
  27. "errors"
  28. "math"
  29. "runtime"
  30. "git.schwanenlied.me/yawning/bsaes.git/ct32"
  31. "git.schwanenlied.me/yawning/bsaes.git/ct64"
  32. )
  33. var (
  34. useCryptoAES = false
  35. ctor = ct64.NewCipher
  36. )
  37. type resetAble interface {
  38. Reset()
  39. }
  40. // NewCipher creates and returns a new cipher.Block. The key argument should
  41. // be the AES key, either 16, 24, or 32 bytes to select AES-128, AES-192, or
  42. // AES-256.
  43. func NewCipher(key []byte) (cipher.Block, error) {
  44. switch len(key) {
  45. case 16, 24, 32:
  46. default:
  47. return nil, errors.New("aes: Invalid key size")
  48. }
  49. if useCryptoAES {
  50. return aes.NewCipher(key)
  51. }
  52. blk := ctor(key)
  53. r := blk.(resetAble)
  54. runtime.SetFinalizer(r, (resetAble).Reset)
  55. return blk, nil
  56. }
  57. // UsingRuntime returns true iff this package is falling through to the
  58. // runtime's implementation due to hardware support for constant time
  59. // operation on the current system.
  60. func UsingRuntime() bool {
  61. return useCryptoAES
  62. }
  63. func init() {
  64. // Fucking appengine doesn't have `unsafe`, so derive based off uintptr.
  65. // It's retarded that this isn't a constant in runtime or something.
  66. maxUintptr := uint64(^uintptr(0))
  67. switch maxUintptr {
  68. case math.MaxUint32:
  69. ctor = ct32.NewCipher
  70. case math.MaxUint64:
  71. ctor = ct64.NewCipher
  72. default:
  73. panic("bsaes: unsupported architecture")
  74. }
  75. useCryptoAES = isCryptoAESSafe()
  76. }