1// Copyright 2016 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 5package aes 6 7import ( 8 "crypto/cipher" 9 "crypto/internal/cipherhw" 10) 11 12type code int 13 14// Function codes for the cipher message family of instructions. 15const ( 16 aes128 code = 18 17 aes192 = 19 18 aes256 = 20 19) 20 21type aesCipherAsm struct { 22 function code // code for cipher message instruction 23 key []byte // key (128, 192 or 256 bytes) 24 storage [256]byte // array backing key slice 25} 26 27// cryptBlocks invokes the cipher message (KM) instruction with 28// the given function code. This is equivalent to AES in ECB 29// mode. The length must be a multiple of BlockSize (16). 30//go:noescape 31func cryptBlocks(c code, key, dst, src *byte, length int) 32 33var useAsm = cipherhw.AESGCMSupport() 34 35func newCipher(key []byte) (cipher.Block, error) { 36 if !useAsm { 37 return newCipherGeneric(key) 38 } 39 40 var function code 41 switch len(key) { 42 case 128 / 8: 43 function = aes128 44 case 192 / 8: 45 function = aes192 46 case 256 / 8: 47 function = aes256 48 default: 49 return nil, KeySizeError(len(key)) 50 } 51 52 var c aesCipherAsm 53 c.function = function 54 c.key = c.storage[:len(key)] 55 copy(c.key, key) 56 return &c, nil 57} 58 59func (c *aesCipherAsm) BlockSize() int { return BlockSize } 60 61func (c *aesCipherAsm) Encrypt(dst, src []byte) { 62 if len(src) < BlockSize { 63 panic("crypto/aes: input not full block") 64 } 65 if len(dst) < BlockSize { 66 panic("crypto/aes: output not full block") 67 } 68 cryptBlocks(c.function, &c.key[0], &dst[0], &src[0], BlockSize) 69} 70 71func (c *aesCipherAsm) Decrypt(dst, src []byte) { 72 if len(src) < BlockSize { 73 panic("crypto/aes: input not full block") 74 } 75 if len(dst) < BlockSize { 76 panic("crypto/aes: output not full block") 77 } 78 // The decrypt function code is equal to the function code + 128. 79 cryptBlocks(c.function+128, &c.key[0], &dst[0], &src[0], BlockSize) 80} 81 82// expandKey is used by BenchmarkExpand. cipher message (KM) does not need key 83// expansion so there is no assembly equivalent. 84func expandKey(key []byte, enc, dec []uint32) { 85 expandKeyGo(key, enc, dec) 86} 87