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  }