xref: /freebsd/crypto/openssl/providers/implementations/ciphers/cipher_aes_hw_s390x.inc (revision e0c4386e7e71d93b0edc0c8fa156263fc4a8b0b6)
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