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