blob: c8282dbd08a9cdd0d18495c2c7ed3df295490768 [file] [log] [blame]
/*
* Copyright 2001-2021 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"
#include <stdio.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 ossl_cipher_hw_generic_cbc
#define s390x_aes_cfb1_cipher_hw ossl_cipher_hw_generic_cfb1
#define s390x_aes_ctr_cipher_hw ossl_cipher_hw_generic_ctr
#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
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);
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;
unsigned int modifier = adat->base.enc ? 0 : S390X_DECRYPT;
s390x_km(in, len, out, adat->plat.s390x.fc | modifier,
&adat->plat.s390x.param.km);
return 1;
}
static int s390x_aes_ofb128_initkey(PROV_CIPHER_CTX *dat,
const unsigned char *key, size_t keylen)
{
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
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;
}
static int s390x_aes_ofb128_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out,
const unsigned char *in, size_t len)
{
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
int n = adat->plat.s390x.res;
int rem;
memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen);
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;
}
}
memcpy(dat->iv, adat->plat.s390x.param.kmo_kmf.cv, dat->ivlen);
adat->plat.s390x.res = n;
return 1;
}
static int s390x_aes_cfb128_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 |= 16 << 24; /* 16 bytes cipher feedback */
adat->plat.s390x.res = 0;
memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen);
return 1;
}
static int s390x_aes_cfb128_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out,
const unsigned char *in, size_t len)
{
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
unsigned int modifier = adat->base.enc ? 0 : S390X_DECRYPT;
int n = adat->plat.s390x.res;
int rem;
unsigned char tmp;
memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen);
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 | modifier,
&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;
}
}
memcpy(dat->iv, adat->plat.s390x.param.kmo_kmf.cv, dat->ivlen);
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 */
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;
unsigned int modifier = adat->base.enc ? 0 : S390X_DECRYPT;
memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen);
s390x_kmf(in, len, out, adat->plat.s390x.fc | modifier,
&adat->plat.s390x.param.kmo_kmf);
memcpy(dat->iv, adat->plat.s390x.param.kmo_kmf.cv, dat->ivlen);
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, \
cipher_hw_aes_copyctx \
};
#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;