Commit 46efe0bc authored by Michael Munday's avatar Michael Munday

crypto/aes: add s390x assembly implementation

Adds support for single block encryption using the cipher message
(KM) instruction. KM handles key expansion internally and
therefore it is not done up front when using the assembly
implementation on s390x.

Change-Id: I69954b8ae36d549e1dc40d7acd5a10bedfaaef9c
Reviewed-on: https://go-review.googlesource.com/22194
Run-TryBot: Michael Munday <munday@ca.ibm.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarBill O'Farrell <billotosyr@gmail.com>
Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
parent b57ac333
// 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.
#include "textflag.h"
// func hasAsm() bool
TEXT ·hasAsm(SB),NOSPLIT,$16-1
XOR R0, R0 // set function code to 0 (query)
LA mask-16(SP), R1 // 16-byte stack variable for mask
WORD $0xB92E0024 // cipher message (KM)
// check if bits 18-20 (big endian) are set
MOVD mask-16(SP), R2
MOVD $(0x38<<40), R3
AND R3, R2
CMPBNE R2, R3, notfound
MOVB $1, ret+0(FP)
RET
notfound:
MOVB $0, ret+0(FP)
RET
// func cryptBlocks(function code, key, dst, src *byte, length int)
TEXT ·cryptBlocks(SB),NOSPLIT,$0-40
MOVD key+8(FP), R1
MOVD dst+16(FP), R2
MOVD src+24(FP), R4
MOVD length+32(FP), R5
MOVD function+0(FP), R0
loop:
WORD $0xB92E0024 // cipher message (KM)
BVS loop // branch back if interrupted
XOR R0, R0
RET
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !amd64
// +build !amd64,!s390x
package aes
......
// 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.
package aes
import (
"crypto/cipher"
)
type code int
// Function codes for the cipher message family of instructions.
const (
aes128 code = 18
aes192 = 19
aes256 = 20
)
type aesCipherAsm struct {
function code // code for cipher message instruction
key []byte // key (128, 192 or 256 bytes)
storage [256]byte // array backing key slice
}
// hasAsm reports whether the AES-128, AES-192 and AES-256
// cipher message (KM) function codes are supported.
// Note: this function call is expensive.
func hasAsm() bool
// 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:noesape
func cryptBlocks(c code, key, dst, src *byte, length int)
var useAsm = hasAsm()
func newCipher(key []byte) (cipher.Block, error) {
if !useAsm {
return newCipherGeneric(key)
}
var function code
switch len(key) {
case 128 / 8:
function = aes128
case 192 / 8:
function = aes192
case 256 / 8:
function = aes256
default:
return nil, KeySizeError(len(key))
}
var c aesCipherAsm
c.function = function
c.key = c.storage[:len(key)]
copy(c.key, key)
return &c, nil
}
func (c *aesCipherAsm) BlockSize() int { return BlockSize }
func (c *aesCipherAsm) Encrypt(dst, src []byte) {
if len(src) < BlockSize {
panic("crypto/aes: input not full block")
}
if len(dst) < BlockSize {
panic("crypto/aes: output not full block")
}
cryptBlocks(c.function, &c.key[0], &dst[0], &src[0], BlockSize)
}
func (c *aesCipherAsm) Decrypt(dst, src []byte) {
if len(src) < BlockSize {
panic("crypto/aes: input not full block")
}
if len(dst) < BlockSize {
panic("crypto/aes: output not full block")
}
// The decrypt function code is equal to the function code + 128.
cryptBlocks(c.function+128, &c.key[0], &dst[0], &src[0], BlockSize)
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment