Home | History | Annotate | Download | only in aes
      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 }
     84