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