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