/* iv + padding length for iv lengths != 12 */
#define S390X_gcm_ivpadlen(i) ((((i) + 15) >> 4 << 4) + 16)
+/* Additional flag or'ed to fc for decryption */
+#define S390X_gcm_decrypt_flag(ctx) (((ctx)->enc) ? 0 : S390X_DECRYPT)
+
+#define S390X_gcm_fc(A,C) ((A)->plat.s390x.fc | (A)->plat.s390x.hsflag |\
+ S390X_gcm_decrypt_flag((C)))
+
static int s390x_aes_gcm_initkey(PROV_GCM_CTX *ctx,
const unsigned char *key, size_t keylen)
{
ctx->key_set = 1;
memcpy(&actx->plat.s390x.param.kma.k, key, keylen);
actx->plat.s390x.fc = S390X_AES_FC(keylen);
- if (!ctx->enc)
- actx->plat.s390x.fc |= S390X_DECRYPT;
return 1;
}
memcpy(&kma->j0, iv, ivlen);
kma->j0.w[3] = 1;
kma->cv.w = 1;
+ actx->plat.s390x.hsflag = 0;
} else {
unsigned long long ivbits = ivlen << 3;
size_t len = S390X_gcm_ivpadlen(ivlen);
* param.
*/
s390x_kma(iv_zero_pad, len, NULL, 0, NULL, actx->plat.s390x.fc, kma);
- actx->plat.s390x.fc |= S390X_KMA_HS; /* The hash subkey is set */
+ actx->plat.s390x.hsflag = S390X_KMA_HS; /* The hash subkey is set */
/* Copy the 128 bit GHASH result into J0 and clear the tag */
kma->j0.g[0] = kma->t.g[0];
PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx;
S390X_KMA_PARAMS *kma = &actx->plat.s390x.param.kma;
unsigned char out[AES_BLOCK_SIZE];
+ unsigned int fc;
int rc;
kma->taadl <<= 3;
kma->tpcl <<= 3;
+ fc = S390X_gcm_fc(actx, ctx) | S390X_KMA_LAAD | S390X_KMA_LPC;
s390x_kma(actx->plat.s390x.ares, actx->plat.s390x.areslen,
actx->plat.s390x.mres, actx->plat.s390x.mreslen, out,
- actx->plat.s390x.fc | S390X_KMA_LAAD | S390X_KMA_LPC, kma);
+ fc, kma);
/* gctx->mres already returned to the caller */
OPENSSL_cleanse(out, actx->plat.s390x.mreslen);
{
PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx;
S390X_KMA_PARAMS *kma = &actx->plat.s390x.param.kma;
+ unsigned int fc;
int rc;
kma->taadl = aad_len << 3;
kma->tpcl = in_len << 3;
- s390x_kma(aad, aad_len, in, in_len, out,
- actx->plat.s390x.fc | S390X_KMA_LAAD | S390X_KMA_LPC, kma);
+ fc = S390X_gcm_fc(actx, ctx) | S390X_KMA_LAAD | S390X_KMA_LPC;
+ s390x_kma(aad, aad_len, in, in_len, out, fc, kma);
if (ctx->enc) {
memcpy(tag, kma->t.b, taglen);
PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx;
S390X_KMA_PARAMS *kma = &actx->plat.s390x.param.kma;
unsigned long long alen;
+ unsigned int fc;
int n, rem;
/* If already processed pt/ct then error */
}
/* ctx->ares contains a complete block if offset has wrapped around */
if (!n) {
- s390x_kma(actx->plat.s390x.ares, 16, NULL, 0, NULL,
- actx->plat.s390x.fc, kma);
- actx->plat.s390x.fc |= S390X_KMA_HS;
+ fc = S390X_gcm_fc(actx, ctx);
+ s390x_kma(actx->plat.s390x.ares, 16, NULL, 0, NULL, fc, kma);
+ actx->plat.s390x.hsflag = S390X_KMA_HS;
}
actx->plat.s390x.areslen = n;
}
/* Add any remaining 16 byte blocks (128 bit each) */
len &= ~(size_t)0xf;
if (len) {
- s390x_kma(aad, len, NULL, 0, NULL, actx->plat.s390x.fc, kma);
- actx->plat.s390x.fc |= S390X_KMA_HS;
+ fc = S390X_gcm_fc(actx, ctx);
+ s390x_kma(aad, len, NULL, 0, NULL, fc, kma);
+ actx->plat.s390x.hsflag = S390X_KMA_HS;
aad += len;
}
S390X_KMA_PARAMS *kma = &actx->plat.s390x.param.kma;
const unsigned char *inptr;
unsigned long long mlen;
+ unsigned int fc;
union {
unsigned int w[4];
unsigned char b[16];
return 0;
kma->tpcl = mlen;
+ fc = S390X_gcm_fc(actx, ctx) | S390X_KMA_LAAD;
n = actx->plat.s390x.mreslen;
if (n) {
inptr = in;
/* ctx->mres contains a complete block if offset has wrapped around */
if (!n) {
s390x_kma(actx->plat.s390x.ares, actx->plat.s390x.areslen,
- actx->plat.s390x.mres, 16, buf.b,
- actx->plat.s390x.fc | S390X_KMA_LAAD, kma);
- actx->plat.s390x.fc |= S390X_KMA_HS;
+ actx->plat.s390x.mres, 16, buf.b, fc, kma);
+ actx->plat.s390x.hsflag = S390X_KMA_HS;
+ fc |= S390X_KMA_HS;
actx->plat.s390x.areslen = 0;
/* previous call already encrypted/decrypted its remainder,
len &= ~(size_t)0xf;
if (len) {
s390x_kma(actx->plat.s390x.ares, actx->plat.s390x.areslen, in, len, out,
- actx->plat.s390x.fc | S390X_KMA_LAAD, kma);
+ fc, kma);
in += len;
out += len;
- actx->plat.s390x.fc |= S390X_KMA_HS;
+ actx->plat.s390x.hsflag = S390X_KMA_HS;
actx->plat.s390x.areslen = 0;
}
buf.w[2] = kma->j0.w[2];
buf.w[3] = kma->cv.w + 1;
s390x_km(buf.b, 16, actx->plat.s390x.kres,
- actx->plat.s390x.fc & 0x1f, &kma->k);
+ fc & 0x1f, &kma->k);
}
n = actx->plat.s390x.mreslen;
#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
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;
}
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, &adat->plat.s390x.param.km);
+ s390x_km(in, len, out, adat->plat.s390x.fc | modifier,
+ &adat->plat.s390x.param.km);
return 1;
}
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.cv,
+ adat->plat.s390x.fc,
adat->plat.s390x.param.kmo_kmf.k);
while (rem--) {
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;
memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen);
return 1;
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;
len &= ~(size_t)0xf;
if (len) {
- s390x_kmf(in, len, out, adat->plat.s390x.fc,
+ s390x_kmf(in, len, out, adat->plat.s390x.fc | modifier,
&adat->plat.s390x.param.kmo_kmf);
out += 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);
+ S390X_AES_FC(dat->keylen),
+ adat->plat.s390x.param.kmo_kmf.k);
while (rem--) {
tmp = in[n];
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;
-
memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen);
return 1;
}
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,
+ 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;