aes.go 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  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. "math"
  28. "runtime"
  29. "git.schwanenlied.me/yawning/bsaes.git/ct32"
  30. "git.schwanenlied.me/yawning/bsaes.git/ct64"
  31. )
  32. // BlockSize is the AES block size in bytes.
  33. const BlockSize = aes.BlockSize
  34. var (
  35. useCryptoAES = false
  36. ctor = ct64.NewCipher
  37. )
  38. type resetAble interface {
  39. Reset()
  40. }
  41. // NewCipher creates and returns a new cipher.Block. The key argument should
  42. // be the AES key, either 16, 24, or 32 bytes to select AES-128, AES-192, or
  43. // AES-256.
  44. func NewCipher(key []byte) (cipher.Block, error) {
  45. switch len(key) {
  46. case 16, 24, 32:
  47. default:
  48. return nil, aes.KeySizeError(len(key))
  49. }
  50. if useCryptoAES {
  51. return aes.NewCipher(key)
  52. }
  53. blk := ctor(key)
  54. r := blk.(resetAble)
  55. runtime.SetFinalizer(r, (resetAble).Reset)
  56. return blk, nil
  57. }
  58. // UsingRuntime returns true iff this package is falling through to the
  59. // runtime's implementation due to hardware support for constant time
  60. // operation on the current system.
  61. func UsingRuntime() bool {
  62. return useCryptoAES
  63. }
  64. func init() {
  65. // Fucking appengine doesn't have `unsafe`, so derive based off uintptr.
  66. // It's retarded that this isn't a constant in runtime or something.
  67. maxUintptr := uint64(^uintptr(0))
  68. switch maxUintptr {
  69. case math.MaxUint32:
  70. ctor = ct32.NewCipher
  71. case math.MaxUint64:
  72. ctor = ct64.NewCipher
  73. default:
  74. panic("bsaes: unsupported architecture")
  75. }
  76. useCryptoAES = isCryptoAESSafe()
  77. }