| // Copyright 2016 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| //go:build !purego |
| |
| package aes |
| |
| import ( |
| "crypto/internal/fips140deps/cpu" |
| "crypto/internal/impl" |
| ) |
| |
| type code int |
| |
| // Function codes for the cipher message family of instructions. |
| const ( |
| aes128 code = 18 |
| aes192 code = 19 |
| aes256 code = 20 |
| ) |
| |
| type block struct { |
| function code // code for cipher message instruction |
| key []byte // key (128, 192 or 256 bits) |
| storage [32]byte // array backing key slice |
| |
| fallback *blockExpanded |
| } |
| |
| // cryptBlocks invokes the cipher message (KM) instruction with |
| // the given function code. This is equivalent to AES in ECB |
| // mode. The length must be a multiple of BlockSize (16). |
| // |
| //go:noescape |
| func cryptBlocks(c code, key, dst, src *byte, length int) |
| |
| var supportsAES = cpu.S390XHasAES && cpu.S390XHasAESCBC |
| |
| func init() { |
| // CP Assist for Cryptographic Functions (CPACF) |
| // https://www.ibm.com/docs/en/zos/3.1.0?topic=icsf-cp-assist-cryptographic-functions-cpacf |
| impl.Register("aes", "CPACF", &supportsAES) |
| } |
| |
| func checkGenericIsExpected() { |
| if supportsAES { |
| panic("crypto/aes: internal error: using generic implementation despite hardware support") |
| } |
| } |
| |
| func newBlock(c *Block, key []byte) *Block { |
| if !supportsAES { |
| c.fallback = &blockExpanded{} |
| newBlockExpanded(c.fallback, key) |
| return c |
| } |
| |
| switch len(key) { |
| case aes128KeySize: |
| c.function = aes128 |
| case aes192KeySize: |
| c.function = aes192 |
| case aes256KeySize: |
| c.function = aes256 |
| } |
| c.key = c.storage[:len(key)] |
| copy(c.key, key) |
| return c |
| } |
| |
| // BlockFunction returns the function code for the block cipher. |
| // It is used by the GCM implementation to invoke the KMA instruction. |
| func BlockFunction(c *Block) int { |
| return int(c.function) |
| } |
| |
| // BlockKey returns the key for the block cipher. |
| // It is used by the GCM implementation to invoke the KMA instruction. |
| func BlockKey(c *Block) []byte { |
| return c.key |
| } |
| |
| func encryptBlock(c *Block, dst, src []byte) { |
| if c.fallback != nil { |
| encryptBlockGeneric(c.fallback, dst, src) |
| } else { |
| cryptBlocks(c.function, &c.key[0], &dst[0], &src[0], BlockSize) |
| } |
| } |
| |
| func decryptBlock(c *Block, dst, src []byte) { |
| if c.fallback != nil { |
| decryptBlockGeneric(c.fallback, dst, src) |
| } else { |
| // The decrypt function code is equal to the function code + 128. |
| cryptBlocks(c.function+128, &c.key[0], &dst[0], &src[0], BlockSize) |
| } |
| } |