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