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