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/subtle" 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//go:noescape 34func cryptBlocks(c code, key, dst, src *byte, length int) 35 36func newCipher(key []byte) (cipher.Block, error) { 37 // The aesCipherAsm type implements the cbcEncAble, cbcDecAble, 38 // ctrAble and gcmAble interfaces. We therefore need to check 39 // for all the features required to implement these modes. 40 // Keep in sync with crypto/tls/common.go. 41 if !(cpu.S390X.HasAES && cpu.S390X.HasAESCBC && cpu.S390X.HasAESCTR && (cpu.S390X.HasGHASH || cpu.S390X.HasAESGCM)) { 42 return newCipherGeneric(key) 43 } 44 45 var function code 46 switch len(key) { 47 case 128 / 8: 48 function = aes128 49 case 192 / 8: 50 function = aes192 51 case 256 / 8: 52 function = aes256 53 default: 54 return nil, KeySizeError(len(key)) 55 } 56 57 var c aesCipherAsm 58 c.function = function 59 c.key = c.storage[:len(key)] 60 copy(c.key, key) 61 return &c, nil 62} 63 64func (c *aesCipherAsm) BlockSize() int { return BlockSize } 65 66func (c *aesCipherAsm) Encrypt(dst, src []byte) { 67 if len(src) < BlockSize { 68 panic("crypto/aes: input not full block") 69 } 70 if len(dst) < BlockSize { 71 panic("crypto/aes: output not full block") 72 } 73 if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { 74 panic("crypto/aes: invalid buffer overlap") 75 } 76 cryptBlocks(c.function, &c.key[0], &dst[0], &src[0], BlockSize) 77} 78 79func (c *aesCipherAsm) Decrypt(dst, src []byte) { 80 if len(src) < BlockSize { 81 panic("crypto/aes: input not full block") 82 } 83 if len(dst) < BlockSize { 84 panic("crypto/aes: output not full block") 85 } 86 if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { 87 panic("crypto/aes: invalid buffer overlap") 88 } 89 // The decrypt function code is equal to the function code + 128. 90 cryptBlocks(c.function+128, &c.key[0], &dst[0], &src[0], BlockSize) 91} 92 93// expandKey is used by BenchmarkExpand. cipher message (KM) does not need key 94// expansion so there is no assembly equivalent. 95func expandKey(key []byte, enc, dec []uint32) { 96 expandKeyGo(key, enc, dec) 97} 98