xref: /freebsd/crypto/openssl/providers/implementations/ciphers/cipher_aes_xts_s390x.inc (revision e7be843b4a162e68651d3911f0357ed464915629)
1*e7be843bSPierre Pronchery/*
2*e7be843bSPierre Pronchery * Copyright 2024 The OpenSSL Project Authors. All Rights Reserved.
3*e7be843bSPierre Pronchery *
4*e7be843bSPierre Pronchery * Licensed under the Apache License 2.0 (the "License").  You may not use
5*e7be843bSPierre Pronchery * this file except in compliance with the License.  You can obtain a copy
6*e7be843bSPierre Pronchery * in the file LICENSE in the source distribution or at
7*e7be843bSPierre Pronchery * https://www.openssl.org/source/license.html
8*e7be843bSPierre Pronchery */
9*e7be843bSPierre Pronchery
10*e7be843bSPierre Pronchery#include "crypto/s390x_arch.h"
11*e7be843bSPierre Pronchery
12*e7be843bSPierre Proncherystatic OSSL_FUNC_cipher_encrypt_init_fn s390x_aes_xts_einit;
13*e7be843bSPierre Proncherystatic OSSL_FUNC_cipher_decrypt_init_fn s390x_aes_xts_dinit;
14*e7be843bSPierre Proncherystatic OSSL_FUNC_cipher_cipher_fn s390x_aes_xts_cipher;
15*e7be843bSPierre Proncherystatic OSSL_FUNC_cipher_dupctx_fn s390x_aes_xts_dupctx;
16*e7be843bSPierre Pronchery
17*e7be843bSPierre Proncherystatic int s390x_aes_xts_init(void *vctx, const unsigned char *key,
18*e7be843bSPierre Pronchery                              size_t keylen, const unsigned char *iv,
19*e7be843bSPierre Pronchery                              size_t ivlen, const OSSL_PARAM params[],
20*e7be843bSPierre Pronchery                              unsigned int dec)
21*e7be843bSPierre Pronchery{
22*e7be843bSPierre Pronchery    PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)vctx;
23*e7be843bSPierre Pronchery    S390X_KM_XTS_PARAMS *km = &xctx->plat.s390x.param.km;
24*e7be843bSPierre Pronchery    unsigned int fc, offs;
25*e7be843bSPierre Pronchery
26*e7be843bSPierre Pronchery    switch (xctx->base.keylen) {
27*e7be843bSPierre Pronchery    case 128 / 8 * 2:
28*e7be843bSPierre Pronchery        fc = S390X_XTS_AES_128_MSA10;
29*e7be843bSPierre Pronchery        offs = 32;
30*e7be843bSPierre Pronchery        break;
31*e7be843bSPierre Pronchery    case 256 / 8 * 2:
32*e7be843bSPierre Pronchery        fc = S390X_XTS_AES_256_MSA10;
33*e7be843bSPierre Pronchery        offs = 0;
34*e7be843bSPierre Pronchery        break;
35*e7be843bSPierre Pronchery    default:
36*e7be843bSPierre Pronchery        goto not_supported;
37*e7be843bSPierre Pronchery    }
38*e7be843bSPierre Pronchery
39*e7be843bSPierre Pronchery    if (!(OPENSSL_s390xcap_P.km[1] && S390X_CAPBIT(fc)))
40*e7be843bSPierre Pronchery        goto not_supported;
41*e7be843bSPierre Pronchery
42*e7be843bSPierre Pronchery    if (iv != NULL) {
43*e7be843bSPierre Pronchery        if (ivlen != xctx->base.ivlen
44*e7be843bSPierre Pronchery                || ivlen > sizeof(km->tweak)) {
45*e7be843bSPierre Pronchery            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
46*e7be843bSPierre Pronchery            return 0;
47*e7be843bSPierre Pronchery        }
48*e7be843bSPierre Pronchery        memcpy(km->tweak, iv, ivlen);
49*e7be843bSPierre Pronchery        xctx->plat.s390x.iv_set = 1;
50*e7be843bSPierre Pronchery    }
51*e7be843bSPierre Pronchery
52*e7be843bSPierre Pronchery    if (key != NULL) {
53*e7be843bSPierre Pronchery        if (keylen != xctx->base.keylen) {
54*e7be843bSPierre Pronchery            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
55*e7be843bSPierre Pronchery            return 0;
56*e7be843bSPierre Pronchery        }
57*e7be843bSPierre Pronchery        if (!aes_xts_check_keys_differ(key, keylen / 2, !dec))
58*e7be843bSPierre Pronchery            return 0;
59*e7be843bSPierre Pronchery
60*e7be843bSPierre Pronchery        memcpy(km->key + offs, key, keylen);
61*e7be843bSPierre Pronchery        xctx->plat.s390x.key_set = 1;
62*e7be843bSPierre Pronchery    }
63*e7be843bSPierre Pronchery
64*e7be843bSPierre Pronchery    xctx->plat.s390x.fc = fc | dec;
65*e7be843bSPierre Pronchery    xctx->plat.s390x.offset = offs;
66*e7be843bSPierre Pronchery
67*e7be843bSPierre Pronchery    memset(km->nap, 0, sizeof(km->nap));
68*e7be843bSPierre Pronchery    km->nap[0] = 0x1;
69*e7be843bSPierre Pronchery
70*e7be843bSPierre Pronchery    return aes_xts_set_ctx_params(xctx, params);
71*e7be843bSPierre Pronchery
72*e7be843bSPierre Proncherynot_supported:
73*e7be843bSPierre Pronchery    xctx->plat.s390x.fc = 0;
74*e7be843bSPierre Pronchery    xctx->plat.s390x.offset = 0;
75*e7be843bSPierre Pronchery    return 0;
76*e7be843bSPierre Pronchery}
77*e7be843bSPierre Pronchery
78*e7be843bSPierre Proncherystatic int s390x_aes_xts_einit(void *vctx, const unsigned char *key,
79*e7be843bSPierre Pronchery                               size_t keylen, const unsigned char *iv,
80*e7be843bSPierre Pronchery                               size_t ivlen, const OSSL_PARAM params[])
81*e7be843bSPierre Pronchery{
82*e7be843bSPierre Pronchery    return s390x_aes_xts_init(vctx, key, keylen, iv, ivlen, params, 0);
83*e7be843bSPierre Pronchery}
84*e7be843bSPierre Pronchery
85*e7be843bSPierre Proncherystatic int s390x_aes_xts_dinit(void *vctx, const unsigned char *key,
86*e7be843bSPierre Pronchery                               size_t keylen, const unsigned char *iv,
87*e7be843bSPierre Pronchery                               size_t ivlen, const OSSL_PARAM params[])
88*e7be843bSPierre Pronchery{
89*e7be843bSPierre Pronchery    return s390x_aes_xts_init(vctx, key, keylen, iv, ivlen, params,
90*e7be843bSPierre Pronchery                              S390X_DECRYPT);
91*e7be843bSPierre Pronchery}
92*e7be843bSPierre Pronchery
93*e7be843bSPierre Proncherystatic void *s390x_aes_xts_dupctx(void *vctx)
94*e7be843bSPierre Pronchery{
95*e7be843bSPierre Pronchery    PROV_AES_XTS_CTX *in = (PROV_AES_XTS_CTX *)vctx;
96*e7be843bSPierre Pronchery    PROV_AES_XTS_CTX *ret = OPENSSL_zalloc(sizeof(*in));
97*e7be843bSPierre Pronchery
98*e7be843bSPierre Pronchery    if (ret != NULL)
99*e7be843bSPierre Pronchery        *ret = *in;
100*e7be843bSPierre Pronchery
101*e7be843bSPierre Pronchery    return ret;
102*e7be843bSPierre Pronchery}
103*e7be843bSPierre Pronchery
104*e7be843bSPierre Proncherystatic int s390x_aes_xts_cipher(void *vctx, unsigned char *out, size_t *outl,
105*e7be843bSPierre Pronchery                                size_t outsize, const unsigned char *in,
106*e7be843bSPierre Pronchery                                size_t inl)
107*e7be843bSPierre Pronchery{
108*e7be843bSPierre Pronchery    PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)vctx;
109*e7be843bSPierre Pronchery    S390X_KM_XTS_PARAMS *km = &xctx->plat.s390x.param.km;
110*e7be843bSPierre Pronchery    unsigned char *param = (unsigned char *)km + xctx->plat.s390x.offset;
111*e7be843bSPierre Pronchery    unsigned int fc = xctx->plat.s390x.fc;
112*e7be843bSPierre Pronchery    unsigned char tmp[2][AES_BLOCK_SIZE];
113*e7be843bSPierre Pronchery    unsigned char nap_n1[AES_BLOCK_SIZE];
114*e7be843bSPierre Pronchery    unsigned char drop[AES_BLOCK_SIZE];
115*e7be843bSPierre Pronchery    size_t len_incomplete, len_complete;
116*e7be843bSPierre Pronchery
117*e7be843bSPierre Pronchery    if (!ossl_prov_is_running()
118*e7be843bSPierre Pronchery            || inl < AES_BLOCK_SIZE
119*e7be843bSPierre Pronchery            || in == NULL
120*e7be843bSPierre Pronchery            || out == NULL
121*e7be843bSPierre Pronchery            || !xctx->plat.s390x.iv_set
122*e7be843bSPierre Pronchery            || !xctx->plat.s390x.key_set)
123*e7be843bSPierre Pronchery        return 0;
124*e7be843bSPierre Pronchery
125*e7be843bSPierre Pronchery    /*
126*e7be843bSPierre Pronchery     * Impose a limit of 2^20 blocks per data unit as specified by
127*e7be843bSPierre Pronchery     * IEEE Std 1619-2018.  The earlier and obsolete IEEE Std 1619-2007
128*e7be843bSPierre Pronchery     * indicated that this was a SHOULD NOT rather than a MUST NOT.
129*e7be843bSPierre Pronchery     * NIST SP 800-38E mandates the same limit.
130*e7be843bSPierre Pronchery     */
131*e7be843bSPierre Pronchery    if (inl > XTS_MAX_BLOCKS_PER_DATA_UNIT * AES_BLOCK_SIZE) {
132*e7be843bSPierre Pronchery        ERR_raise(ERR_LIB_PROV, PROV_R_XTS_DATA_UNIT_IS_TOO_LARGE);
133*e7be843bSPierre Pronchery        return 0;
134*e7be843bSPierre Pronchery    }
135*e7be843bSPierre Pronchery
136*e7be843bSPierre Pronchery    len_incomplete = inl % AES_BLOCK_SIZE;
137*e7be843bSPierre Pronchery    len_complete = (len_incomplete == 0) ? inl :
138*e7be843bSPierre Pronchery                       (inl / AES_BLOCK_SIZE - 1) * AES_BLOCK_SIZE;
139*e7be843bSPierre Pronchery
140*e7be843bSPierre Pronchery    if (len_complete > 0)
141*e7be843bSPierre Pronchery        s390x_km(in, len_complete, out, fc, param);
142*e7be843bSPierre Pronchery    if (len_incomplete == 0)
143*e7be843bSPierre Pronchery       goto out;
144*e7be843bSPierre Pronchery
145*e7be843bSPierre Pronchery    memcpy(tmp, in + len_complete, AES_BLOCK_SIZE + len_incomplete);
146*e7be843bSPierre Pronchery    /* swap NAP for decrypt */
147*e7be843bSPierre Pronchery    if (fc & S390X_DECRYPT) {
148*e7be843bSPierre Pronchery        memcpy(nap_n1, km->nap, AES_BLOCK_SIZE);
149*e7be843bSPierre Pronchery        s390x_km(tmp[0], AES_BLOCK_SIZE, drop, fc, param);
150*e7be843bSPierre Pronchery    }
151*e7be843bSPierre Pronchery    s390x_km(tmp[0], AES_BLOCK_SIZE, tmp[0], fc, param);
152*e7be843bSPierre Pronchery    if (fc & S390X_DECRYPT)
153*e7be843bSPierre Pronchery        memcpy(km->nap, nap_n1, AES_BLOCK_SIZE);
154*e7be843bSPierre Pronchery
155*e7be843bSPierre Pronchery    memcpy(tmp[1] + len_incomplete, tmp[0] + len_incomplete,
156*e7be843bSPierre Pronchery           AES_BLOCK_SIZE - len_incomplete);
157*e7be843bSPierre Pronchery    s390x_km(tmp[1], AES_BLOCK_SIZE, out + len_complete, fc, param);
158*e7be843bSPierre Pronchery    memcpy(out + len_complete + AES_BLOCK_SIZE, tmp[0], len_incomplete);
159*e7be843bSPierre Pronchery
160*e7be843bSPierre Pronchery    /* do not expose temporary data */
161*e7be843bSPierre Pronchery    OPENSSL_cleanse(tmp, sizeof(tmp));
162*e7be843bSPierre Proncheryout:
163*e7be843bSPierre Pronchery    memcpy(xctx->base.iv, km->tweak, AES_BLOCK_SIZE);
164*e7be843bSPierre Pronchery    *outl = inl;
165*e7be843bSPierre Pronchery
166*e7be843bSPierre Pronchery    return 1;
167*e7be843bSPierre Pronchery}
168