1b077aed3SPierre Pronchery/* 2*e0c4386eSCy Schubert * Copyright 2001-2024 The OpenSSL Project Authors. All Rights Reserved. 3b077aed3SPierre Pronchery * 4b077aed3SPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use 5b077aed3SPierre Pronchery * this file except in compliance with the License. You can obtain a copy 6b077aed3SPierre Pronchery * in the file LICENSE in the source distribution or at 7b077aed3SPierre Pronchery * https://www.openssl.org/source/license.html 8b077aed3SPierre Pronchery */ 9b077aed3SPierre Pronchery 10b077aed3SPierre Pronchery/* 11b077aed3SPierre Pronchery * IBM S390X support for AES modes ecb, cbc, ofb, cfb, ctr. 12b077aed3SPierre Pronchery * This file is included by cipher_aes_hw.c 13b077aed3SPierre Pronchery */ 14b077aed3SPierre Pronchery 15b077aed3SPierre Pronchery#include "s390x_arch.h" 16b077aed3SPierre Pronchery 17b077aed3SPierre Pronchery#include <stdio.h> 18b077aed3SPierre Pronchery 19b077aed3SPierre Pronchery#define s390x_aes_cbc_initkey cipher_hw_aes_initkey 20b077aed3SPierre Pronchery#define s390x_aes_cfb1_initkey cipher_hw_aes_initkey 21b077aed3SPierre Pronchery#define s390x_aes_ctr_initkey cipher_hw_aes_initkey 22b077aed3SPierre Pronchery#define s390x_aes_cbc_cipher_hw ossl_cipher_hw_generic_cbc 23b077aed3SPierre Pronchery#define s390x_aes_cfb1_cipher_hw ossl_cipher_hw_generic_cfb1 24b077aed3SPierre Pronchery#define s390x_aes_ctr_cipher_hw ossl_cipher_hw_generic_ctr 25b077aed3SPierre Pronchery 26b077aed3SPierre Pronchery#define S390X_aes_128_ofb128_CAPABLE S390X_aes_128_ofb_CAPABLE 27b077aed3SPierre Pronchery#define S390X_aes_192_ofb128_CAPABLE S390X_aes_192_ofb_CAPABLE 28b077aed3SPierre Pronchery#define S390X_aes_256_ofb128_CAPABLE S390X_aes_256_ofb_CAPABLE 29b077aed3SPierre Pronchery#define S390X_aes_128_cfb128_CAPABLE S390X_aes_128_cfb_CAPABLE 30b077aed3SPierre Pronchery#define S390X_aes_192_cfb128_CAPABLE S390X_aes_192_cfb_CAPABLE 31b077aed3SPierre Pronchery#define S390X_aes_256_cfb128_CAPABLE S390X_aes_256_cfb_CAPABLE 32b077aed3SPierre Pronchery 33b077aed3SPierre Proncherystatic int s390x_aes_ecb_initkey(PROV_CIPHER_CTX *dat, 34b077aed3SPierre Pronchery const unsigned char *key, size_t keylen) 35b077aed3SPierre Pronchery{ 36b077aed3SPierre Pronchery PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; 37b077aed3SPierre Pronchery 38b077aed3SPierre Pronchery adat->plat.s390x.fc = S390X_AES_FC(keylen); 39b077aed3SPierre Pronchery memcpy(adat->plat.s390x.param.km.k, key, keylen); 40b077aed3SPierre Pronchery return 1; 41b077aed3SPierre Pronchery} 42b077aed3SPierre Pronchery 43b077aed3SPierre Proncherystatic int s390x_aes_ecb_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out, 44b077aed3SPierre Pronchery const unsigned char *in, size_t len) 45b077aed3SPierre Pronchery{ 46b077aed3SPierre Pronchery PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; 47b077aed3SPierre Pronchery unsigned int modifier = adat->base.enc ? 0 : S390X_DECRYPT; 48b077aed3SPierre Pronchery 49b077aed3SPierre Pronchery s390x_km(in, len, out, adat->plat.s390x.fc | modifier, 50b077aed3SPierre Pronchery &adat->plat.s390x.param.km); 51b077aed3SPierre Pronchery return 1; 52b077aed3SPierre Pronchery} 53b077aed3SPierre Pronchery 54b077aed3SPierre Proncherystatic int s390x_aes_ofb128_initkey(PROV_CIPHER_CTX *dat, 55b077aed3SPierre Pronchery const unsigned char *key, size_t keylen) 56b077aed3SPierre Pronchery{ 57b077aed3SPierre Pronchery PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; 58b077aed3SPierre Pronchery 59b077aed3SPierre Pronchery memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen); 60b077aed3SPierre Pronchery adat->plat.s390x.fc = S390X_AES_FC(keylen); 61b077aed3SPierre Pronchery return 1; 62b077aed3SPierre Pronchery} 63b077aed3SPierre Pronchery 64b077aed3SPierre Proncherystatic int s390x_aes_ofb128_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out, 65b077aed3SPierre Pronchery const unsigned char *in, size_t len) 66b077aed3SPierre Pronchery{ 67b077aed3SPierre Pronchery PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; 68*e0c4386eSCy Schubert int n = dat->num; 69b077aed3SPierre Pronchery int rem; 70b077aed3SPierre Pronchery 71b077aed3SPierre Pronchery memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen); 72b077aed3SPierre Pronchery while (n && len) { 73b077aed3SPierre Pronchery *out = *in ^ adat->plat.s390x.param.kmo_kmf.cv[n]; 74b077aed3SPierre Pronchery n = (n + 1) & 0xf; 75b077aed3SPierre Pronchery --len; 76b077aed3SPierre Pronchery ++in; 77b077aed3SPierre Pronchery ++out; 78b077aed3SPierre Pronchery } 79b077aed3SPierre Pronchery 80b077aed3SPierre Pronchery rem = len & 0xf; 81b077aed3SPierre Pronchery 82b077aed3SPierre Pronchery len &= ~(size_t)0xf; 83b077aed3SPierre Pronchery if (len) { 84b077aed3SPierre Pronchery s390x_kmo(in, len, out, adat->plat.s390x.fc, 85b077aed3SPierre Pronchery &adat->plat.s390x.param.kmo_kmf); 86b077aed3SPierre Pronchery 87b077aed3SPierre Pronchery out += len; 88b077aed3SPierre Pronchery in += len; 89b077aed3SPierre Pronchery } 90b077aed3SPierre Pronchery 91b077aed3SPierre Pronchery if (rem) { 92b077aed3SPierre Pronchery s390x_km(adat->plat.s390x.param.kmo_kmf.cv, 16, 93b077aed3SPierre Pronchery adat->plat.s390x.param.kmo_kmf.cv, 94b077aed3SPierre Pronchery adat->plat.s390x.fc, 95b077aed3SPierre Pronchery adat->plat.s390x.param.kmo_kmf.k); 96b077aed3SPierre Pronchery 97b077aed3SPierre Pronchery while (rem--) { 98b077aed3SPierre Pronchery out[n] = in[n] ^ adat->plat.s390x.param.kmo_kmf.cv[n]; 99b077aed3SPierre Pronchery ++n; 100b077aed3SPierre Pronchery } 101b077aed3SPierre Pronchery } 102b077aed3SPierre Pronchery 103b077aed3SPierre Pronchery memcpy(dat->iv, adat->plat.s390x.param.kmo_kmf.cv, dat->ivlen); 104*e0c4386eSCy Schubert dat->num = n; 105b077aed3SPierre Pronchery return 1; 106b077aed3SPierre Pronchery} 107b077aed3SPierre Pronchery 108b077aed3SPierre Proncherystatic int s390x_aes_cfb128_initkey(PROV_CIPHER_CTX *dat, 109b077aed3SPierre Pronchery const unsigned char *key, size_t keylen) 110b077aed3SPierre Pronchery{ 111b077aed3SPierre Pronchery PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; 112b077aed3SPierre Pronchery 113b077aed3SPierre Pronchery adat->plat.s390x.fc = S390X_AES_FC(keylen); 114b077aed3SPierre Pronchery adat->plat.s390x.fc |= 16 << 24; /* 16 bytes cipher feedback */ 115b077aed3SPierre Pronchery memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen); 116b077aed3SPierre Pronchery return 1; 117b077aed3SPierre Pronchery} 118b077aed3SPierre Pronchery 119b077aed3SPierre Proncherystatic int s390x_aes_cfb128_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out, 120b077aed3SPierre Pronchery const unsigned char *in, size_t len) 121b077aed3SPierre Pronchery{ 122b077aed3SPierre Pronchery PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; 123b077aed3SPierre Pronchery unsigned int modifier = adat->base.enc ? 0 : S390X_DECRYPT; 124*e0c4386eSCy Schubert int n = dat->num; 125b077aed3SPierre Pronchery int rem; 126b077aed3SPierre Pronchery unsigned char tmp; 127b077aed3SPierre Pronchery 128b077aed3SPierre Pronchery memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen); 129b077aed3SPierre Pronchery while (n && len) { 130b077aed3SPierre Pronchery tmp = *in; 131b077aed3SPierre Pronchery *out = adat->plat.s390x.param.kmo_kmf.cv[n] ^ tmp; 132b077aed3SPierre Pronchery adat->plat.s390x.param.kmo_kmf.cv[n] = dat->enc ? *out : tmp; 133b077aed3SPierre Pronchery n = (n + 1) & 0xf; 134b077aed3SPierre Pronchery --len; 135b077aed3SPierre Pronchery ++in; 136b077aed3SPierre Pronchery ++out; 137b077aed3SPierre Pronchery } 138b077aed3SPierre Pronchery 139b077aed3SPierre Pronchery rem = len & 0xf; 140b077aed3SPierre Pronchery 141b077aed3SPierre Pronchery len &= ~(size_t)0xf; 142b077aed3SPierre Pronchery if (len) { 143b077aed3SPierre Pronchery s390x_kmf(in, len, out, adat->plat.s390x.fc | modifier, 144b077aed3SPierre Pronchery &adat->plat.s390x.param.kmo_kmf); 145b077aed3SPierre Pronchery 146b077aed3SPierre Pronchery out += len; 147b077aed3SPierre Pronchery in += len; 148b077aed3SPierre Pronchery } 149b077aed3SPierre Pronchery 150b077aed3SPierre Pronchery if (rem) { 151b077aed3SPierre Pronchery s390x_km(adat->plat.s390x.param.kmo_kmf.cv, 16, 152b077aed3SPierre Pronchery adat->plat.s390x.param.kmo_kmf.cv, 153b077aed3SPierre Pronchery S390X_AES_FC(dat->keylen), 154b077aed3SPierre Pronchery adat->plat.s390x.param.kmo_kmf.k); 155b077aed3SPierre Pronchery 156b077aed3SPierre Pronchery while (rem--) { 157b077aed3SPierre Pronchery tmp = in[n]; 158b077aed3SPierre Pronchery out[n] = adat->plat.s390x.param.kmo_kmf.cv[n] ^ tmp; 159b077aed3SPierre Pronchery adat->plat.s390x.param.kmo_kmf.cv[n] = dat->enc ? out[n] : tmp; 160b077aed3SPierre Pronchery ++n; 161b077aed3SPierre Pronchery } 162b077aed3SPierre Pronchery } 163b077aed3SPierre Pronchery 164b077aed3SPierre Pronchery memcpy(dat->iv, adat->plat.s390x.param.kmo_kmf.cv, dat->ivlen); 165*e0c4386eSCy Schubert dat->num = n; 166b077aed3SPierre Pronchery return 1; 167b077aed3SPierre Pronchery} 168b077aed3SPierre Pronchery 169b077aed3SPierre Proncherystatic int s390x_aes_cfb8_initkey(PROV_CIPHER_CTX *dat, 170b077aed3SPierre Pronchery const unsigned char *key, size_t keylen) 171b077aed3SPierre Pronchery{ 172b077aed3SPierre Pronchery PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; 173b077aed3SPierre Pronchery 174b077aed3SPierre Pronchery adat->plat.s390x.fc = S390X_AES_FC(keylen); 175b077aed3SPierre Pronchery adat->plat.s390x.fc |= 1 << 24; /* 1 byte cipher feedback */ 176b077aed3SPierre Pronchery memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen); 177b077aed3SPierre Pronchery return 1; 178b077aed3SPierre Pronchery} 179b077aed3SPierre Pronchery 180b077aed3SPierre Proncherystatic int s390x_aes_cfb8_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out, 181b077aed3SPierre Pronchery const unsigned char *in, size_t len) 182b077aed3SPierre Pronchery{ 183b077aed3SPierre Pronchery PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; 184b077aed3SPierre Pronchery unsigned int modifier = adat->base.enc ? 0 : S390X_DECRYPT; 185b077aed3SPierre Pronchery 186b077aed3SPierre Pronchery memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen); 187b077aed3SPierre Pronchery s390x_kmf(in, len, out, adat->plat.s390x.fc | modifier, 188b077aed3SPierre Pronchery &adat->plat.s390x.param.kmo_kmf); 189b077aed3SPierre Pronchery memcpy(dat->iv, adat->plat.s390x.param.kmo_kmf.cv, dat->ivlen); 190b077aed3SPierre Pronchery return 1; 191b077aed3SPierre Pronchery} 192b077aed3SPierre Pronchery 193b077aed3SPierre Pronchery#define PROV_CIPHER_HW_declare(mode) \ 194b077aed3SPierre Proncherystatic const PROV_CIPHER_HW s390x_aes_##mode = { \ 195b077aed3SPierre Pronchery s390x_aes_##mode##_initkey, \ 196b077aed3SPierre Pronchery s390x_aes_##mode##_cipher_hw, \ 197b077aed3SPierre Pronchery cipher_hw_aes_copyctx \ 198b077aed3SPierre Pronchery}; 199b077aed3SPierre Pronchery#define PROV_CIPHER_HW_select(mode) \ 200b077aed3SPierre Proncheryif ((keybits == 128 && S390X_aes_128_##mode##_CAPABLE) \ 201b077aed3SPierre Pronchery || (keybits == 192 && S390X_aes_192_##mode##_CAPABLE) \ 202b077aed3SPierre Pronchery || (keybits == 256 && S390X_aes_256_##mode##_CAPABLE)) \ 203b077aed3SPierre Pronchery return &s390x_aes_##mode; 204b077aed3SPierre Pronchery 205