2019-08-22 09:42:54 +08:00
|
|
|
/*
|
|
|
|
* Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
|
|
|
* this file except in compliance with the License. You can obtain a copy
|
|
|
|
* in the file LICENSE in the source distribution or at
|
|
|
|
* https://www.openssl.org/source/license.html
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* IBM S390X support for AES modes ecb, cbc, ofb, cfb, ctr.
|
|
|
|
* This file is included by cipher_aes_hw.c
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "s390x_arch.h"
|
|
|
|
|
|
|
|
#define s390x_aes_cbc_initkey cipher_hw_aes_initkey
|
|
|
|
#define s390x_aes_cfb1_initkey cipher_hw_aes_initkey
|
|
|
|
#define s390x_aes_ctr_initkey cipher_hw_aes_initkey
|
|
|
|
#define s390x_aes_cbc_cipher_hw cipher_hw_generic_cbc
|
|
|
|
#define s390x_aes_cfb1_cipher_hw cipher_hw_generic_cfb1
|
|
|
|
#define s390x_aes_ctr_cipher_hw cipher_hw_generic_ctr
|
|
|
|
|
2019-08-27 17:22:42 +08:00
|
|
|
#define S390X_aes_128_ofb128_CAPABLE S390X_aes_128_ofb_CAPABLE
|
|
|
|
#define S390X_aes_192_ofb128_CAPABLE S390X_aes_192_ofb_CAPABLE
|
|
|
|
#define S390X_aes_256_ofb128_CAPABLE S390X_aes_256_ofb_CAPABLE
|
|
|
|
#define S390X_aes_128_cfb128_CAPABLE S390X_aes_128_cfb_CAPABLE
|
|
|
|
#define S390X_aes_192_cfb128_CAPABLE S390X_aes_192_cfb_CAPABLE
|
|
|
|
#define S390X_aes_256_cfb128_CAPABLE S390X_aes_256_cfb_CAPABLE
|
|
|
|
|
2019-08-22 09:42:54 +08:00
|
|
|
static int s390x_aes_ecb_initkey(PROV_CIPHER_CTX *dat,
|
|
|
|
const unsigned char *key, size_t keylen)
|
|
|
|
{
|
|
|
|
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
|
|
|
|
|
|
|
|
adat->plat.s390x.fc = S390X_AES_FC(keylen);
|
|
|
|
if (!dat->enc)
|
|
|
|
adat->plat.s390x.fc |= S390X_DECRYPT;
|
|
|
|
|
|
|
|
memcpy(adat->plat.s390x.param.km.k, key, keylen);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int s390x_aes_ecb_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out,
|
|
|
|
const unsigned char *in, size_t len)
|
|
|
|
{
|
|
|
|
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
|
|
|
|
|
|
|
|
s390x_km(in, len, out, adat->plat.s390x.fc, &adat->plat.s390x.param.km);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2019-08-27 17:22:42 +08:00
|
|
|
static int s390x_aes_ofb128_initkey(PROV_CIPHER_CTX *dat,
|
|
|
|
const unsigned char *key, size_t keylen)
|
2019-08-22 09:42:54 +08:00
|
|
|
{
|
|
|
|
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
|
|
|
|
|
2019-09-19 02:43:02 +08:00
|
|
|
memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen);
|
2019-08-22 09:42:54 +08:00
|
|
|
memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen);
|
|
|
|
adat->plat.s390x.fc = S390X_AES_FC(keylen);
|
|
|
|
adat->plat.s390x.res = 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2019-08-27 17:22:42 +08:00
|
|
|
static int s390x_aes_ofb128_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out,
|
|
|
|
const unsigned char *in, size_t len)
|
2019-08-22 09:42:54 +08:00
|
|
|
{
|
|
|
|
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
|
|
|
|
int n = adat->plat.s390x.res;
|
|
|
|
int rem;
|
|
|
|
|
|
|
|
while (n && len) {
|
|
|
|
*out = *in ^ adat->plat.s390x.param.kmo_kmf.cv[n];
|
|
|
|
n = (n + 1) & 0xf;
|
|
|
|
--len;
|
|
|
|
++in;
|
|
|
|
++out;
|
|
|
|
}
|
|
|
|
|
|
|
|
rem = len & 0xf;
|
|
|
|
|
|
|
|
len &= ~(size_t)0xf;
|
|
|
|
if (len) {
|
|
|
|
s390x_kmo(in, len, out, adat->plat.s390x.fc,
|
|
|
|
&adat->plat.s390x.param.kmo_kmf);
|
|
|
|
|
|
|
|
out += len;
|
|
|
|
in += len;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rem) {
|
|
|
|
s390x_km(adat->plat.s390x.param.kmo_kmf.cv, 16,
|
|
|
|
adat->plat.s390x.param.kmo_kmf.cv, adat->plat.s390x.fc,
|
|
|
|
adat->plat.s390x.param.kmo_kmf.k);
|
|
|
|
|
|
|
|
while (rem--) {
|
|
|
|
out[n] = in[n] ^ adat->plat.s390x.param.kmo_kmf.cv[n];
|
|
|
|
++n;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
adat->plat.s390x.res = n;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2019-08-27 17:22:42 +08:00
|
|
|
static int s390x_aes_cfb128_initkey(PROV_CIPHER_CTX *dat,
|
|
|
|
const unsigned char *key, size_t keylen)
|
2019-08-22 09:42:54 +08:00
|
|
|
{
|
|
|
|
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
|
|
|
|
|
|
|
|
adat->plat.s390x.fc = S390X_AES_FC(keylen);
|
|
|
|
adat->plat.s390x.fc |= 16 << 24; /* 16 bytes cipher feedback */
|
|
|
|
if (!dat->enc)
|
|
|
|
adat->plat.s390x.fc |= S390X_DECRYPT;
|
|
|
|
|
|
|
|
adat->plat.s390x.res = 0;
|
2019-09-19 02:43:02 +08:00
|
|
|
memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen);
|
2019-08-22 09:42:54 +08:00
|
|
|
memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2019-08-27 17:22:42 +08:00
|
|
|
static int s390x_aes_cfb128_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out,
|
|
|
|
const unsigned char *in, size_t len)
|
2019-08-22 09:42:54 +08:00
|
|
|
{
|
|
|
|
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
|
|
|
|
int n = adat->plat.s390x.res;
|
|
|
|
int rem;
|
|
|
|
unsigned char tmp;
|
|
|
|
|
|
|
|
while (n && len) {
|
|
|
|
tmp = *in;
|
|
|
|
*out = adat->plat.s390x.param.kmo_kmf.cv[n] ^ tmp;
|
|
|
|
adat->plat.s390x.param.kmo_kmf.cv[n] = dat->enc ? *out : tmp;
|
|
|
|
n = (n + 1) & 0xf;
|
|
|
|
--len;
|
|
|
|
++in;
|
|
|
|
++out;
|
|
|
|
}
|
|
|
|
|
|
|
|
rem = len & 0xf;
|
|
|
|
|
|
|
|
len &= ~(size_t)0xf;
|
|
|
|
if (len) {
|
|
|
|
s390x_kmf(in, len, out, adat->plat.s390x.fc,
|
|
|
|
&adat->plat.s390x.param.kmo_kmf);
|
|
|
|
|
|
|
|
out += len;
|
|
|
|
in += len;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rem) {
|
|
|
|
s390x_km(adat->plat.s390x.param.kmo_kmf.cv, 16,
|
|
|
|
adat->plat.s390x.param.kmo_kmf.cv,
|
|
|
|
S390X_AES_FC(dat->keylen), adat->plat.s390x.param.kmo_kmf.k);
|
|
|
|
|
|
|
|
while (rem--) {
|
|
|
|
tmp = in[n];
|
|
|
|
out[n] = adat->plat.s390x.param.kmo_kmf.cv[n] ^ tmp;
|
|
|
|
adat->plat.s390x.param.kmo_kmf.cv[n] = dat->enc ? out[n] : tmp;
|
|
|
|
++n;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
adat->plat.s390x.res = n;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int s390x_aes_cfb8_initkey(PROV_CIPHER_CTX *dat,
|
|
|
|
const unsigned char *key, size_t keylen)
|
|
|
|
{
|
|
|
|
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
|
|
|
|
|
|
|
|
adat->plat.s390x.fc = S390X_AES_FC(keylen);
|
|
|
|
adat->plat.s390x.fc |= 1 << 24; /* 1 byte cipher feedback */
|
|
|
|
if (!dat->enc)
|
|
|
|
adat->plat.s390x.fc |= S390X_DECRYPT;
|
|
|
|
|
2019-09-19 02:43:02 +08:00
|
|
|
memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen);
|
2019-08-22 09:42:54 +08:00
|
|
|
memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int s390x_aes_cfb8_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out,
|
|
|
|
const unsigned char *in, size_t len)
|
|
|
|
{
|
|
|
|
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
|
|
|
|
|
|
|
|
s390x_kmf(in, len, out, adat->plat.s390x.fc,
|
|
|
|
&adat->plat.s390x.param.kmo_kmf);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define PROV_CIPHER_HW_declare(mode) \
|
|
|
|
static const PROV_CIPHER_HW s390x_aes_##mode = { \
|
|
|
|
s390x_aes_##mode##_initkey, \
|
|
|
|
s390x_aes_##mode##_cipher_hw \
|
2019-11-18 11:13:05 +08:00
|
|
|
cipher_hw_aes_copyctx \
|
2019-08-22 09:42:54 +08:00
|
|
|
};
|
|
|
|
#define PROV_CIPHER_HW_select(mode) \
|
|
|
|
if ((keybits == 128 && S390X_aes_128_##mode##_CAPABLE) \
|
|
|
|
|| (keybits == 192 && S390X_aes_192_##mode##_CAPABLE) \
|
|
|
|
|| (keybits == 256 && S390X_aes_256_##mode##_CAPABLE)) \
|
|
|
|
return &s390x_aes_##mode;
|
|
|
|
|