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