github.com/mattn/go@v0.0.0-20171011075504-07f7db3ea99f/src/crypto/aes/cipher_amd64.go (about)

     1  // Copyright 2012 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  
     5  package aes
     6  
     7  import (
     8  	"crypto/cipher"
     9  	"crypto/internal/cipherhw"
    10  )
    11  
    12  // defined in asm_amd64.s
    13  func encryptBlockAsm(nr int, xk *uint32, dst, src *byte)
    14  func decryptBlockAsm(nr int, xk *uint32, dst, src *byte)
    15  func expandKeyAsm(nr int, key *byte, enc *uint32, dec *uint32)
    16  
    17  type aesCipherAsm struct {
    18  	aesCipher
    19  }
    20  
    21  var useAsm = cipherhw.AESGCMSupport()
    22  
    23  func newCipher(key []byte) (cipher.Block, error) {
    24  	if !useAsm {
    25  		return newCipherGeneric(key)
    26  	}
    27  	n := len(key) + 28
    28  	c := aesCipherAsm{aesCipher{make([]uint32, n), make([]uint32, n)}}
    29  	rounds := 10
    30  	switch len(key) {
    31  	case 128 / 8:
    32  		rounds = 10
    33  	case 192 / 8:
    34  		rounds = 12
    35  	case 256 / 8:
    36  		rounds = 14
    37  	}
    38  	expandKeyAsm(rounds, &key[0], &c.enc[0], &c.dec[0])
    39  	if hasGCMAsm() {
    40  		return &aesCipherGCM{c}, nil
    41  	}
    42  
    43  	return &c, nil
    44  }
    45  
    46  func (c *aesCipherAsm) BlockSize() int { return BlockSize }
    47  
    48  func (c *aesCipherAsm) Encrypt(dst, src []byte) {
    49  	if len(src) < BlockSize {
    50  		panic("crypto/aes: input not full block")
    51  	}
    52  	if len(dst) < BlockSize {
    53  		panic("crypto/aes: output not full block")
    54  	}
    55  	encryptBlockAsm(len(c.enc)/4-1, &c.enc[0], &dst[0], &src[0])
    56  }
    57  
    58  func (c *aesCipherAsm) Decrypt(dst, src []byte) {
    59  	if len(src) < BlockSize {
    60  		panic("crypto/aes: input not full block")
    61  	}
    62  	if len(dst) < BlockSize {
    63  		panic("crypto/aes: output not full block")
    64  	}
    65  	decryptBlockAsm(len(c.dec)/4-1, &c.dec[0], &dst[0], &src[0])
    66  }
    67  
    68  // expandKey is used by BenchmarkExpand to ensure that the asm implementation
    69  // of key expansion is used for the benchmark when it is available.
    70  func expandKey(key []byte, enc, dec []uint32) {
    71  	if useAsm {
    72  		rounds := 10 // rounds needed for AES128
    73  		switch len(key) {
    74  		case 192 / 8:
    75  			rounds = 12
    76  		case 256 / 8:
    77  			rounds = 14
    78  		}
    79  		expandKeyAsm(rounds, &key[0], &enc[0], &dec[0])
    80  	} else {
    81  		expandKeyGo(key, enc, dec)
    82  	}
    83  }