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 * This file uses the low level AES functions (which are deprecated for
12e1051a39Sopenharmony_ci * non-internal use) in order to implement the EVP AES ciphers.
13e1051a39Sopenharmony_ci */
14e1051a39Sopenharmony_ci#include "internal/deprecated.h"
15e1051a39Sopenharmony_ci
16e1051a39Sopenharmony_ci#include <string.h>
17e1051a39Sopenharmony_ci#include <assert.h>
18e1051a39Sopenharmony_ci#include <openssl/opensslconf.h>
19e1051a39Sopenharmony_ci#include <openssl/crypto.h>
20e1051a39Sopenharmony_ci#include <openssl/evp.h>
21e1051a39Sopenharmony_ci#include <openssl/err.h>
22e1051a39Sopenharmony_ci#include <openssl/aes.h>
23e1051a39Sopenharmony_ci#include <openssl/rand.h>
24e1051a39Sopenharmony_ci#include <openssl/cmac.h>
25e1051a39Sopenharmony_ci#include "crypto/evp.h"
26e1051a39Sopenharmony_ci#include "internal/cryptlib.h"
27e1051a39Sopenharmony_ci#include "crypto/modes.h"
28e1051a39Sopenharmony_ci#include "crypto/siv.h"
29e1051a39Sopenharmony_ci#include "crypto/aes_platform.h"
30e1051a39Sopenharmony_ci#include "evp_local.h"
31e1051a39Sopenharmony_ci
32e1051a39Sopenharmony_citypedef struct {
33e1051a39Sopenharmony_ci    union {
34e1051a39Sopenharmony_ci        OSSL_UNION_ALIGN;
35e1051a39Sopenharmony_ci        AES_KEY ks;
36e1051a39Sopenharmony_ci    } ks;
37e1051a39Sopenharmony_ci    block128_f block;
38e1051a39Sopenharmony_ci    union {
39e1051a39Sopenharmony_ci        cbc128_f cbc;
40e1051a39Sopenharmony_ci        ctr128_f ctr;
41e1051a39Sopenharmony_ci    } stream;
42e1051a39Sopenharmony_ci} EVP_AES_KEY;
43e1051a39Sopenharmony_ci
44e1051a39Sopenharmony_citypedef struct {
45e1051a39Sopenharmony_ci    union {
46e1051a39Sopenharmony_ci        OSSL_UNION_ALIGN;
47e1051a39Sopenharmony_ci        AES_KEY ks;
48e1051a39Sopenharmony_ci    } ks;                       /* AES key schedule to use */
49e1051a39Sopenharmony_ci    int key_set;                /* Set if key initialised */
50e1051a39Sopenharmony_ci    int iv_set;                 /* Set if an iv is set */
51e1051a39Sopenharmony_ci    GCM128_CONTEXT gcm;
52e1051a39Sopenharmony_ci    unsigned char *iv;          /* Temporary IV store */
53e1051a39Sopenharmony_ci    int ivlen;                  /* IV length */
54e1051a39Sopenharmony_ci    int taglen;
55e1051a39Sopenharmony_ci    int iv_gen;                 /* It is OK to generate IVs */
56e1051a39Sopenharmony_ci    int iv_gen_rand;            /* No IV was specified, so generate a rand IV */
57e1051a39Sopenharmony_ci    int tls_aad_len;            /* TLS AAD length */
58e1051a39Sopenharmony_ci    uint64_t tls_enc_records;   /* Number of TLS records encrypted */
59e1051a39Sopenharmony_ci    ctr128_f ctr;
60e1051a39Sopenharmony_ci} EVP_AES_GCM_CTX;
61e1051a39Sopenharmony_ci
62e1051a39Sopenharmony_citypedef struct {
63e1051a39Sopenharmony_ci    union {
64e1051a39Sopenharmony_ci        OSSL_UNION_ALIGN;
65e1051a39Sopenharmony_ci        AES_KEY ks;
66e1051a39Sopenharmony_ci    } ks1, ks2;                 /* AES key schedules to use */
67e1051a39Sopenharmony_ci    XTS128_CONTEXT xts;
68e1051a39Sopenharmony_ci    void (*stream) (const unsigned char *in,
69e1051a39Sopenharmony_ci                    unsigned char *out, size_t length,
70e1051a39Sopenharmony_ci                    const AES_KEY *key1, const AES_KEY *key2,
71e1051a39Sopenharmony_ci                    const unsigned char iv[16]);
72e1051a39Sopenharmony_ci} EVP_AES_XTS_CTX;
73e1051a39Sopenharmony_ci
74e1051a39Sopenharmony_ci#ifdef FIPS_MODULE
75e1051a39Sopenharmony_cistatic const int allow_insecure_decrypt = 0;
76e1051a39Sopenharmony_ci#else
77e1051a39Sopenharmony_cistatic const int allow_insecure_decrypt = 1;
78e1051a39Sopenharmony_ci#endif
79e1051a39Sopenharmony_ci
80e1051a39Sopenharmony_citypedef struct {
81e1051a39Sopenharmony_ci    union {
82e1051a39Sopenharmony_ci        OSSL_UNION_ALIGN;
83e1051a39Sopenharmony_ci        AES_KEY ks;
84e1051a39Sopenharmony_ci    } ks;                       /* AES key schedule to use */
85e1051a39Sopenharmony_ci    int key_set;                /* Set if key initialised */
86e1051a39Sopenharmony_ci    int iv_set;                 /* Set if an iv is set */
87e1051a39Sopenharmony_ci    int tag_set;                /* Set if tag is valid */
88e1051a39Sopenharmony_ci    int len_set;                /* Set if message length set */
89e1051a39Sopenharmony_ci    int L, M;                   /* L and M parameters from RFC3610 */
90e1051a39Sopenharmony_ci    int tls_aad_len;            /* TLS AAD length */
91e1051a39Sopenharmony_ci    CCM128_CONTEXT ccm;
92e1051a39Sopenharmony_ci    ccm128_f str;
93e1051a39Sopenharmony_ci} EVP_AES_CCM_CTX;
94e1051a39Sopenharmony_ci
95e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_OCB
96e1051a39Sopenharmony_citypedef struct {
97e1051a39Sopenharmony_ci    union {
98e1051a39Sopenharmony_ci        OSSL_UNION_ALIGN;
99e1051a39Sopenharmony_ci        AES_KEY ks;
100e1051a39Sopenharmony_ci    } ksenc;                    /* AES key schedule to use for encryption */
101e1051a39Sopenharmony_ci    union {
102e1051a39Sopenharmony_ci        OSSL_UNION_ALIGN;
103e1051a39Sopenharmony_ci        AES_KEY ks;
104e1051a39Sopenharmony_ci    } ksdec;                    /* AES key schedule to use for decryption */
105e1051a39Sopenharmony_ci    int key_set;                /* Set if key initialised */
106e1051a39Sopenharmony_ci    int iv_set;                 /* Set if an iv is set */
107e1051a39Sopenharmony_ci    OCB128_CONTEXT ocb;
108e1051a39Sopenharmony_ci    unsigned char *iv;          /* Temporary IV store */
109e1051a39Sopenharmony_ci    unsigned char tag[16];
110e1051a39Sopenharmony_ci    unsigned char data_buf[16]; /* Store partial data blocks */
111e1051a39Sopenharmony_ci    unsigned char aad_buf[16];  /* Store partial AAD blocks */
112e1051a39Sopenharmony_ci    int data_buf_len;
113e1051a39Sopenharmony_ci    int aad_buf_len;
114e1051a39Sopenharmony_ci    int ivlen;                  /* IV length */
115e1051a39Sopenharmony_ci    int taglen;
116e1051a39Sopenharmony_ci} EVP_AES_OCB_CTX;
117e1051a39Sopenharmony_ci#endif
118e1051a39Sopenharmony_ci
119e1051a39Sopenharmony_ci#define MAXBITCHUNK     ((size_t)1<<(sizeof(size_t)*8-4))
120e1051a39Sopenharmony_ci
121e1051a39Sopenharmony_ci/* increment counter (64-bit int) by 1 */
122e1051a39Sopenharmony_cistatic void ctr64_inc(unsigned char *counter)
123e1051a39Sopenharmony_ci{
124e1051a39Sopenharmony_ci    int n = 8;
125e1051a39Sopenharmony_ci    unsigned char c;
126e1051a39Sopenharmony_ci
127e1051a39Sopenharmony_ci    do {
128e1051a39Sopenharmony_ci        --n;
129e1051a39Sopenharmony_ci        c = counter[n];
130e1051a39Sopenharmony_ci        ++c;
131e1051a39Sopenharmony_ci        counter[n] = c;
132e1051a39Sopenharmony_ci        if (c)
133e1051a39Sopenharmony_ci            return;
134e1051a39Sopenharmony_ci    } while (n);
135e1051a39Sopenharmony_ci}
136e1051a39Sopenharmony_ci
137e1051a39Sopenharmony_ci#if defined(AESNI_CAPABLE)
138e1051a39Sopenharmony_ci# if defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)
139e1051a39Sopenharmony_ci#  define AES_GCM_ASM2(gctx)      (gctx->gcm.block==(block128_f)aesni_encrypt && \
140e1051a39Sopenharmony_ci                                 gctx->gcm.ghash==gcm_ghash_avx)
141e1051a39Sopenharmony_ci#  undef AES_GCM_ASM2          /* minor size optimization */
142e1051a39Sopenharmony_ci# endif
143e1051a39Sopenharmony_ci
144e1051a39Sopenharmony_cistatic int aesni_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
145e1051a39Sopenharmony_ci                          const unsigned char *iv, int enc)
146e1051a39Sopenharmony_ci{
147e1051a39Sopenharmony_ci    int ret, mode;
148e1051a39Sopenharmony_ci    EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
149e1051a39Sopenharmony_ci
150e1051a39Sopenharmony_ci    mode = EVP_CIPHER_CTX_get_mode(ctx);
151e1051a39Sopenharmony_ci    if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE)
152e1051a39Sopenharmony_ci        && !enc) {
153e1051a39Sopenharmony_ci        ret = aesni_set_decrypt_key(key,
154e1051a39Sopenharmony_ci                                    EVP_CIPHER_CTX_get_key_length(ctx) * 8,
155e1051a39Sopenharmony_ci                                    &dat->ks.ks);
156e1051a39Sopenharmony_ci        dat->block = (block128_f) aesni_decrypt;
157e1051a39Sopenharmony_ci        dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
158e1051a39Sopenharmony_ci            (cbc128_f) aesni_cbc_encrypt : NULL;
159e1051a39Sopenharmony_ci    } else {
160e1051a39Sopenharmony_ci        ret = aesni_set_encrypt_key(key,
161e1051a39Sopenharmony_ci                                    EVP_CIPHER_CTX_get_key_length(ctx) * 8,
162e1051a39Sopenharmony_ci                                    &dat->ks.ks);
163e1051a39Sopenharmony_ci        dat->block = (block128_f) aesni_encrypt;
164e1051a39Sopenharmony_ci        if (mode == EVP_CIPH_CBC_MODE)
165e1051a39Sopenharmony_ci            dat->stream.cbc = (cbc128_f) aesni_cbc_encrypt;
166e1051a39Sopenharmony_ci        else if (mode == EVP_CIPH_CTR_MODE)
167e1051a39Sopenharmony_ci            dat->stream.ctr = (ctr128_f) aesni_ctr32_encrypt_blocks;
168e1051a39Sopenharmony_ci        else
169e1051a39Sopenharmony_ci            dat->stream.cbc = NULL;
170e1051a39Sopenharmony_ci    }
171e1051a39Sopenharmony_ci
172e1051a39Sopenharmony_ci    if (ret < 0) {
173e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EVP, EVP_R_AES_KEY_SETUP_FAILED);
174e1051a39Sopenharmony_ci        return 0;
175e1051a39Sopenharmony_ci    }
176e1051a39Sopenharmony_ci
177e1051a39Sopenharmony_ci    return 1;
178e1051a39Sopenharmony_ci}
179e1051a39Sopenharmony_ci
180e1051a39Sopenharmony_cistatic int aesni_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
181e1051a39Sopenharmony_ci                            const unsigned char *in, size_t len)
182e1051a39Sopenharmony_ci{
183e1051a39Sopenharmony_ci    aesni_cbc_encrypt(in, out, len, &EVP_C_DATA(EVP_AES_KEY,ctx)->ks.ks,
184e1051a39Sopenharmony_ci                      ctx->iv, EVP_CIPHER_CTX_is_encrypting(ctx));
185e1051a39Sopenharmony_ci
186e1051a39Sopenharmony_ci    return 1;
187e1051a39Sopenharmony_ci}
188e1051a39Sopenharmony_ci
189e1051a39Sopenharmony_cistatic int aesni_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
190e1051a39Sopenharmony_ci                            const unsigned char *in, size_t len)
191e1051a39Sopenharmony_ci{
192e1051a39Sopenharmony_ci    size_t bl = EVP_CIPHER_CTX_get_block_size(ctx);
193e1051a39Sopenharmony_ci
194e1051a39Sopenharmony_ci    if (len < bl)
195e1051a39Sopenharmony_ci        return 1;
196e1051a39Sopenharmony_ci
197e1051a39Sopenharmony_ci    aesni_ecb_encrypt(in, out, len, &EVP_C_DATA(EVP_AES_KEY,ctx)->ks.ks,
198e1051a39Sopenharmony_ci                      EVP_CIPHER_CTX_is_encrypting(ctx));
199e1051a39Sopenharmony_ci
200e1051a39Sopenharmony_ci    return 1;
201e1051a39Sopenharmony_ci}
202e1051a39Sopenharmony_ci
203e1051a39Sopenharmony_ci# define aesni_ofb_cipher aes_ofb_cipher
204e1051a39Sopenharmony_cistatic int aesni_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
205e1051a39Sopenharmony_ci                            const unsigned char *in, size_t len);
206e1051a39Sopenharmony_ci
207e1051a39Sopenharmony_ci# define aesni_cfb_cipher aes_cfb_cipher
208e1051a39Sopenharmony_cistatic int aesni_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
209e1051a39Sopenharmony_ci                            const unsigned char *in, size_t len);
210e1051a39Sopenharmony_ci
211e1051a39Sopenharmony_ci# define aesni_cfb8_cipher aes_cfb8_cipher
212e1051a39Sopenharmony_cistatic int aesni_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
213e1051a39Sopenharmony_ci                             const unsigned char *in, size_t len);
214e1051a39Sopenharmony_ci
215e1051a39Sopenharmony_ci# define aesni_cfb1_cipher aes_cfb1_cipher
216e1051a39Sopenharmony_cistatic int aesni_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
217e1051a39Sopenharmony_ci                             const unsigned char *in, size_t len);
218e1051a39Sopenharmony_ci
219e1051a39Sopenharmony_ci# define aesni_ctr_cipher aes_ctr_cipher
220e1051a39Sopenharmony_cistatic int aesni_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
221e1051a39Sopenharmony_ci                            const unsigned char *in, size_t len);
222e1051a39Sopenharmony_ci
223e1051a39Sopenharmony_cistatic int aesni_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
224e1051a39Sopenharmony_ci                              const unsigned char *iv, int enc)
225e1051a39Sopenharmony_ci{
226e1051a39Sopenharmony_ci    EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx);
227e1051a39Sopenharmony_ci    if (!iv && !key)
228e1051a39Sopenharmony_ci        return 1;
229e1051a39Sopenharmony_ci    if (key) {
230e1051a39Sopenharmony_ci        aesni_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
231e1051a39Sopenharmony_ci                              &gctx->ks.ks);
232e1051a39Sopenharmony_ci        CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, (block128_f) aesni_encrypt);
233e1051a39Sopenharmony_ci        gctx->ctr = (ctr128_f) aesni_ctr32_encrypt_blocks;
234e1051a39Sopenharmony_ci        /*
235e1051a39Sopenharmony_ci         * If we have an iv can set it directly, otherwise use saved IV.
236e1051a39Sopenharmony_ci         */
237e1051a39Sopenharmony_ci        if (iv == NULL && gctx->iv_set)
238e1051a39Sopenharmony_ci            iv = gctx->iv;
239e1051a39Sopenharmony_ci        if (iv) {
240e1051a39Sopenharmony_ci            CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen);
241e1051a39Sopenharmony_ci            gctx->iv_set = 1;
242e1051a39Sopenharmony_ci        }
243e1051a39Sopenharmony_ci        gctx->key_set = 1;
244e1051a39Sopenharmony_ci    } else {
245e1051a39Sopenharmony_ci        /* If key set use IV, otherwise copy */
246e1051a39Sopenharmony_ci        if (gctx->key_set)
247e1051a39Sopenharmony_ci            CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen);
248e1051a39Sopenharmony_ci        else
249e1051a39Sopenharmony_ci            memcpy(gctx->iv, iv, gctx->ivlen);
250e1051a39Sopenharmony_ci        gctx->iv_set = 1;
251e1051a39Sopenharmony_ci        gctx->iv_gen = 0;
252e1051a39Sopenharmony_ci    }
253e1051a39Sopenharmony_ci    return 1;
254e1051a39Sopenharmony_ci}
255e1051a39Sopenharmony_ci
256e1051a39Sopenharmony_ci# define aesni_gcm_cipher aes_gcm_cipher
257e1051a39Sopenharmony_cistatic int aesni_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
258e1051a39Sopenharmony_ci                            const unsigned char *in, size_t len);
259e1051a39Sopenharmony_ci
260e1051a39Sopenharmony_cistatic int aesni_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
261e1051a39Sopenharmony_ci                              const unsigned char *iv, int enc)
262e1051a39Sopenharmony_ci{
263e1051a39Sopenharmony_ci    EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,ctx);
264e1051a39Sopenharmony_ci
265e1051a39Sopenharmony_ci    if (!iv && !key)
266e1051a39Sopenharmony_ci        return 1;
267e1051a39Sopenharmony_ci
268e1051a39Sopenharmony_ci    if (key) {
269e1051a39Sopenharmony_ci        /* The key is two half length keys in reality */
270e1051a39Sopenharmony_ci        const int bytes = EVP_CIPHER_CTX_get_key_length(ctx) / 2;
271e1051a39Sopenharmony_ci        const int bits = bytes * 8;
272e1051a39Sopenharmony_ci
273e1051a39Sopenharmony_ci        /*
274e1051a39Sopenharmony_ci         * Verify that the two keys are different.
275e1051a39Sopenharmony_ci         *
276e1051a39Sopenharmony_ci         * This addresses Rogaway's vulnerability.
277e1051a39Sopenharmony_ci         * See comment in aes_xts_init_key() below.
278e1051a39Sopenharmony_ci         */
279e1051a39Sopenharmony_ci        if ((!allow_insecure_decrypt || enc)
280e1051a39Sopenharmony_ci                && CRYPTO_memcmp(key, key + bytes, bytes) == 0) {
281e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_EVP, EVP_R_XTS_DUPLICATED_KEYS);
282e1051a39Sopenharmony_ci            return 0;
283e1051a39Sopenharmony_ci        }
284e1051a39Sopenharmony_ci
285e1051a39Sopenharmony_ci        /* key_len is two AES keys */
286e1051a39Sopenharmony_ci        if (enc) {
287e1051a39Sopenharmony_ci            aesni_set_encrypt_key(key, bits, &xctx->ks1.ks);
288e1051a39Sopenharmony_ci            xctx->xts.block1 = (block128_f) aesni_encrypt;
289e1051a39Sopenharmony_ci            xctx->stream = aesni_xts_encrypt;
290e1051a39Sopenharmony_ci        } else {
291e1051a39Sopenharmony_ci            aesni_set_decrypt_key(key, bits, &xctx->ks1.ks);
292e1051a39Sopenharmony_ci            xctx->xts.block1 = (block128_f) aesni_decrypt;
293e1051a39Sopenharmony_ci            xctx->stream = aesni_xts_decrypt;
294e1051a39Sopenharmony_ci        }
295e1051a39Sopenharmony_ci
296e1051a39Sopenharmony_ci        aesni_set_encrypt_key(key + bytes, bits, &xctx->ks2.ks);
297e1051a39Sopenharmony_ci        xctx->xts.block2 = (block128_f) aesni_encrypt;
298e1051a39Sopenharmony_ci
299e1051a39Sopenharmony_ci        xctx->xts.key1 = &xctx->ks1;
300e1051a39Sopenharmony_ci    }
301e1051a39Sopenharmony_ci
302e1051a39Sopenharmony_ci    if (iv) {
303e1051a39Sopenharmony_ci        xctx->xts.key2 = &xctx->ks2;
304e1051a39Sopenharmony_ci        memcpy(ctx->iv, iv, 16);
305e1051a39Sopenharmony_ci    }
306e1051a39Sopenharmony_ci
307e1051a39Sopenharmony_ci    return 1;
308e1051a39Sopenharmony_ci}
309e1051a39Sopenharmony_ci
310e1051a39Sopenharmony_ci# define aesni_xts_cipher aes_xts_cipher
311e1051a39Sopenharmony_cistatic int aesni_xts_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
312e1051a39Sopenharmony_ci                            const unsigned char *in, size_t len);
313e1051a39Sopenharmony_ci
314e1051a39Sopenharmony_cistatic int aesni_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
315e1051a39Sopenharmony_ci                              const unsigned char *iv, int enc)
316e1051a39Sopenharmony_ci{
317e1051a39Sopenharmony_ci    EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx);
318e1051a39Sopenharmony_ci    if (!iv && !key)
319e1051a39Sopenharmony_ci        return 1;
320e1051a39Sopenharmony_ci    if (key) {
321e1051a39Sopenharmony_ci        aesni_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
322e1051a39Sopenharmony_ci                              &cctx->ks.ks);
323e1051a39Sopenharmony_ci        CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L,
324e1051a39Sopenharmony_ci                           &cctx->ks, (block128_f) aesni_encrypt);
325e1051a39Sopenharmony_ci        cctx->str = enc ? (ccm128_f) aesni_ccm64_encrypt_blocks :
326e1051a39Sopenharmony_ci            (ccm128_f) aesni_ccm64_decrypt_blocks;
327e1051a39Sopenharmony_ci        cctx->key_set = 1;
328e1051a39Sopenharmony_ci    }
329e1051a39Sopenharmony_ci    if (iv) {
330e1051a39Sopenharmony_ci        memcpy(ctx->iv, iv, 15 - cctx->L);
331e1051a39Sopenharmony_ci        cctx->iv_set = 1;
332e1051a39Sopenharmony_ci    }
333e1051a39Sopenharmony_ci    return 1;
334e1051a39Sopenharmony_ci}
335e1051a39Sopenharmony_ci
336e1051a39Sopenharmony_ci# define aesni_ccm_cipher aes_ccm_cipher
337e1051a39Sopenharmony_cistatic int aesni_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
338e1051a39Sopenharmony_ci                            const unsigned char *in, size_t len);
339e1051a39Sopenharmony_ci
340e1051a39Sopenharmony_ci# ifndef OPENSSL_NO_OCB
341e1051a39Sopenharmony_cistatic int aesni_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
342e1051a39Sopenharmony_ci                              const unsigned char *iv, int enc)
343e1051a39Sopenharmony_ci{
344e1051a39Sopenharmony_ci    EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,ctx);
345e1051a39Sopenharmony_ci    if (!iv && !key)
346e1051a39Sopenharmony_ci        return 1;
347e1051a39Sopenharmony_ci    if (key) {
348e1051a39Sopenharmony_ci        do {
349e1051a39Sopenharmony_ci            /*
350e1051a39Sopenharmony_ci             * We set both the encrypt and decrypt key here because decrypt
351e1051a39Sopenharmony_ci             * needs both. We could possibly optimise to remove setting the
352e1051a39Sopenharmony_ci             * decrypt for an encryption operation.
353e1051a39Sopenharmony_ci             */
354e1051a39Sopenharmony_ci            aesni_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
355e1051a39Sopenharmony_ci                                  &octx->ksenc.ks);
356e1051a39Sopenharmony_ci            aesni_set_decrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
357e1051a39Sopenharmony_ci                                  &octx->ksdec.ks);
358e1051a39Sopenharmony_ci            if (!CRYPTO_ocb128_init(&octx->ocb,
359e1051a39Sopenharmony_ci                                    &octx->ksenc.ks, &octx->ksdec.ks,
360e1051a39Sopenharmony_ci                                    (block128_f) aesni_encrypt,
361e1051a39Sopenharmony_ci                                    (block128_f) aesni_decrypt,
362e1051a39Sopenharmony_ci                                    enc ? aesni_ocb_encrypt
363e1051a39Sopenharmony_ci                                        : aesni_ocb_decrypt))
364e1051a39Sopenharmony_ci                return 0;
365e1051a39Sopenharmony_ci        }
366e1051a39Sopenharmony_ci        while (0);
367e1051a39Sopenharmony_ci
368e1051a39Sopenharmony_ci        /*
369e1051a39Sopenharmony_ci         * If we have an iv we can set it directly, otherwise use saved IV.
370e1051a39Sopenharmony_ci         */
371e1051a39Sopenharmony_ci        if (iv == NULL && octx->iv_set)
372e1051a39Sopenharmony_ci            iv = octx->iv;
373e1051a39Sopenharmony_ci        if (iv) {
374e1051a39Sopenharmony_ci            if (CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen)
375e1051a39Sopenharmony_ci                != 1)
376e1051a39Sopenharmony_ci                return 0;
377e1051a39Sopenharmony_ci            octx->iv_set = 1;
378e1051a39Sopenharmony_ci        }
379e1051a39Sopenharmony_ci        octx->key_set = 1;
380e1051a39Sopenharmony_ci    } else {
381e1051a39Sopenharmony_ci        /* If key set use IV, otherwise copy */
382e1051a39Sopenharmony_ci        if (octx->key_set)
383e1051a39Sopenharmony_ci            CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen);
384e1051a39Sopenharmony_ci        else
385e1051a39Sopenharmony_ci            memcpy(octx->iv, iv, octx->ivlen);
386e1051a39Sopenharmony_ci        octx->iv_set = 1;
387e1051a39Sopenharmony_ci    }
388e1051a39Sopenharmony_ci    return 1;
389e1051a39Sopenharmony_ci}
390e1051a39Sopenharmony_ci
391e1051a39Sopenharmony_ci#  define aesni_ocb_cipher aes_ocb_cipher
392e1051a39Sopenharmony_cistatic int aesni_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
393e1051a39Sopenharmony_ci                            const unsigned char *in, size_t len);
394e1051a39Sopenharmony_ci# endif                        /* OPENSSL_NO_OCB */
395e1051a39Sopenharmony_ci
396e1051a39Sopenharmony_ci# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \
397e1051a39Sopenharmony_cistatic const EVP_CIPHER aesni_##keylen##_##mode = { \
398e1051a39Sopenharmony_ci        nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \
399e1051a39Sopenharmony_ci        flags|EVP_CIPH_##MODE##_MODE,   \
400e1051a39Sopenharmony_ci        EVP_ORIG_GLOBAL,                \
401e1051a39Sopenharmony_ci        aesni_init_key,                 \
402e1051a39Sopenharmony_ci        aesni_##mode##_cipher,          \
403e1051a39Sopenharmony_ci        NULL,                           \
404e1051a39Sopenharmony_ci        sizeof(EVP_AES_KEY),            \
405e1051a39Sopenharmony_ci        NULL,NULL,NULL,NULL }; \
406e1051a39Sopenharmony_cistatic const EVP_CIPHER aes_##keylen##_##mode = { \
407e1051a39Sopenharmony_ci        nid##_##keylen##_##nmode,blocksize,     \
408e1051a39Sopenharmony_ci        keylen/8,ivlen,                 \
409e1051a39Sopenharmony_ci        flags|EVP_CIPH_##MODE##_MODE,   \
410e1051a39Sopenharmony_ci        EVP_ORIG_GLOBAL,                 \
411e1051a39Sopenharmony_ci        aes_init_key,                   \
412e1051a39Sopenharmony_ci        aes_##mode##_cipher,            \
413e1051a39Sopenharmony_ci        NULL,                           \
414e1051a39Sopenharmony_ci        sizeof(EVP_AES_KEY),            \
415e1051a39Sopenharmony_ci        NULL,NULL,NULL,NULL }; \
416e1051a39Sopenharmony_ciconst EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
417e1051a39Sopenharmony_ci{ return AESNI_CAPABLE?&aesni_##keylen##_##mode:&aes_##keylen##_##mode; }
418e1051a39Sopenharmony_ci
419e1051a39Sopenharmony_ci# define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags) \
420e1051a39Sopenharmony_cistatic const EVP_CIPHER aesni_##keylen##_##mode = { \
421e1051a39Sopenharmony_ci        nid##_##keylen##_##mode,blocksize, \
422e1051a39Sopenharmony_ci        (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE||EVP_CIPH_##MODE##_MODE==EVP_CIPH_SIV_MODE?2:1)*keylen/8, \
423e1051a39Sopenharmony_ci        ivlen,                          \
424e1051a39Sopenharmony_ci        flags|EVP_CIPH_##MODE##_MODE,   \
425e1051a39Sopenharmony_ci        EVP_ORIG_GLOBAL,                \
426e1051a39Sopenharmony_ci        aesni_##mode##_init_key,        \
427e1051a39Sopenharmony_ci        aesni_##mode##_cipher,          \
428e1051a39Sopenharmony_ci        aes_##mode##_cleanup,           \
429e1051a39Sopenharmony_ci        sizeof(EVP_AES_##MODE##_CTX),   \
430e1051a39Sopenharmony_ci        NULL,NULL,aes_##mode##_ctrl,NULL }; \
431e1051a39Sopenharmony_cistatic const EVP_CIPHER aes_##keylen##_##mode = { \
432e1051a39Sopenharmony_ci        nid##_##keylen##_##mode,blocksize, \
433e1051a39Sopenharmony_ci        (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE||EVP_CIPH_##MODE##_MODE==EVP_CIPH_SIV_MODE?2:1)*keylen/8, \
434e1051a39Sopenharmony_ci        ivlen,                          \
435e1051a39Sopenharmony_ci        flags|EVP_CIPH_##MODE##_MODE,   \
436e1051a39Sopenharmony_ci        EVP_ORIG_GLOBAL,                \
437e1051a39Sopenharmony_ci        aes_##mode##_init_key,          \
438e1051a39Sopenharmony_ci        aes_##mode##_cipher,            \
439e1051a39Sopenharmony_ci        aes_##mode##_cleanup,           \
440e1051a39Sopenharmony_ci        sizeof(EVP_AES_##MODE##_CTX),   \
441e1051a39Sopenharmony_ci        NULL,NULL,aes_##mode##_ctrl,NULL }; \
442e1051a39Sopenharmony_ciconst EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
443e1051a39Sopenharmony_ci{ return AESNI_CAPABLE?&aesni_##keylen##_##mode:&aes_##keylen##_##mode; }
444e1051a39Sopenharmony_ci
445e1051a39Sopenharmony_ci#elif defined(SPARC_AES_CAPABLE)
446e1051a39Sopenharmony_ci
447e1051a39Sopenharmony_cistatic int aes_t4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
448e1051a39Sopenharmony_ci                           const unsigned char *iv, int enc)
449e1051a39Sopenharmony_ci{
450e1051a39Sopenharmony_ci    int ret, mode, bits;
451e1051a39Sopenharmony_ci    EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
452e1051a39Sopenharmony_ci
453e1051a39Sopenharmony_ci    mode = EVP_CIPHER_CTX_get_mode(ctx);
454e1051a39Sopenharmony_ci    bits = EVP_CIPHER_CTX_get_key_length(ctx) * 8;
455e1051a39Sopenharmony_ci    if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE)
456e1051a39Sopenharmony_ci        && !enc) {
457e1051a39Sopenharmony_ci        ret = 0;
458e1051a39Sopenharmony_ci        aes_t4_set_decrypt_key(key, bits, &dat->ks.ks);
459e1051a39Sopenharmony_ci        dat->block = (block128_f) aes_t4_decrypt;
460e1051a39Sopenharmony_ci        switch (bits) {
461e1051a39Sopenharmony_ci        case 128:
462e1051a39Sopenharmony_ci            dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
463e1051a39Sopenharmony_ci                (cbc128_f) aes128_t4_cbc_decrypt : NULL;
464e1051a39Sopenharmony_ci            break;
465e1051a39Sopenharmony_ci        case 192:
466e1051a39Sopenharmony_ci            dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
467e1051a39Sopenharmony_ci                (cbc128_f) aes192_t4_cbc_decrypt : NULL;
468e1051a39Sopenharmony_ci            break;
469e1051a39Sopenharmony_ci        case 256:
470e1051a39Sopenharmony_ci            dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
471e1051a39Sopenharmony_ci                (cbc128_f) aes256_t4_cbc_decrypt : NULL;
472e1051a39Sopenharmony_ci            break;
473e1051a39Sopenharmony_ci        default:
474e1051a39Sopenharmony_ci            ret = -1;
475e1051a39Sopenharmony_ci        }
476e1051a39Sopenharmony_ci    } else {
477e1051a39Sopenharmony_ci        ret = 0;
478e1051a39Sopenharmony_ci        aes_t4_set_encrypt_key(key, bits, &dat->ks.ks);
479e1051a39Sopenharmony_ci        dat->block = (block128_f) aes_t4_encrypt;
480e1051a39Sopenharmony_ci        switch (bits) {
481e1051a39Sopenharmony_ci        case 128:
482e1051a39Sopenharmony_ci            if (mode == EVP_CIPH_CBC_MODE)
483e1051a39Sopenharmony_ci                dat->stream.cbc = (cbc128_f) aes128_t4_cbc_encrypt;
484e1051a39Sopenharmony_ci            else if (mode == EVP_CIPH_CTR_MODE)
485e1051a39Sopenharmony_ci                dat->stream.ctr = (ctr128_f) aes128_t4_ctr32_encrypt;
486e1051a39Sopenharmony_ci            else
487e1051a39Sopenharmony_ci                dat->stream.cbc = NULL;
488e1051a39Sopenharmony_ci            break;
489e1051a39Sopenharmony_ci        case 192:
490e1051a39Sopenharmony_ci            if (mode == EVP_CIPH_CBC_MODE)
491e1051a39Sopenharmony_ci                dat->stream.cbc = (cbc128_f) aes192_t4_cbc_encrypt;
492e1051a39Sopenharmony_ci            else if (mode == EVP_CIPH_CTR_MODE)
493e1051a39Sopenharmony_ci                dat->stream.ctr = (ctr128_f) aes192_t4_ctr32_encrypt;
494e1051a39Sopenharmony_ci            else
495e1051a39Sopenharmony_ci                dat->stream.cbc = NULL;
496e1051a39Sopenharmony_ci            break;
497e1051a39Sopenharmony_ci        case 256:
498e1051a39Sopenharmony_ci            if (mode == EVP_CIPH_CBC_MODE)
499e1051a39Sopenharmony_ci                dat->stream.cbc = (cbc128_f) aes256_t4_cbc_encrypt;
500e1051a39Sopenharmony_ci            else if (mode == EVP_CIPH_CTR_MODE)
501e1051a39Sopenharmony_ci                dat->stream.ctr = (ctr128_f) aes256_t4_ctr32_encrypt;
502e1051a39Sopenharmony_ci            else
503e1051a39Sopenharmony_ci                dat->stream.cbc = NULL;
504e1051a39Sopenharmony_ci            break;
505e1051a39Sopenharmony_ci        default:
506e1051a39Sopenharmony_ci            ret = -1;
507e1051a39Sopenharmony_ci        }
508e1051a39Sopenharmony_ci    }
509e1051a39Sopenharmony_ci
510e1051a39Sopenharmony_ci    if (ret < 0) {
511e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EVP, EVP_R_AES_KEY_SETUP_FAILED);
512e1051a39Sopenharmony_ci        return 0;
513e1051a39Sopenharmony_ci    }
514e1051a39Sopenharmony_ci
515e1051a39Sopenharmony_ci    return 1;
516e1051a39Sopenharmony_ci}
517e1051a39Sopenharmony_ci
518e1051a39Sopenharmony_ci# define aes_t4_cbc_cipher aes_cbc_cipher
519e1051a39Sopenharmony_cistatic int aes_t4_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
520e1051a39Sopenharmony_ci                             const unsigned char *in, size_t len);
521e1051a39Sopenharmony_ci
522e1051a39Sopenharmony_ci# define aes_t4_ecb_cipher aes_ecb_cipher
523e1051a39Sopenharmony_cistatic int aes_t4_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
524e1051a39Sopenharmony_ci                             const unsigned char *in, size_t len);
525e1051a39Sopenharmony_ci
526e1051a39Sopenharmony_ci# define aes_t4_ofb_cipher aes_ofb_cipher
527e1051a39Sopenharmony_cistatic int aes_t4_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
528e1051a39Sopenharmony_ci                             const unsigned char *in, size_t len);
529e1051a39Sopenharmony_ci
530e1051a39Sopenharmony_ci# define aes_t4_cfb_cipher aes_cfb_cipher
531e1051a39Sopenharmony_cistatic int aes_t4_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
532e1051a39Sopenharmony_ci                             const unsigned char *in, size_t len);
533e1051a39Sopenharmony_ci
534e1051a39Sopenharmony_ci# define aes_t4_cfb8_cipher aes_cfb8_cipher
535e1051a39Sopenharmony_cistatic int aes_t4_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
536e1051a39Sopenharmony_ci                              const unsigned char *in, size_t len);
537e1051a39Sopenharmony_ci
538e1051a39Sopenharmony_ci# define aes_t4_cfb1_cipher aes_cfb1_cipher
539e1051a39Sopenharmony_cistatic int aes_t4_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
540e1051a39Sopenharmony_ci                              const unsigned char *in, size_t len);
541e1051a39Sopenharmony_ci
542e1051a39Sopenharmony_ci# define aes_t4_ctr_cipher aes_ctr_cipher
543e1051a39Sopenharmony_cistatic int aes_t4_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
544e1051a39Sopenharmony_ci                             const unsigned char *in, size_t len);
545e1051a39Sopenharmony_ci
546e1051a39Sopenharmony_cistatic int aes_t4_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
547e1051a39Sopenharmony_ci                               const unsigned char *iv, int enc)
548e1051a39Sopenharmony_ci{
549e1051a39Sopenharmony_ci    EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx);
550e1051a39Sopenharmony_ci    if (!iv && !key)
551e1051a39Sopenharmony_ci        return 1;
552e1051a39Sopenharmony_ci    if (key) {
553e1051a39Sopenharmony_ci        int bits = EVP_CIPHER_CTX_get_key_length(ctx) * 8;
554e1051a39Sopenharmony_ci        aes_t4_set_encrypt_key(key, bits, &gctx->ks.ks);
555e1051a39Sopenharmony_ci        CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks,
556e1051a39Sopenharmony_ci                           (block128_f) aes_t4_encrypt);
557e1051a39Sopenharmony_ci        switch (bits) {
558e1051a39Sopenharmony_ci        case 128:
559e1051a39Sopenharmony_ci            gctx->ctr = (ctr128_f) aes128_t4_ctr32_encrypt;
560e1051a39Sopenharmony_ci            break;
561e1051a39Sopenharmony_ci        case 192:
562e1051a39Sopenharmony_ci            gctx->ctr = (ctr128_f) aes192_t4_ctr32_encrypt;
563e1051a39Sopenharmony_ci            break;
564e1051a39Sopenharmony_ci        case 256:
565e1051a39Sopenharmony_ci            gctx->ctr = (ctr128_f) aes256_t4_ctr32_encrypt;
566e1051a39Sopenharmony_ci            break;
567e1051a39Sopenharmony_ci        default:
568e1051a39Sopenharmony_ci            return 0;
569e1051a39Sopenharmony_ci        }
570e1051a39Sopenharmony_ci        /*
571e1051a39Sopenharmony_ci         * If we have an iv can set it directly, otherwise use saved IV.
572e1051a39Sopenharmony_ci         */
573e1051a39Sopenharmony_ci        if (iv == NULL && gctx->iv_set)
574e1051a39Sopenharmony_ci            iv = gctx->iv;
575e1051a39Sopenharmony_ci        if (iv) {
576e1051a39Sopenharmony_ci            CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen);
577e1051a39Sopenharmony_ci            gctx->iv_set = 1;
578e1051a39Sopenharmony_ci        }
579e1051a39Sopenharmony_ci        gctx->key_set = 1;
580e1051a39Sopenharmony_ci    } else {
581e1051a39Sopenharmony_ci        /* If key set use IV, otherwise copy */
582e1051a39Sopenharmony_ci        if (gctx->key_set)
583e1051a39Sopenharmony_ci            CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen);
584e1051a39Sopenharmony_ci        else
585e1051a39Sopenharmony_ci            memcpy(gctx->iv, iv, gctx->ivlen);
586e1051a39Sopenharmony_ci        gctx->iv_set = 1;
587e1051a39Sopenharmony_ci        gctx->iv_gen = 0;
588e1051a39Sopenharmony_ci    }
589e1051a39Sopenharmony_ci    return 1;
590e1051a39Sopenharmony_ci}
591e1051a39Sopenharmony_ci
592e1051a39Sopenharmony_ci# define aes_t4_gcm_cipher aes_gcm_cipher
593e1051a39Sopenharmony_cistatic int aes_t4_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
594e1051a39Sopenharmony_ci                             const unsigned char *in, size_t len);
595e1051a39Sopenharmony_ci
596e1051a39Sopenharmony_cistatic int aes_t4_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
597e1051a39Sopenharmony_ci                               const unsigned char *iv, int enc)
598e1051a39Sopenharmony_ci{
599e1051a39Sopenharmony_ci    EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,ctx);
600e1051a39Sopenharmony_ci
601e1051a39Sopenharmony_ci    if (!iv && !key)
602e1051a39Sopenharmony_ci        return 1;
603e1051a39Sopenharmony_ci
604e1051a39Sopenharmony_ci    if (key) {
605e1051a39Sopenharmony_ci        /* The key is two half length keys in reality */
606e1051a39Sopenharmony_ci        const int bytes = EVP_CIPHER_CTX_get_key_length(ctx) / 2;
607e1051a39Sopenharmony_ci        const int bits = bytes * 8;
608e1051a39Sopenharmony_ci
609e1051a39Sopenharmony_ci        /*
610e1051a39Sopenharmony_ci         * Verify that the two keys are different.
611e1051a39Sopenharmony_ci         *
612e1051a39Sopenharmony_ci         * This addresses Rogaway's vulnerability.
613e1051a39Sopenharmony_ci         * See comment in aes_xts_init_key() below.
614e1051a39Sopenharmony_ci         */
615e1051a39Sopenharmony_ci        if ((!allow_insecure_decrypt || enc)
616e1051a39Sopenharmony_ci                && CRYPTO_memcmp(key, key + bytes, bytes) == 0) {
617e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_EVP, EVP_R_XTS_DUPLICATED_KEYS);
618e1051a39Sopenharmony_ci            return 0;
619e1051a39Sopenharmony_ci        }
620e1051a39Sopenharmony_ci
621e1051a39Sopenharmony_ci        xctx->stream = NULL;
622e1051a39Sopenharmony_ci        /* key_len is two AES keys */
623e1051a39Sopenharmony_ci        if (enc) {
624e1051a39Sopenharmony_ci            aes_t4_set_encrypt_key(key, bits, &xctx->ks1.ks);
625e1051a39Sopenharmony_ci            xctx->xts.block1 = (block128_f) aes_t4_encrypt;
626e1051a39Sopenharmony_ci            switch (bits) {
627e1051a39Sopenharmony_ci            case 128:
628e1051a39Sopenharmony_ci                xctx->stream = aes128_t4_xts_encrypt;
629e1051a39Sopenharmony_ci                break;
630e1051a39Sopenharmony_ci            case 256:
631e1051a39Sopenharmony_ci                xctx->stream = aes256_t4_xts_encrypt;
632e1051a39Sopenharmony_ci                break;
633e1051a39Sopenharmony_ci            default:
634e1051a39Sopenharmony_ci                return 0;
635e1051a39Sopenharmony_ci            }
636e1051a39Sopenharmony_ci        } else {
637e1051a39Sopenharmony_ci            aes_t4_set_decrypt_key(key, bits, &xctx->ks1.ks);
638e1051a39Sopenharmony_ci            xctx->xts.block1 = (block128_f) aes_t4_decrypt;
639e1051a39Sopenharmony_ci            switch (bits) {
640e1051a39Sopenharmony_ci            case 128:
641e1051a39Sopenharmony_ci                xctx->stream = aes128_t4_xts_decrypt;
642e1051a39Sopenharmony_ci                break;
643e1051a39Sopenharmony_ci            case 256:
644e1051a39Sopenharmony_ci                xctx->stream = aes256_t4_xts_decrypt;
645e1051a39Sopenharmony_ci                break;
646e1051a39Sopenharmony_ci            default:
647e1051a39Sopenharmony_ci                return 0;
648e1051a39Sopenharmony_ci            }
649e1051a39Sopenharmony_ci        }
650e1051a39Sopenharmony_ci
651e1051a39Sopenharmony_ci        aes_t4_set_encrypt_key(key + bytes, bits, &xctx->ks2.ks);
652e1051a39Sopenharmony_ci        xctx->xts.block2 = (block128_f) aes_t4_encrypt;
653e1051a39Sopenharmony_ci
654e1051a39Sopenharmony_ci        xctx->xts.key1 = &xctx->ks1;
655e1051a39Sopenharmony_ci    }
656e1051a39Sopenharmony_ci
657e1051a39Sopenharmony_ci    if (iv) {
658e1051a39Sopenharmony_ci        xctx->xts.key2 = &xctx->ks2;
659e1051a39Sopenharmony_ci        memcpy(ctx->iv, iv, 16);
660e1051a39Sopenharmony_ci    }
661e1051a39Sopenharmony_ci
662e1051a39Sopenharmony_ci    return 1;
663e1051a39Sopenharmony_ci}
664e1051a39Sopenharmony_ci
665e1051a39Sopenharmony_ci# define aes_t4_xts_cipher aes_xts_cipher
666e1051a39Sopenharmony_cistatic int aes_t4_xts_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
667e1051a39Sopenharmony_ci                             const unsigned char *in, size_t len);
668e1051a39Sopenharmony_ci
669e1051a39Sopenharmony_cistatic int aes_t4_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
670e1051a39Sopenharmony_ci                               const unsigned char *iv, int enc)
671e1051a39Sopenharmony_ci{
672e1051a39Sopenharmony_ci    EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx);
673e1051a39Sopenharmony_ci    if (!iv && !key)
674e1051a39Sopenharmony_ci        return 1;
675e1051a39Sopenharmony_ci    if (key) {
676e1051a39Sopenharmony_ci        int bits = EVP_CIPHER_CTX_get_key_length(ctx) * 8;
677e1051a39Sopenharmony_ci        aes_t4_set_encrypt_key(key, bits, &cctx->ks.ks);
678e1051a39Sopenharmony_ci        CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L,
679e1051a39Sopenharmony_ci                           &cctx->ks, (block128_f) aes_t4_encrypt);
680e1051a39Sopenharmony_ci        cctx->str = NULL;
681e1051a39Sopenharmony_ci        cctx->key_set = 1;
682e1051a39Sopenharmony_ci    }
683e1051a39Sopenharmony_ci    if (iv) {
684e1051a39Sopenharmony_ci        memcpy(ctx->iv, iv, 15 - cctx->L);
685e1051a39Sopenharmony_ci        cctx->iv_set = 1;
686e1051a39Sopenharmony_ci    }
687e1051a39Sopenharmony_ci    return 1;
688e1051a39Sopenharmony_ci}
689e1051a39Sopenharmony_ci
690e1051a39Sopenharmony_ci# define aes_t4_ccm_cipher aes_ccm_cipher
691e1051a39Sopenharmony_cistatic int aes_t4_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
692e1051a39Sopenharmony_ci                             const unsigned char *in, size_t len);
693e1051a39Sopenharmony_ci
694e1051a39Sopenharmony_ci# ifndef OPENSSL_NO_OCB
695e1051a39Sopenharmony_cistatic int aes_t4_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
696e1051a39Sopenharmony_ci                               const unsigned char *iv, int enc)
697e1051a39Sopenharmony_ci{
698e1051a39Sopenharmony_ci    EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,ctx);
699e1051a39Sopenharmony_ci    if (!iv && !key)
700e1051a39Sopenharmony_ci        return 1;
701e1051a39Sopenharmony_ci    if (key) {
702e1051a39Sopenharmony_ci        do {
703e1051a39Sopenharmony_ci            /*
704e1051a39Sopenharmony_ci             * We set both the encrypt and decrypt key here because decrypt
705e1051a39Sopenharmony_ci             * needs both. We could possibly optimise to remove setting the
706e1051a39Sopenharmony_ci             * decrypt for an encryption operation.
707e1051a39Sopenharmony_ci             */
708e1051a39Sopenharmony_ci            aes_t4_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
709e1051a39Sopenharmony_ci                                   &octx->ksenc.ks);
710e1051a39Sopenharmony_ci            aes_t4_set_decrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
711e1051a39Sopenharmony_ci                                   &octx->ksdec.ks);
712e1051a39Sopenharmony_ci            if (!CRYPTO_ocb128_init(&octx->ocb,
713e1051a39Sopenharmony_ci                                    &octx->ksenc.ks, &octx->ksdec.ks,
714e1051a39Sopenharmony_ci                                    (block128_f) aes_t4_encrypt,
715e1051a39Sopenharmony_ci                                    (block128_f) aes_t4_decrypt,
716e1051a39Sopenharmony_ci                                    NULL))
717e1051a39Sopenharmony_ci                return 0;
718e1051a39Sopenharmony_ci        }
719e1051a39Sopenharmony_ci        while (0);
720e1051a39Sopenharmony_ci
721e1051a39Sopenharmony_ci        /*
722e1051a39Sopenharmony_ci         * If we have an iv we can set it directly, otherwise use saved IV.
723e1051a39Sopenharmony_ci         */
724e1051a39Sopenharmony_ci        if (iv == NULL && octx->iv_set)
725e1051a39Sopenharmony_ci            iv = octx->iv;
726e1051a39Sopenharmony_ci        if (iv) {
727e1051a39Sopenharmony_ci            if (CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen)
728e1051a39Sopenharmony_ci                != 1)
729e1051a39Sopenharmony_ci                return 0;
730e1051a39Sopenharmony_ci            octx->iv_set = 1;
731e1051a39Sopenharmony_ci        }
732e1051a39Sopenharmony_ci        octx->key_set = 1;
733e1051a39Sopenharmony_ci    } else {
734e1051a39Sopenharmony_ci        /* If key set use IV, otherwise copy */
735e1051a39Sopenharmony_ci        if (octx->key_set)
736e1051a39Sopenharmony_ci            CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen);
737e1051a39Sopenharmony_ci        else
738e1051a39Sopenharmony_ci            memcpy(octx->iv, iv, octx->ivlen);
739e1051a39Sopenharmony_ci        octx->iv_set = 1;
740e1051a39Sopenharmony_ci    }
741e1051a39Sopenharmony_ci    return 1;
742e1051a39Sopenharmony_ci}
743e1051a39Sopenharmony_ci
744e1051a39Sopenharmony_ci#  define aes_t4_ocb_cipher aes_ocb_cipher
745e1051a39Sopenharmony_cistatic int aes_t4_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
746e1051a39Sopenharmony_ci                             const unsigned char *in, size_t len);
747e1051a39Sopenharmony_ci# endif                        /* OPENSSL_NO_OCB */
748e1051a39Sopenharmony_ci
749e1051a39Sopenharmony_ci# ifndef OPENSSL_NO_SIV
750e1051a39Sopenharmony_ci#  define aes_t4_siv_init_key aes_siv_init_key
751e1051a39Sopenharmony_ci#  define aes_t4_siv_cipher aes_siv_cipher
752e1051a39Sopenharmony_ci# endif /* OPENSSL_NO_SIV */
753e1051a39Sopenharmony_ci
754e1051a39Sopenharmony_ci# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \
755e1051a39Sopenharmony_cistatic const EVP_CIPHER aes_t4_##keylen##_##mode = { \
756e1051a39Sopenharmony_ci        nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \
757e1051a39Sopenharmony_ci        flags|EVP_CIPH_##MODE##_MODE,   \
758e1051a39Sopenharmony_ci        EVP_ORIG_GLOBAL,                \
759e1051a39Sopenharmony_ci        aes_t4_init_key,                \
760e1051a39Sopenharmony_ci        aes_t4_##mode##_cipher,         \
761e1051a39Sopenharmony_ci        NULL,                           \
762e1051a39Sopenharmony_ci        sizeof(EVP_AES_KEY),            \
763e1051a39Sopenharmony_ci        NULL,NULL,NULL,NULL }; \
764e1051a39Sopenharmony_cistatic const EVP_CIPHER aes_##keylen##_##mode = { \
765e1051a39Sopenharmony_ci        nid##_##keylen##_##nmode,blocksize,     \
766e1051a39Sopenharmony_ci        keylen/8,ivlen, \
767e1051a39Sopenharmony_ci        flags|EVP_CIPH_##MODE##_MODE,   \
768e1051a39Sopenharmony_ci        EVP_ORIG_GLOBAL,                \
769e1051a39Sopenharmony_ci        aes_init_key,                   \
770e1051a39Sopenharmony_ci        aes_##mode##_cipher,            \
771e1051a39Sopenharmony_ci        NULL,                           \
772e1051a39Sopenharmony_ci        sizeof(EVP_AES_KEY),            \
773e1051a39Sopenharmony_ci        NULL,NULL,NULL,NULL }; \
774e1051a39Sopenharmony_ciconst EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
775e1051a39Sopenharmony_ci{ return SPARC_AES_CAPABLE?&aes_t4_##keylen##_##mode:&aes_##keylen##_##mode; }
776e1051a39Sopenharmony_ci
777e1051a39Sopenharmony_ci# define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags) \
778e1051a39Sopenharmony_cistatic const EVP_CIPHER aes_t4_##keylen##_##mode = { \
779e1051a39Sopenharmony_ci        nid##_##keylen##_##mode,blocksize, \
780e1051a39Sopenharmony_ci        (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE||EVP_CIPH_##MODE##_MODE==EVP_CIPH_SIV_MODE?2:1)*keylen/8, \
781e1051a39Sopenharmony_ci        ivlen,                          \
782e1051a39Sopenharmony_ci        flags|EVP_CIPH_##MODE##_MODE,   \
783e1051a39Sopenharmony_ci        EVP_ORIG_GLOBAL,                \
784e1051a39Sopenharmony_ci        aes_t4_##mode##_init_key,       \
785e1051a39Sopenharmony_ci        aes_t4_##mode##_cipher,         \
786e1051a39Sopenharmony_ci        aes_##mode##_cleanup,           \
787e1051a39Sopenharmony_ci        sizeof(EVP_AES_##MODE##_CTX),   \
788e1051a39Sopenharmony_ci        NULL,NULL,aes_##mode##_ctrl,NULL }; \
789e1051a39Sopenharmony_cistatic const EVP_CIPHER aes_##keylen##_##mode = { \
790e1051a39Sopenharmony_ci        nid##_##keylen##_##mode,blocksize, \
791e1051a39Sopenharmony_ci        (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE||EVP_CIPH_##MODE##_MODE==EVP_CIPH_SIV_MODE?2:1)*keylen/8, \
792e1051a39Sopenharmony_ci        ivlen,                          \
793e1051a39Sopenharmony_ci        flags|EVP_CIPH_##MODE##_MODE,   \
794e1051a39Sopenharmony_ci        EVP_ORIG_GLOBAL,                \
795e1051a39Sopenharmony_ci        aes_##mode##_init_key,          \
796e1051a39Sopenharmony_ci        aes_##mode##_cipher,            \
797e1051a39Sopenharmony_ci        aes_##mode##_cleanup,           \
798e1051a39Sopenharmony_ci        sizeof(EVP_AES_##MODE##_CTX),   \
799e1051a39Sopenharmony_ci        NULL,NULL,aes_##mode##_ctrl,NULL }; \
800e1051a39Sopenharmony_ciconst EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
801e1051a39Sopenharmony_ci{ return SPARC_AES_CAPABLE?&aes_t4_##keylen##_##mode:&aes_##keylen##_##mode; }
802e1051a39Sopenharmony_ci
803e1051a39Sopenharmony_ci#elif defined(S390X_aes_128_CAPABLE)
804e1051a39Sopenharmony_ci/* IBM S390X support */
805e1051a39Sopenharmony_citypedef struct {
806e1051a39Sopenharmony_ci    union {
807e1051a39Sopenharmony_ci        OSSL_UNION_ALIGN;
808e1051a39Sopenharmony_ci        /*-
809e1051a39Sopenharmony_ci         * KM-AES parameter block - begin
810e1051a39Sopenharmony_ci         * (see z/Architecture Principles of Operation >= SA22-7832-06)
811e1051a39Sopenharmony_ci         */
812e1051a39Sopenharmony_ci        struct {
813e1051a39Sopenharmony_ci            unsigned char k[32];
814e1051a39Sopenharmony_ci        } param;
815e1051a39Sopenharmony_ci        /* KM-AES parameter block - end */
816e1051a39Sopenharmony_ci    } km;
817e1051a39Sopenharmony_ci    unsigned int fc;
818e1051a39Sopenharmony_ci} S390X_AES_ECB_CTX;
819e1051a39Sopenharmony_ci
820e1051a39Sopenharmony_citypedef struct {
821e1051a39Sopenharmony_ci    union {
822e1051a39Sopenharmony_ci        OSSL_UNION_ALIGN;
823e1051a39Sopenharmony_ci        /*-
824e1051a39Sopenharmony_ci         * KMO-AES parameter block - begin
825e1051a39Sopenharmony_ci         * (see z/Architecture Principles of Operation >= SA22-7832-08)
826e1051a39Sopenharmony_ci         */
827e1051a39Sopenharmony_ci        struct {
828e1051a39Sopenharmony_ci            unsigned char cv[16];
829e1051a39Sopenharmony_ci            unsigned char k[32];
830e1051a39Sopenharmony_ci        } param;
831e1051a39Sopenharmony_ci        /* KMO-AES parameter block - end */
832e1051a39Sopenharmony_ci    } kmo;
833e1051a39Sopenharmony_ci    unsigned int fc;
834e1051a39Sopenharmony_ci
835e1051a39Sopenharmony_ci    int res;
836e1051a39Sopenharmony_ci} S390X_AES_OFB_CTX;
837e1051a39Sopenharmony_ci
838e1051a39Sopenharmony_citypedef struct {
839e1051a39Sopenharmony_ci    union {
840e1051a39Sopenharmony_ci        OSSL_UNION_ALIGN;
841e1051a39Sopenharmony_ci        /*-
842e1051a39Sopenharmony_ci         * KMF-AES parameter block - begin
843e1051a39Sopenharmony_ci         * (see z/Architecture Principles of Operation >= SA22-7832-08)
844e1051a39Sopenharmony_ci         */
845e1051a39Sopenharmony_ci        struct {
846e1051a39Sopenharmony_ci            unsigned char cv[16];
847e1051a39Sopenharmony_ci            unsigned char k[32];
848e1051a39Sopenharmony_ci        } param;
849e1051a39Sopenharmony_ci        /* KMF-AES parameter block - end */
850e1051a39Sopenharmony_ci    } kmf;
851e1051a39Sopenharmony_ci    unsigned int fc;
852e1051a39Sopenharmony_ci
853e1051a39Sopenharmony_ci    int res;
854e1051a39Sopenharmony_ci} S390X_AES_CFB_CTX;
855e1051a39Sopenharmony_ci
856e1051a39Sopenharmony_citypedef struct {
857e1051a39Sopenharmony_ci    union {
858e1051a39Sopenharmony_ci        OSSL_UNION_ALIGN;
859e1051a39Sopenharmony_ci        /*-
860e1051a39Sopenharmony_ci         * KMA-GCM-AES parameter block - begin
861e1051a39Sopenharmony_ci         * (see z/Architecture Principles of Operation >= SA22-7832-11)
862e1051a39Sopenharmony_ci         */
863e1051a39Sopenharmony_ci        struct {
864e1051a39Sopenharmony_ci            unsigned char reserved[12];
865e1051a39Sopenharmony_ci            union {
866e1051a39Sopenharmony_ci                unsigned int w;
867e1051a39Sopenharmony_ci                unsigned char b[4];
868e1051a39Sopenharmony_ci            } cv;
869e1051a39Sopenharmony_ci            union {
870e1051a39Sopenharmony_ci                unsigned long long g[2];
871e1051a39Sopenharmony_ci                unsigned char b[16];
872e1051a39Sopenharmony_ci            } t;
873e1051a39Sopenharmony_ci            unsigned char h[16];
874e1051a39Sopenharmony_ci            unsigned long long taadl;
875e1051a39Sopenharmony_ci            unsigned long long tpcl;
876e1051a39Sopenharmony_ci            union {
877e1051a39Sopenharmony_ci                unsigned long long g[2];
878e1051a39Sopenharmony_ci                unsigned int w[4];
879e1051a39Sopenharmony_ci            } j0;
880e1051a39Sopenharmony_ci            unsigned char k[32];
881e1051a39Sopenharmony_ci        } param;
882e1051a39Sopenharmony_ci        /* KMA-GCM-AES parameter block - end */
883e1051a39Sopenharmony_ci    } kma;
884e1051a39Sopenharmony_ci    unsigned int fc;
885e1051a39Sopenharmony_ci    int key_set;
886e1051a39Sopenharmony_ci
887e1051a39Sopenharmony_ci    unsigned char *iv;
888e1051a39Sopenharmony_ci    int ivlen;
889e1051a39Sopenharmony_ci    int iv_set;
890e1051a39Sopenharmony_ci    int iv_gen;
891e1051a39Sopenharmony_ci
892e1051a39Sopenharmony_ci    int taglen;
893e1051a39Sopenharmony_ci
894e1051a39Sopenharmony_ci    unsigned char ares[16];
895e1051a39Sopenharmony_ci    unsigned char mres[16];
896e1051a39Sopenharmony_ci    unsigned char kres[16];
897e1051a39Sopenharmony_ci    int areslen;
898e1051a39Sopenharmony_ci    int mreslen;
899e1051a39Sopenharmony_ci    int kreslen;
900e1051a39Sopenharmony_ci
901e1051a39Sopenharmony_ci    int tls_aad_len;
902e1051a39Sopenharmony_ci    uint64_t tls_enc_records;   /* Number of TLS records encrypted */
903e1051a39Sopenharmony_ci} S390X_AES_GCM_CTX;
904e1051a39Sopenharmony_ci
905e1051a39Sopenharmony_citypedef struct {
906e1051a39Sopenharmony_ci    union {
907e1051a39Sopenharmony_ci        OSSL_UNION_ALIGN;
908e1051a39Sopenharmony_ci        /*-
909e1051a39Sopenharmony_ci         * Padding is chosen so that ccm.kmac_param.k overlaps with key.k and
910e1051a39Sopenharmony_ci         * ccm.fc with key.k.rounds. Remember that on s390x, an AES_KEY's
911e1051a39Sopenharmony_ci         * rounds field is used to store the function code and that the key
912e1051a39Sopenharmony_ci         * schedule is not stored (if aes hardware support is detected).
913e1051a39Sopenharmony_ci         */
914e1051a39Sopenharmony_ci        struct {
915e1051a39Sopenharmony_ci            unsigned char pad[16];
916e1051a39Sopenharmony_ci            AES_KEY k;
917e1051a39Sopenharmony_ci        } key;
918e1051a39Sopenharmony_ci
919e1051a39Sopenharmony_ci        struct {
920e1051a39Sopenharmony_ci            /*-
921e1051a39Sopenharmony_ci             * KMAC-AES parameter block - begin
922e1051a39Sopenharmony_ci             * (see z/Architecture Principles of Operation >= SA22-7832-08)
923e1051a39Sopenharmony_ci             */
924e1051a39Sopenharmony_ci            struct {
925e1051a39Sopenharmony_ci                union {
926e1051a39Sopenharmony_ci                    unsigned long long g[2];
927e1051a39Sopenharmony_ci                    unsigned char b[16];
928e1051a39Sopenharmony_ci                } icv;
929e1051a39Sopenharmony_ci                unsigned char k[32];
930e1051a39Sopenharmony_ci            } kmac_param;
931e1051a39Sopenharmony_ci            /* KMAC-AES parameter block - end */
932e1051a39Sopenharmony_ci
933e1051a39Sopenharmony_ci            union {
934e1051a39Sopenharmony_ci                unsigned long long g[2];
935e1051a39Sopenharmony_ci                unsigned char b[16];
936e1051a39Sopenharmony_ci            } nonce;
937e1051a39Sopenharmony_ci            union {
938e1051a39Sopenharmony_ci                unsigned long long g[2];
939e1051a39Sopenharmony_ci                unsigned char b[16];
940e1051a39Sopenharmony_ci            } buf;
941e1051a39Sopenharmony_ci
942e1051a39Sopenharmony_ci            unsigned long long blocks;
943e1051a39Sopenharmony_ci            int l;
944e1051a39Sopenharmony_ci            int m;
945e1051a39Sopenharmony_ci            int tls_aad_len;
946e1051a39Sopenharmony_ci            int iv_set;
947e1051a39Sopenharmony_ci            int tag_set;
948e1051a39Sopenharmony_ci            int len_set;
949e1051a39Sopenharmony_ci            int key_set;
950e1051a39Sopenharmony_ci
951e1051a39Sopenharmony_ci            unsigned char pad[140];
952e1051a39Sopenharmony_ci            unsigned int fc;
953e1051a39Sopenharmony_ci        } ccm;
954e1051a39Sopenharmony_ci    } aes;
955e1051a39Sopenharmony_ci} S390X_AES_CCM_CTX;
956e1051a39Sopenharmony_ci
957e1051a39Sopenharmony_ci# define s390x_aes_init_key aes_init_key
958e1051a39Sopenharmony_cistatic int s390x_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
959e1051a39Sopenharmony_ci                              const unsigned char *iv, int enc);
960e1051a39Sopenharmony_ci
961e1051a39Sopenharmony_ci# define S390X_AES_CBC_CTX              EVP_AES_KEY
962e1051a39Sopenharmony_ci
963e1051a39Sopenharmony_ci# define s390x_aes_cbc_init_key aes_init_key
964e1051a39Sopenharmony_ci
965e1051a39Sopenharmony_ci# define s390x_aes_cbc_cipher aes_cbc_cipher
966e1051a39Sopenharmony_cistatic int s390x_aes_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
967e1051a39Sopenharmony_ci                                const unsigned char *in, size_t len);
968e1051a39Sopenharmony_ci
969e1051a39Sopenharmony_cistatic int s390x_aes_ecb_init_key(EVP_CIPHER_CTX *ctx,
970e1051a39Sopenharmony_ci                                  const unsigned char *key,
971e1051a39Sopenharmony_ci                                  const unsigned char *iv, int enc)
972e1051a39Sopenharmony_ci{
973e1051a39Sopenharmony_ci    S390X_AES_ECB_CTX *cctx = EVP_C_DATA(S390X_AES_ECB_CTX, ctx);
974e1051a39Sopenharmony_ci    const int keylen = EVP_CIPHER_CTX_get_key_length(ctx);
975e1051a39Sopenharmony_ci
976e1051a39Sopenharmony_ci    cctx->fc = S390X_AES_FC(keylen);
977e1051a39Sopenharmony_ci    if (!enc)
978e1051a39Sopenharmony_ci        cctx->fc |= S390X_DECRYPT;
979e1051a39Sopenharmony_ci
980e1051a39Sopenharmony_ci    memcpy(cctx->km.param.k, key, keylen);
981e1051a39Sopenharmony_ci    return 1;
982e1051a39Sopenharmony_ci}
983e1051a39Sopenharmony_ci
984e1051a39Sopenharmony_cistatic int s390x_aes_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
985e1051a39Sopenharmony_ci                                const unsigned char *in, size_t len)
986e1051a39Sopenharmony_ci{
987e1051a39Sopenharmony_ci    S390X_AES_ECB_CTX *cctx = EVP_C_DATA(S390X_AES_ECB_CTX, ctx);
988e1051a39Sopenharmony_ci
989e1051a39Sopenharmony_ci    s390x_km(in, len, out, cctx->fc, &cctx->km.param);
990e1051a39Sopenharmony_ci    return 1;
991e1051a39Sopenharmony_ci}
992e1051a39Sopenharmony_ci
993e1051a39Sopenharmony_cistatic int s390x_aes_ofb_init_key(EVP_CIPHER_CTX *ctx,
994e1051a39Sopenharmony_ci                                  const unsigned char *key,
995e1051a39Sopenharmony_ci                                  const unsigned char *ivec, int enc)
996e1051a39Sopenharmony_ci{
997e1051a39Sopenharmony_ci    S390X_AES_OFB_CTX *cctx = EVP_C_DATA(S390X_AES_OFB_CTX, ctx);
998e1051a39Sopenharmony_ci    const unsigned char *iv = ctx->oiv;
999e1051a39Sopenharmony_ci    const int keylen = EVP_CIPHER_CTX_get_key_length(ctx);
1000e1051a39Sopenharmony_ci    const int ivlen = EVP_CIPHER_CTX_get_iv_length(ctx);
1001e1051a39Sopenharmony_ci
1002e1051a39Sopenharmony_ci    memcpy(cctx->kmo.param.cv, iv, ivlen);
1003e1051a39Sopenharmony_ci    memcpy(cctx->kmo.param.k, key, keylen);
1004e1051a39Sopenharmony_ci    cctx->fc = S390X_AES_FC(keylen);
1005e1051a39Sopenharmony_ci    cctx->res = 0;
1006e1051a39Sopenharmony_ci    return 1;
1007e1051a39Sopenharmony_ci}
1008e1051a39Sopenharmony_ci
1009e1051a39Sopenharmony_cistatic int s390x_aes_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
1010e1051a39Sopenharmony_ci                                const unsigned char *in, size_t len)
1011e1051a39Sopenharmony_ci{
1012e1051a39Sopenharmony_ci    S390X_AES_OFB_CTX *cctx = EVP_C_DATA(S390X_AES_OFB_CTX, ctx);
1013e1051a39Sopenharmony_ci    const int ivlen = EVP_CIPHER_CTX_get_iv_length(ctx);
1014e1051a39Sopenharmony_ci    unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
1015e1051a39Sopenharmony_ci    int n = cctx->res;
1016e1051a39Sopenharmony_ci    int rem;
1017e1051a39Sopenharmony_ci
1018e1051a39Sopenharmony_ci    memcpy(cctx->kmo.param.cv, iv, ivlen);
1019e1051a39Sopenharmony_ci    while (n && len) {
1020e1051a39Sopenharmony_ci        *out = *in ^ cctx->kmo.param.cv[n];
1021e1051a39Sopenharmony_ci        n = (n + 1) & 0xf;
1022e1051a39Sopenharmony_ci        --len;
1023e1051a39Sopenharmony_ci        ++in;
1024e1051a39Sopenharmony_ci        ++out;
1025e1051a39Sopenharmony_ci    }
1026e1051a39Sopenharmony_ci
1027e1051a39Sopenharmony_ci    rem = len & 0xf;
1028e1051a39Sopenharmony_ci
1029e1051a39Sopenharmony_ci    len &= ~(size_t)0xf;
1030e1051a39Sopenharmony_ci    if (len) {
1031e1051a39Sopenharmony_ci        s390x_kmo(in, len, out, cctx->fc, &cctx->kmo.param);
1032e1051a39Sopenharmony_ci
1033e1051a39Sopenharmony_ci        out += len;
1034e1051a39Sopenharmony_ci        in += len;
1035e1051a39Sopenharmony_ci    }
1036e1051a39Sopenharmony_ci
1037e1051a39Sopenharmony_ci    if (rem) {
1038e1051a39Sopenharmony_ci        s390x_km(cctx->kmo.param.cv, 16, cctx->kmo.param.cv, cctx->fc,
1039e1051a39Sopenharmony_ci                 cctx->kmo.param.k);
1040e1051a39Sopenharmony_ci
1041e1051a39Sopenharmony_ci        while (rem--) {
1042e1051a39Sopenharmony_ci            out[n] = in[n] ^ cctx->kmo.param.cv[n];
1043e1051a39Sopenharmony_ci            ++n;
1044e1051a39Sopenharmony_ci        }
1045e1051a39Sopenharmony_ci    }
1046e1051a39Sopenharmony_ci
1047e1051a39Sopenharmony_ci    memcpy(iv, cctx->kmo.param.cv, ivlen);
1048e1051a39Sopenharmony_ci    cctx->res = n;
1049e1051a39Sopenharmony_ci    return 1;
1050e1051a39Sopenharmony_ci}
1051e1051a39Sopenharmony_ci
1052e1051a39Sopenharmony_cistatic int s390x_aes_cfb_init_key(EVP_CIPHER_CTX *ctx,
1053e1051a39Sopenharmony_ci                                  const unsigned char *key,
1054e1051a39Sopenharmony_ci                                  const unsigned char *ivec, int enc)
1055e1051a39Sopenharmony_ci{
1056e1051a39Sopenharmony_ci    S390X_AES_CFB_CTX *cctx = EVP_C_DATA(S390X_AES_CFB_CTX, ctx);
1057e1051a39Sopenharmony_ci    const unsigned char *iv = ctx->oiv;
1058e1051a39Sopenharmony_ci    const int keylen = EVP_CIPHER_CTX_get_key_length(ctx);
1059e1051a39Sopenharmony_ci    const int ivlen = EVP_CIPHER_CTX_get_iv_length(ctx);
1060e1051a39Sopenharmony_ci
1061e1051a39Sopenharmony_ci    cctx->fc = S390X_AES_FC(keylen);
1062e1051a39Sopenharmony_ci    cctx->fc |= 16 << 24;   /* 16 bytes cipher feedback */
1063e1051a39Sopenharmony_ci    if (!enc)
1064e1051a39Sopenharmony_ci        cctx->fc |= S390X_DECRYPT;
1065e1051a39Sopenharmony_ci
1066e1051a39Sopenharmony_ci    cctx->res = 0;
1067e1051a39Sopenharmony_ci    memcpy(cctx->kmf.param.cv, iv, ivlen);
1068e1051a39Sopenharmony_ci    memcpy(cctx->kmf.param.k, key, keylen);
1069e1051a39Sopenharmony_ci    return 1;
1070e1051a39Sopenharmony_ci}
1071e1051a39Sopenharmony_ci
1072e1051a39Sopenharmony_cistatic int s390x_aes_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
1073e1051a39Sopenharmony_ci                                const unsigned char *in, size_t len)
1074e1051a39Sopenharmony_ci{
1075e1051a39Sopenharmony_ci    S390X_AES_CFB_CTX *cctx = EVP_C_DATA(S390X_AES_CFB_CTX, ctx);
1076e1051a39Sopenharmony_ci    const int keylen = EVP_CIPHER_CTX_get_key_length(ctx);
1077e1051a39Sopenharmony_ci    const int enc = EVP_CIPHER_CTX_is_encrypting(ctx);
1078e1051a39Sopenharmony_ci    const int ivlen = EVP_CIPHER_CTX_get_iv_length(ctx);
1079e1051a39Sopenharmony_ci    unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
1080e1051a39Sopenharmony_ci    int n = cctx->res;
1081e1051a39Sopenharmony_ci    int rem;
1082e1051a39Sopenharmony_ci    unsigned char tmp;
1083e1051a39Sopenharmony_ci
1084e1051a39Sopenharmony_ci    memcpy(cctx->kmf.param.cv, iv, ivlen);
1085e1051a39Sopenharmony_ci    while (n && len) {
1086e1051a39Sopenharmony_ci        tmp = *in;
1087e1051a39Sopenharmony_ci        *out = cctx->kmf.param.cv[n] ^ tmp;
1088e1051a39Sopenharmony_ci        cctx->kmf.param.cv[n] = enc ? *out : tmp;
1089e1051a39Sopenharmony_ci        n = (n + 1) & 0xf;
1090e1051a39Sopenharmony_ci        --len;
1091e1051a39Sopenharmony_ci        ++in;
1092e1051a39Sopenharmony_ci        ++out;
1093e1051a39Sopenharmony_ci    }
1094e1051a39Sopenharmony_ci
1095e1051a39Sopenharmony_ci    rem = len & 0xf;
1096e1051a39Sopenharmony_ci
1097e1051a39Sopenharmony_ci    len &= ~(size_t)0xf;
1098e1051a39Sopenharmony_ci    if (len) {
1099e1051a39Sopenharmony_ci        s390x_kmf(in, len, out, cctx->fc, &cctx->kmf.param);
1100e1051a39Sopenharmony_ci
1101e1051a39Sopenharmony_ci        out += len;
1102e1051a39Sopenharmony_ci        in += len;
1103e1051a39Sopenharmony_ci    }
1104e1051a39Sopenharmony_ci
1105e1051a39Sopenharmony_ci    if (rem) {
1106e1051a39Sopenharmony_ci        s390x_km(cctx->kmf.param.cv, 16, cctx->kmf.param.cv,
1107e1051a39Sopenharmony_ci                 S390X_AES_FC(keylen), cctx->kmf.param.k);
1108e1051a39Sopenharmony_ci
1109e1051a39Sopenharmony_ci        while (rem--) {
1110e1051a39Sopenharmony_ci            tmp = in[n];
1111e1051a39Sopenharmony_ci            out[n] = cctx->kmf.param.cv[n] ^ tmp;
1112e1051a39Sopenharmony_ci            cctx->kmf.param.cv[n] = enc ? out[n] : tmp;
1113e1051a39Sopenharmony_ci            ++n;
1114e1051a39Sopenharmony_ci        }
1115e1051a39Sopenharmony_ci    }
1116e1051a39Sopenharmony_ci
1117e1051a39Sopenharmony_ci    memcpy(iv, cctx->kmf.param.cv, ivlen);
1118e1051a39Sopenharmony_ci    cctx->res = n;
1119e1051a39Sopenharmony_ci    return 1;
1120e1051a39Sopenharmony_ci}
1121e1051a39Sopenharmony_ci
1122e1051a39Sopenharmony_cistatic int s390x_aes_cfb8_init_key(EVP_CIPHER_CTX *ctx,
1123e1051a39Sopenharmony_ci                                   const unsigned char *key,
1124e1051a39Sopenharmony_ci                                   const unsigned char *ivec, int enc)
1125e1051a39Sopenharmony_ci{
1126e1051a39Sopenharmony_ci    S390X_AES_CFB_CTX *cctx = EVP_C_DATA(S390X_AES_CFB_CTX, ctx);
1127e1051a39Sopenharmony_ci    const unsigned char *iv = ctx->oiv;
1128e1051a39Sopenharmony_ci    const int keylen = EVP_CIPHER_CTX_get_key_length(ctx);
1129e1051a39Sopenharmony_ci    const int ivlen = EVP_CIPHER_CTX_get_iv_length(ctx);
1130e1051a39Sopenharmony_ci
1131e1051a39Sopenharmony_ci    cctx->fc = S390X_AES_FC(keylen);
1132e1051a39Sopenharmony_ci    cctx->fc |= 1 << 24;   /* 1 byte cipher feedback */
1133e1051a39Sopenharmony_ci    if (!enc)
1134e1051a39Sopenharmony_ci        cctx->fc |= S390X_DECRYPT;
1135e1051a39Sopenharmony_ci
1136e1051a39Sopenharmony_ci    memcpy(cctx->kmf.param.cv, iv, ivlen);
1137e1051a39Sopenharmony_ci    memcpy(cctx->kmf.param.k, key, keylen);
1138e1051a39Sopenharmony_ci    return 1;
1139e1051a39Sopenharmony_ci}
1140e1051a39Sopenharmony_ci
1141e1051a39Sopenharmony_cistatic int s390x_aes_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
1142e1051a39Sopenharmony_ci                                 const unsigned char *in, size_t len)
1143e1051a39Sopenharmony_ci{
1144e1051a39Sopenharmony_ci    S390X_AES_CFB_CTX *cctx = EVP_C_DATA(S390X_AES_CFB_CTX, ctx);
1145e1051a39Sopenharmony_ci    const int ivlen = EVP_CIPHER_CTX_get_iv_length(ctx);
1146e1051a39Sopenharmony_ci    unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
1147e1051a39Sopenharmony_ci
1148e1051a39Sopenharmony_ci    memcpy(cctx->kmf.param.cv, iv, ivlen);
1149e1051a39Sopenharmony_ci    s390x_kmf(in, len, out, cctx->fc, &cctx->kmf.param);
1150e1051a39Sopenharmony_ci    memcpy(iv, cctx->kmf.param.cv, ivlen);
1151e1051a39Sopenharmony_ci    return 1;
1152e1051a39Sopenharmony_ci}
1153e1051a39Sopenharmony_ci
1154e1051a39Sopenharmony_ci# define s390x_aes_cfb1_init_key aes_init_key
1155e1051a39Sopenharmony_ci
1156e1051a39Sopenharmony_ci# define s390x_aes_cfb1_cipher aes_cfb1_cipher
1157e1051a39Sopenharmony_cistatic int s390x_aes_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
1158e1051a39Sopenharmony_ci                                 const unsigned char *in, size_t len);
1159e1051a39Sopenharmony_ci
1160e1051a39Sopenharmony_ci# define S390X_AES_CTR_CTX              EVP_AES_KEY
1161e1051a39Sopenharmony_ci
1162e1051a39Sopenharmony_ci# define s390x_aes_ctr_init_key aes_init_key
1163e1051a39Sopenharmony_ci
1164e1051a39Sopenharmony_ci# define s390x_aes_ctr_cipher aes_ctr_cipher
1165e1051a39Sopenharmony_cistatic int s390x_aes_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
1166e1051a39Sopenharmony_ci                                const unsigned char *in, size_t len);
1167e1051a39Sopenharmony_ci
1168e1051a39Sopenharmony_ci/* iv + padding length for iv lengths != 12 */
1169e1051a39Sopenharmony_ci# define S390X_gcm_ivpadlen(i)  ((((i) + 15) >> 4 << 4) + 16)
1170e1051a39Sopenharmony_ci
1171e1051a39Sopenharmony_ci/*-
1172e1051a39Sopenharmony_ci * Process additional authenticated data. Returns 0 on success. Code is
1173e1051a39Sopenharmony_ci * big-endian.
1174e1051a39Sopenharmony_ci */
1175e1051a39Sopenharmony_cistatic int s390x_aes_gcm_aad(S390X_AES_GCM_CTX *ctx, const unsigned char *aad,
1176e1051a39Sopenharmony_ci                             size_t len)
1177e1051a39Sopenharmony_ci{
1178e1051a39Sopenharmony_ci    unsigned long long alen;
1179e1051a39Sopenharmony_ci    int n, rem;
1180e1051a39Sopenharmony_ci
1181e1051a39Sopenharmony_ci    if (ctx->kma.param.tpcl)
1182e1051a39Sopenharmony_ci        return -2;
1183e1051a39Sopenharmony_ci
1184e1051a39Sopenharmony_ci    alen = ctx->kma.param.taadl + len;
1185e1051a39Sopenharmony_ci    if (alen > (U64(1) << 61) || (sizeof(len) == 8 && alen < len))
1186e1051a39Sopenharmony_ci        return -1;
1187e1051a39Sopenharmony_ci    ctx->kma.param.taadl = alen;
1188e1051a39Sopenharmony_ci
1189e1051a39Sopenharmony_ci    n = ctx->areslen;
1190e1051a39Sopenharmony_ci    if (n) {
1191e1051a39Sopenharmony_ci        while (n && len) {
1192e1051a39Sopenharmony_ci            ctx->ares[n] = *aad;
1193e1051a39Sopenharmony_ci            n = (n + 1) & 0xf;
1194e1051a39Sopenharmony_ci            ++aad;
1195e1051a39Sopenharmony_ci            --len;
1196e1051a39Sopenharmony_ci        }
1197e1051a39Sopenharmony_ci        /* ctx->ares contains a complete block if offset has wrapped around */
1198e1051a39Sopenharmony_ci        if (!n) {
1199e1051a39Sopenharmony_ci            s390x_kma(ctx->ares, 16, NULL, 0, NULL, ctx->fc, &ctx->kma.param);
1200e1051a39Sopenharmony_ci            ctx->fc |= S390X_KMA_HS;
1201e1051a39Sopenharmony_ci        }
1202e1051a39Sopenharmony_ci        ctx->areslen = n;
1203e1051a39Sopenharmony_ci    }
1204e1051a39Sopenharmony_ci
1205e1051a39Sopenharmony_ci    rem = len & 0xf;
1206e1051a39Sopenharmony_ci
1207e1051a39Sopenharmony_ci    len &= ~(size_t)0xf;
1208e1051a39Sopenharmony_ci    if (len) {
1209e1051a39Sopenharmony_ci        s390x_kma(aad, len, NULL, 0, NULL, ctx->fc, &ctx->kma.param);
1210e1051a39Sopenharmony_ci        aad += len;
1211e1051a39Sopenharmony_ci        ctx->fc |= S390X_KMA_HS;
1212e1051a39Sopenharmony_ci    }
1213e1051a39Sopenharmony_ci
1214e1051a39Sopenharmony_ci    if (rem) {
1215e1051a39Sopenharmony_ci        ctx->areslen = rem;
1216e1051a39Sopenharmony_ci
1217e1051a39Sopenharmony_ci        do {
1218e1051a39Sopenharmony_ci            --rem;
1219e1051a39Sopenharmony_ci            ctx->ares[rem] = aad[rem];
1220e1051a39Sopenharmony_ci        } while (rem);
1221e1051a39Sopenharmony_ci    }
1222e1051a39Sopenharmony_ci    return 0;
1223e1051a39Sopenharmony_ci}
1224e1051a39Sopenharmony_ci
1225e1051a39Sopenharmony_ci/*-
1226e1051a39Sopenharmony_ci * En/de-crypt plain/cipher-text and authenticate ciphertext. Returns 0 for
1227e1051a39Sopenharmony_ci * success. Code is big-endian.
1228e1051a39Sopenharmony_ci */
1229e1051a39Sopenharmony_cistatic int s390x_aes_gcm(S390X_AES_GCM_CTX *ctx, const unsigned char *in,
1230e1051a39Sopenharmony_ci                         unsigned char *out, size_t len)
1231e1051a39Sopenharmony_ci{
1232e1051a39Sopenharmony_ci    const unsigned char *inptr;
1233e1051a39Sopenharmony_ci    unsigned long long mlen;
1234e1051a39Sopenharmony_ci    union {
1235e1051a39Sopenharmony_ci        unsigned int w[4];
1236e1051a39Sopenharmony_ci        unsigned char b[16];
1237e1051a39Sopenharmony_ci    } buf;
1238e1051a39Sopenharmony_ci    size_t inlen;
1239e1051a39Sopenharmony_ci    int n, rem, i;
1240e1051a39Sopenharmony_ci
1241e1051a39Sopenharmony_ci    mlen = ctx->kma.param.tpcl + len;
1242e1051a39Sopenharmony_ci    if (mlen > ((U64(1) << 36) - 32) || (sizeof(len) == 8 && mlen < len))
1243e1051a39Sopenharmony_ci        return -1;
1244e1051a39Sopenharmony_ci    ctx->kma.param.tpcl = mlen;
1245e1051a39Sopenharmony_ci
1246e1051a39Sopenharmony_ci    n = ctx->mreslen;
1247e1051a39Sopenharmony_ci    if (n) {
1248e1051a39Sopenharmony_ci        inptr = in;
1249e1051a39Sopenharmony_ci        inlen = len;
1250e1051a39Sopenharmony_ci        while (n && inlen) {
1251e1051a39Sopenharmony_ci            ctx->mres[n] = *inptr;
1252e1051a39Sopenharmony_ci            n = (n + 1) & 0xf;
1253e1051a39Sopenharmony_ci            ++inptr;
1254e1051a39Sopenharmony_ci            --inlen;
1255e1051a39Sopenharmony_ci        }
1256e1051a39Sopenharmony_ci        /* ctx->mres contains a complete block if offset has wrapped around */
1257e1051a39Sopenharmony_ci        if (!n) {
1258e1051a39Sopenharmony_ci            s390x_kma(ctx->ares, ctx->areslen, ctx->mres, 16, buf.b,
1259e1051a39Sopenharmony_ci                      ctx->fc | S390X_KMA_LAAD, &ctx->kma.param);
1260e1051a39Sopenharmony_ci            ctx->fc |= S390X_KMA_HS;
1261e1051a39Sopenharmony_ci            ctx->areslen = 0;
1262e1051a39Sopenharmony_ci
1263e1051a39Sopenharmony_ci            /* previous call already encrypted/decrypted its remainder,
1264e1051a39Sopenharmony_ci             * see comment below */
1265e1051a39Sopenharmony_ci            n = ctx->mreslen;
1266e1051a39Sopenharmony_ci            while (n) {
1267e1051a39Sopenharmony_ci                *out = buf.b[n];
1268e1051a39Sopenharmony_ci                n = (n + 1) & 0xf;
1269e1051a39Sopenharmony_ci                ++out;
1270e1051a39Sopenharmony_ci                ++in;
1271e1051a39Sopenharmony_ci                --len;
1272e1051a39Sopenharmony_ci            }
1273e1051a39Sopenharmony_ci            ctx->mreslen = 0;
1274e1051a39Sopenharmony_ci        }
1275e1051a39Sopenharmony_ci    }
1276e1051a39Sopenharmony_ci
1277e1051a39Sopenharmony_ci    rem = len & 0xf;
1278e1051a39Sopenharmony_ci
1279e1051a39Sopenharmony_ci    len &= ~(size_t)0xf;
1280e1051a39Sopenharmony_ci    if (len) {
1281e1051a39Sopenharmony_ci        s390x_kma(ctx->ares, ctx->areslen, in, len, out,
1282e1051a39Sopenharmony_ci                  ctx->fc | S390X_KMA_LAAD, &ctx->kma.param);
1283e1051a39Sopenharmony_ci        in += len;
1284e1051a39Sopenharmony_ci        out += len;
1285e1051a39Sopenharmony_ci        ctx->fc |= S390X_KMA_HS;
1286e1051a39Sopenharmony_ci        ctx->areslen = 0;
1287e1051a39Sopenharmony_ci    }
1288e1051a39Sopenharmony_ci
1289e1051a39Sopenharmony_ci    /*-
1290e1051a39Sopenharmony_ci     * If there is a remainder, it has to be saved such that it can be
1291e1051a39Sopenharmony_ci     * processed by kma later. However, we also have to do the for-now
1292e1051a39Sopenharmony_ci     * unauthenticated encryption/decryption part here and now...
1293e1051a39Sopenharmony_ci     */
1294e1051a39Sopenharmony_ci    if (rem) {
1295e1051a39Sopenharmony_ci        if (!ctx->mreslen) {
1296e1051a39Sopenharmony_ci            buf.w[0] = ctx->kma.param.j0.w[0];
1297e1051a39Sopenharmony_ci            buf.w[1] = ctx->kma.param.j0.w[1];
1298e1051a39Sopenharmony_ci            buf.w[2] = ctx->kma.param.j0.w[2];
1299e1051a39Sopenharmony_ci            buf.w[3] = ctx->kma.param.cv.w + 1;
1300e1051a39Sopenharmony_ci            s390x_km(buf.b, 16, ctx->kres, ctx->fc & 0x1f, &ctx->kma.param.k);
1301e1051a39Sopenharmony_ci        }
1302e1051a39Sopenharmony_ci
1303e1051a39Sopenharmony_ci        n = ctx->mreslen;
1304e1051a39Sopenharmony_ci        for (i = 0; i < rem; i++) {
1305e1051a39Sopenharmony_ci            ctx->mres[n + i] = in[i];
1306e1051a39Sopenharmony_ci            out[i] = in[i] ^ ctx->kres[n + i];
1307e1051a39Sopenharmony_ci        }
1308e1051a39Sopenharmony_ci
1309e1051a39Sopenharmony_ci        ctx->mreslen += rem;
1310e1051a39Sopenharmony_ci    }
1311e1051a39Sopenharmony_ci    return 0;
1312e1051a39Sopenharmony_ci}
1313e1051a39Sopenharmony_ci
1314e1051a39Sopenharmony_ci/*-
1315e1051a39Sopenharmony_ci * Initialize context structure. Code is big-endian.
1316e1051a39Sopenharmony_ci */
1317e1051a39Sopenharmony_cistatic void s390x_aes_gcm_setiv(S390X_AES_GCM_CTX *ctx,
1318e1051a39Sopenharmony_ci                                const unsigned char *iv)
1319e1051a39Sopenharmony_ci{
1320e1051a39Sopenharmony_ci    ctx->kma.param.t.g[0] = 0;
1321e1051a39Sopenharmony_ci    ctx->kma.param.t.g[1] = 0;
1322e1051a39Sopenharmony_ci    ctx->kma.param.tpcl = 0;
1323e1051a39Sopenharmony_ci    ctx->kma.param.taadl = 0;
1324e1051a39Sopenharmony_ci    ctx->mreslen = 0;
1325e1051a39Sopenharmony_ci    ctx->areslen = 0;
1326e1051a39Sopenharmony_ci    ctx->kreslen = 0;
1327e1051a39Sopenharmony_ci
1328e1051a39Sopenharmony_ci    if (ctx->ivlen == 12) {
1329e1051a39Sopenharmony_ci        memcpy(&ctx->kma.param.j0, iv, ctx->ivlen);
1330e1051a39Sopenharmony_ci        ctx->kma.param.j0.w[3] = 1;
1331e1051a39Sopenharmony_ci        ctx->kma.param.cv.w = 1;
1332e1051a39Sopenharmony_ci    } else {
1333e1051a39Sopenharmony_ci        /* ctx->iv has the right size and is already padded. */
1334e1051a39Sopenharmony_ci        memcpy(ctx->iv, iv, ctx->ivlen);
1335e1051a39Sopenharmony_ci        s390x_kma(ctx->iv, S390X_gcm_ivpadlen(ctx->ivlen), NULL, 0, NULL,
1336e1051a39Sopenharmony_ci                  ctx->fc, &ctx->kma.param);
1337e1051a39Sopenharmony_ci        ctx->fc |= S390X_KMA_HS;
1338e1051a39Sopenharmony_ci
1339e1051a39Sopenharmony_ci        ctx->kma.param.j0.g[0] = ctx->kma.param.t.g[0];
1340e1051a39Sopenharmony_ci        ctx->kma.param.j0.g[1] = ctx->kma.param.t.g[1];
1341e1051a39Sopenharmony_ci        ctx->kma.param.cv.w = ctx->kma.param.j0.w[3];
1342e1051a39Sopenharmony_ci        ctx->kma.param.t.g[0] = 0;
1343e1051a39Sopenharmony_ci        ctx->kma.param.t.g[1] = 0;
1344e1051a39Sopenharmony_ci    }
1345e1051a39Sopenharmony_ci}
1346e1051a39Sopenharmony_ci
1347e1051a39Sopenharmony_ci/*-
1348e1051a39Sopenharmony_ci * Performs various operations on the context structure depending on control
1349e1051a39Sopenharmony_ci * type. Returns 1 for success, 0 for failure and -1 for unknown control type.
1350e1051a39Sopenharmony_ci * Code is big-endian.
1351e1051a39Sopenharmony_ci */
1352e1051a39Sopenharmony_cistatic int s390x_aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
1353e1051a39Sopenharmony_ci{
1354e1051a39Sopenharmony_ci    S390X_AES_GCM_CTX *gctx = EVP_C_DATA(S390X_AES_GCM_CTX, c);
1355e1051a39Sopenharmony_ci    S390X_AES_GCM_CTX *gctx_out;
1356e1051a39Sopenharmony_ci    EVP_CIPHER_CTX *out;
1357e1051a39Sopenharmony_ci    unsigned char *buf;
1358e1051a39Sopenharmony_ci    int ivlen, enc, len;
1359e1051a39Sopenharmony_ci
1360e1051a39Sopenharmony_ci    switch (type) {
1361e1051a39Sopenharmony_ci    case EVP_CTRL_INIT:
1362e1051a39Sopenharmony_ci        ivlen = EVP_CIPHER_get_iv_length(c->cipher);
1363e1051a39Sopenharmony_ci        gctx->key_set = 0;
1364e1051a39Sopenharmony_ci        gctx->iv_set = 0;
1365e1051a39Sopenharmony_ci        gctx->ivlen = ivlen;
1366e1051a39Sopenharmony_ci        gctx->iv = c->iv;
1367e1051a39Sopenharmony_ci        gctx->taglen = -1;
1368e1051a39Sopenharmony_ci        gctx->iv_gen = 0;
1369e1051a39Sopenharmony_ci        gctx->tls_aad_len = -1;
1370e1051a39Sopenharmony_ci        return 1;
1371e1051a39Sopenharmony_ci
1372e1051a39Sopenharmony_ci    case EVP_CTRL_GET_IVLEN:
1373e1051a39Sopenharmony_ci        *(int *)ptr = gctx->ivlen;
1374e1051a39Sopenharmony_ci        return 1;
1375e1051a39Sopenharmony_ci
1376e1051a39Sopenharmony_ci    case EVP_CTRL_AEAD_SET_IVLEN:
1377e1051a39Sopenharmony_ci        if (arg <= 0)
1378e1051a39Sopenharmony_ci            return 0;
1379e1051a39Sopenharmony_ci
1380e1051a39Sopenharmony_ci        if (arg != 12) {
1381e1051a39Sopenharmony_ci            len = S390X_gcm_ivpadlen(arg);
1382e1051a39Sopenharmony_ci
1383e1051a39Sopenharmony_ci            /* Allocate memory for iv if needed. */
1384e1051a39Sopenharmony_ci            if (gctx->ivlen == 12 || len > S390X_gcm_ivpadlen(gctx->ivlen)) {
1385e1051a39Sopenharmony_ci                if (gctx->iv != c->iv)
1386e1051a39Sopenharmony_ci                    OPENSSL_free(gctx->iv);
1387e1051a39Sopenharmony_ci
1388e1051a39Sopenharmony_ci                if ((gctx->iv = OPENSSL_malloc(len)) == NULL) {
1389e1051a39Sopenharmony_ci                    ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
1390e1051a39Sopenharmony_ci                    return 0;
1391e1051a39Sopenharmony_ci                }
1392e1051a39Sopenharmony_ci            }
1393e1051a39Sopenharmony_ci            /* Add padding. */
1394e1051a39Sopenharmony_ci            memset(gctx->iv + arg, 0, len - arg - 8);
1395e1051a39Sopenharmony_ci            *((unsigned long long *)(gctx->iv + len - 8)) = arg << 3;
1396e1051a39Sopenharmony_ci        }
1397e1051a39Sopenharmony_ci        gctx->ivlen = arg;
1398e1051a39Sopenharmony_ci        return 1;
1399e1051a39Sopenharmony_ci
1400e1051a39Sopenharmony_ci    case EVP_CTRL_AEAD_SET_TAG:
1401e1051a39Sopenharmony_ci        buf = EVP_CIPHER_CTX_buf_noconst(c);
1402e1051a39Sopenharmony_ci        enc = EVP_CIPHER_CTX_is_encrypting(c);
1403e1051a39Sopenharmony_ci        if (arg <= 0 || arg > 16 || enc)
1404e1051a39Sopenharmony_ci            return 0;
1405e1051a39Sopenharmony_ci
1406e1051a39Sopenharmony_ci        memcpy(buf, ptr, arg);
1407e1051a39Sopenharmony_ci        gctx->taglen = arg;
1408e1051a39Sopenharmony_ci        return 1;
1409e1051a39Sopenharmony_ci
1410e1051a39Sopenharmony_ci    case EVP_CTRL_AEAD_GET_TAG:
1411e1051a39Sopenharmony_ci        enc = EVP_CIPHER_CTX_is_encrypting(c);
1412e1051a39Sopenharmony_ci        if (arg <= 0 || arg > 16 || !enc || gctx->taglen < 0)
1413e1051a39Sopenharmony_ci            return 0;
1414e1051a39Sopenharmony_ci
1415e1051a39Sopenharmony_ci        memcpy(ptr, gctx->kma.param.t.b, arg);
1416e1051a39Sopenharmony_ci        return 1;
1417e1051a39Sopenharmony_ci
1418e1051a39Sopenharmony_ci    case EVP_CTRL_GCM_SET_IV_FIXED:
1419e1051a39Sopenharmony_ci        /* Special case: -1 length restores whole iv */
1420e1051a39Sopenharmony_ci        if (arg == -1) {
1421e1051a39Sopenharmony_ci            memcpy(gctx->iv, ptr, gctx->ivlen);
1422e1051a39Sopenharmony_ci            gctx->iv_gen = 1;
1423e1051a39Sopenharmony_ci            return 1;
1424e1051a39Sopenharmony_ci        }
1425e1051a39Sopenharmony_ci        /*
1426e1051a39Sopenharmony_ci         * Fixed field must be at least 4 bytes and invocation field at least
1427e1051a39Sopenharmony_ci         * 8.
1428e1051a39Sopenharmony_ci         */
1429e1051a39Sopenharmony_ci        if ((arg < 4) || (gctx->ivlen - arg) < 8)
1430e1051a39Sopenharmony_ci            return 0;
1431e1051a39Sopenharmony_ci
1432e1051a39Sopenharmony_ci        if (arg)
1433e1051a39Sopenharmony_ci            memcpy(gctx->iv, ptr, arg);
1434e1051a39Sopenharmony_ci
1435e1051a39Sopenharmony_ci        enc = EVP_CIPHER_CTX_is_encrypting(c);
1436e1051a39Sopenharmony_ci        if (enc && RAND_bytes(gctx->iv + arg, gctx->ivlen - arg) <= 0)
1437e1051a39Sopenharmony_ci            return 0;
1438e1051a39Sopenharmony_ci
1439e1051a39Sopenharmony_ci        gctx->iv_gen = 1;
1440e1051a39Sopenharmony_ci        return 1;
1441e1051a39Sopenharmony_ci
1442e1051a39Sopenharmony_ci    case EVP_CTRL_GCM_IV_GEN:
1443e1051a39Sopenharmony_ci        if (gctx->iv_gen == 0 || gctx->key_set == 0)
1444e1051a39Sopenharmony_ci            return 0;
1445e1051a39Sopenharmony_ci
1446e1051a39Sopenharmony_ci        s390x_aes_gcm_setiv(gctx, gctx->iv);
1447e1051a39Sopenharmony_ci
1448e1051a39Sopenharmony_ci        if (arg <= 0 || arg > gctx->ivlen)
1449e1051a39Sopenharmony_ci            arg = gctx->ivlen;
1450e1051a39Sopenharmony_ci
1451e1051a39Sopenharmony_ci        memcpy(ptr, gctx->iv + gctx->ivlen - arg, arg);
1452e1051a39Sopenharmony_ci        /*
1453e1051a39Sopenharmony_ci         * Invocation field will be at least 8 bytes in size and so no need
1454e1051a39Sopenharmony_ci         * to check wrap around or increment more than last 8 bytes.
1455e1051a39Sopenharmony_ci         */
1456e1051a39Sopenharmony_ci        ctr64_inc(gctx->iv + gctx->ivlen - 8);
1457e1051a39Sopenharmony_ci        gctx->iv_set = 1;
1458e1051a39Sopenharmony_ci        return 1;
1459e1051a39Sopenharmony_ci
1460e1051a39Sopenharmony_ci    case EVP_CTRL_GCM_SET_IV_INV:
1461e1051a39Sopenharmony_ci        enc = EVP_CIPHER_CTX_is_encrypting(c);
1462e1051a39Sopenharmony_ci        if (gctx->iv_gen == 0 || gctx->key_set == 0 || enc)
1463e1051a39Sopenharmony_ci            return 0;
1464e1051a39Sopenharmony_ci
1465e1051a39Sopenharmony_ci        memcpy(gctx->iv + gctx->ivlen - arg, ptr, arg);
1466e1051a39Sopenharmony_ci        s390x_aes_gcm_setiv(gctx, gctx->iv);
1467e1051a39Sopenharmony_ci        gctx->iv_set = 1;
1468e1051a39Sopenharmony_ci        return 1;
1469e1051a39Sopenharmony_ci
1470e1051a39Sopenharmony_ci    case EVP_CTRL_AEAD_TLS1_AAD:
1471e1051a39Sopenharmony_ci        /* Save the aad for later use. */
1472e1051a39Sopenharmony_ci        if (arg != EVP_AEAD_TLS1_AAD_LEN)
1473e1051a39Sopenharmony_ci            return 0;
1474e1051a39Sopenharmony_ci
1475e1051a39Sopenharmony_ci        buf = EVP_CIPHER_CTX_buf_noconst(c);
1476e1051a39Sopenharmony_ci        memcpy(buf, ptr, arg);
1477e1051a39Sopenharmony_ci        gctx->tls_aad_len = arg;
1478e1051a39Sopenharmony_ci        gctx->tls_enc_records = 0;
1479e1051a39Sopenharmony_ci
1480e1051a39Sopenharmony_ci        len = buf[arg - 2] << 8 | buf[arg - 1];
1481e1051a39Sopenharmony_ci        /* Correct length for explicit iv. */
1482e1051a39Sopenharmony_ci        if (len < EVP_GCM_TLS_EXPLICIT_IV_LEN)
1483e1051a39Sopenharmony_ci            return 0;
1484e1051a39Sopenharmony_ci        len -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
1485e1051a39Sopenharmony_ci
1486e1051a39Sopenharmony_ci        /* If decrypting correct for tag too. */
1487e1051a39Sopenharmony_ci        enc = EVP_CIPHER_CTX_is_encrypting(c);
1488e1051a39Sopenharmony_ci        if (!enc) {
1489e1051a39Sopenharmony_ci            if (len < EVP_GCM_TLS_TAG_LEN)
1490e1051a39Sopenharmony_ci                return 0;
1491e1051a39Sopenharmony_ci            len -= EVP_GCM_TLS_TAG_LEN;
1492e1051a39Sopenharmony_ci        }
1493e1051a39Sopenharmony_ci        buf[arg - 2] = len >> 8;
1494e1051a39Sopenharmony_ci        buf[arg - 1] = len & 0xff;
1495e1051a39Sopenharmony_ci        /* Extra padding: tag appended to record. */
1496e1051a39Sopenharmony_ci        return EVP_GCM_TLS_TAG_LEN;
1497e1051a39Sopenharmony_ci
1498e1051a39Sopenharmony_ci    case EVP_CTRL_COPY:
1499e1051a39Sopenharmony_ci        out = ptr;
1500e1051a39Sopenharmony_ci        gctx_out = EVP_C_DATA(S390X_AES_GCM_CTX, out);
1501e1051a39Sopenharmony_ci
1502e1051a39Sopenharmony_ci        if (gctx->iv == c->iv) {
1503e1051a39Sopenharmony_ci            gctx_out->iv = out->iv;
1504e1051a39Sopenharmony_ci        } else {
1505e1051a39Sopenharmony_ci            len = S390X_gcm_ivpadlen(gctx->ivlen);
1506e1051a39Sopenharmony_ci
1507e1051a39Sopenharmony_ci            if ((gctx_out->iv = OPENSSL_malloc(len)) == NULL) {
1508e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
1509e1051a39Sopenharmony_ci                return 0;
1510e1051a39Sopenharmony_ci            }
1511e1051a39Sopenharmony_ci
1512e1051a39Sopenharmony_ci            memcpy(gctx_out->iv, gctx->iv, len);
1513e1051a39Sopenharmony_ci        }
1514e1051a39Sopenharmony_ci        return 1;
1515e1051a39Sopenharmony_ci
1516e1051a39Sopenharmony_ci    default:
1517e1051a39Sopenharmony_ci        return -1;
1518e1051a39Sopenharmony_ci    }
1519e1051a39Sopenharmony_ci}
1520e1051a39Sopenharmony_ci
1521e1051a39Sopenharmony_ci/*-
1522e1051a39Sopenharmony_ci * Set key and/or iv. Returns 1 on success. Otherwise 0 is returned.
1523e1051a39Sopenharmony_ci */
1524e1051a39Sopenharmony_cistatic int s390x_aes_gcm_init_key(EVP_CIPHER_CTX *ctx,
1525e1051a39Sopenharmony_ci                                  const unsigned char *key,
1526e1051a39Sopenharmony_ci                                  const unsigned char *iv, int enc)
1527e1051a39Sopenharmony_ci{
1528e1051a39Sopenharmony_ci    S390X_AES_GCM_CTX *gctx = EVP_C_DATA(S390X_AES_GCM_CTX, ctx);
1529e1051a39Sopenharmony_ci    int keylen;
1530e1051a39Sopenharmony_ci
1531e1051a39Sopenharmony_ci    if (iv == NULL && key == NULL)
1532e1051a39Sopenharmony_ci        return 1;
1533e1051a39Sopenharmony_ci
1534e1051a39Sopenharmony_ci    if (key != NULL) {
1535e1051a39Sopenharmony_ci        keylen = EVP_CIPHER_CTX_get_key_length(ctx);
1536e1051a39Sopenharmony_ci        memcpy(&gctx->kma.param.k, key, keylen);
1537e1051a39Sopenharmony_ci
1538e1051a39Sopenharmony_ci        gctx->fc = S390X_AES_FC(keylen);
1539e1051a39Sopenharmony_ci        if (!enc)
1540e1051a39Sopenharmony_ci            gctx->fc |= S390X_DECRYPT;
1541e1051a39Sopenharmony_ci
1542e1051a39Sopenharmony_ci        if (iv == NULL && gctx->iv_set)
1543e1051a39Sopenharmony_ci            iv = gctx->iv;
1544e1051a39Sopenharmony_ci
1545e1051a39Sopenharmony_ci        if (iv != NULL) {
1546e1051a39Sopenharmony_ci            s390x_aes_gcm_setiv(gctx, iv);
1547e1051a39Sopenharmony_ci            gctx->iv_set = 1;
1548e1051a39Sopenharmony_ci        }
1549e1051a39Sopenharmony_ci        gctx->key_set = 1;
1550e1051a39Sopenharmony_ci    } else {
1551e1051a39Sopenharmony_ci        if (gctx->key_set)
1552e1051a39Sopenharmony_ci            s390x_aes_gcm_setiv(gctx, iv);
1553e1051a39Sopenharmony_ci        else
1554e1051a39Sopenharmony_ci            memcpy(gctx->iv, iv, gctx->ivlen);
1555e1051a39Sopenharmony_ci
1556e1051a39Sopenharmony_ci        gctx->iv_set = 1;
1557e1051a39Sopenharmony_ci        gctx->iv_gen = 0;
1558e1051a39Sopenharmony_ci    }
1559e1051a39Sopenharmony_ci    return 1;
1560e1051a39Sopenharmony_ci}
1561e1051a39Sopenharmony_ci
1562e1051a39Sopenharmony_ci/*-
1563e1051a39Sopenharmony_ci * En/de-crypt and authenticate TLS packet. Returns the number of bytes written
1564e1051a39Sopenharmony_ci * if successful. Otherwise -1 is returned. Code is big-endian.
1565e1051a39Sopenharmony_ci */
1566e1051a39Sopenharmony_cistatic int s390x_aes_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
1567e1051a39Sopenharmony_ci                                    const unsigned char *in, size_t len)
1568e1051a39Sopenharmony_ci{
1569e1051a39Sopenharmony_ci    S390X_AES_GCM_CTX *gctx = EVP_C_DATA(S390X_AES_GCM_CTX, ctx);
1570e1051a39Sopenharmony_ci    const unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx);
1571e1051a39Sopenharmony_ci    const int enc = EVP_CIPHER_CTX_is_encrypting(ctx);
1572e1051a39Sopenharmony_ci    int rv = -1;
1573e1051a39Sopenharmony_ci
1574e1051a39Sopenharmony_ci    if (out != in || len < (EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN))
1575e1051a39Sopenharmony_ci        return -1;
1576e1051a39Sopenharmony_ci
1577e1051a39Sopenharmony_ci    /*
1578e1051a39Sopenharmony_ci     * Check for too many keys as per FIPS 140-2 IG A.5 "Key/IV Pair Uniqueness
1579e1051a39Sopenharmony_ci     * Requirements from SP 800-38D".  The requirements is for one party to the
1580e1051a39Sopenharmony_ci     * communication to fail after 2^64 - 1 keys.  We do this on the encrypting
1581e1051a39Sopenharmony_ci     * side only.
1582e1051a39Sopenharmony_ci     */
1583e1051a39Sopenharmony_ci    if (ctx->encrypt && ++gctx->tls_enc_records == 0) {
1584e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EVP, EVP_R_TOO_MANY_RECORDS);
1585e1051a39Sopenharmony_ci        goto err;
1586e1051a39Sopenharmony_ci    }
1587e1051a39Sopenharmony_ci
1588e1051a39Sopenharmony_ci    if (EVP_CIPHER_CTX_ctrl(ctx, enc ? EVP_CTRL_GCM_IV_GEN
1589e1051a39Sopenharmony_ci                                     : EVP_CTRL_GCM_SET_IV_INV,
1590e1051a39Sopenharmony_ci                            EVP_GCM_TLS_EXPLICIT_IV_LEN, out) <= 0)
1591e1051a39Sopenharmony_ci        goto err;
1592e1051a39Sopenharmony_ci
1593e1051a39Sopenharmony_ci    in += EVP_GCM_TLS_EXPLICIT_IV_LEN;
1594e1051a39Sopenharmony_ci    out += EVP_GCM_TLS_EXPLICIT_IV_LEN;
1595e1051a39Sopenharmony_ci    len -= EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
1596e1051a39Sopenharmony_ci
1597e1051a39Sopenharmony_ci    gctx->kma.param.taadl = gctx->tls_aad_len << 3;
1598e1051a39Sopenharmony_ci    gctx->kma.param.tpcl = len << 3;
1599e1051a39Sopenharmony_ci    s390x_kma(buf, gctx->tls_aad_len, in, len, out,
1600e1051a39Sopenharmony_ci              gctx->fc | S390X_KMA_LAAD | S390X_KMA_LPC, &gctx->kma.param);
1601e1051a39Sopenharmony_ci
1602e1051a39Sopenharmony_ci    if (enc) {
1603e1051a39Sopenharmony_ci        memcpy(out + len, gctx->kma.param.t.b, EVP_GCM_TLS_TAG_LEN);
1604e1051a39Sopenharmony_ci        rv = len + EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
1605e1051a39Sopenharmony_ci    } else {
1606e1051a39Sopenharmony_ci        if (CRYPTO_memcmp(gctx->kma.param.t.b, in + len,
1607e1051a39Sopenharmony_ci                          EVP_GCM_TLS_TAG_LEN)) {
1608e1051a39Sopenharmony_ci            OPENSSL_cleanse(out, len);
1609e1051a39Sopenharmony_ci            goto err;
1610e1051a39Sopenharmony_ci        }
1611e1051a39Sopenharmony_ci        rv = len;
1612e1051a39Sopenharmony_ci    }
1613e1051a39Sopenharmony_cierr:
1614e1051a39Sopenharmony_ci    gctx->iv_set = 0;
1615e1051a39Sopenharmony_ci    gctx->tls_aad_len = -1;
1616e1051a39Sopenharmony_ci    return rv;
1617e1051a39Sopenharmony_ci}
1618e1051a39Sopenharmony_ci
1619e1051a39Sopenharmony_ci/*-
1620e1051a39Sopenharmony_ci * Called from EVP layer to initialize context, process additional
1621e1051a39Sopenharmony_ci * authenticated data, en/de-crypt plain/cipher-text and authenticate
1622e1051a39Sopenharmony_ci * ciphertext or process a TLS packet, depending on context. Returns bytes
1623e1051a39Sopenharmony_ci * written on success. Otherwise -1 is returned. Code is big-endian.
1624e1051a39Sopenharmony_ci */
1625e1051a39Sopenharmony_cistatic int s390x_aes_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
1626e1051a39Sopenharmony_ci                                const unsigned char *in, size_t len)
1627e1051a39Sopenharmony_ci{
1628e1051a39Sopenharmony_ci    S390X_AES_GCM_CTX *gctx = EVP_C_DATA(S390X_AES_GCM_CTX, ctx);
1629e1051a39Sopenharmony_ci    unsigned char *buf, tmp[16];
1630e1051a39Sopenharmony_ci    int enc;
1631e1051a39Sopenharmony_ci
1632e1051a39Sopenharmony_ci    if (!gctx->key_set)
1633e1051a39Sopenharmony_ci        return -1;
1634e1051a39Sopenharmony_ci
1635e1051a39Sopenharmony_ci    if (gctx->tls_aad_len >= 0)
1636e1051a39Sopenharmony_ci        return s390x_aes_gcm_tls_cipher(ctx, out, in, len);
1637e1051a39Sopenharmony_ci
1638e1051a39Sopenharmony_ci    if (!gctx->iv_set)
1639e1051a39Sopenharmony_ci        return -1;
1640e1051a39Sopenharmony_ci
1641e1051a39Sopenharmony_ci    if (in != NULL) {
1642e1051a39Sopenharmony_ci        if (out == NULL) {
1643e1051a39Sopenharmony_ci            if (s390x_aes_gcm_aad(gctx, in, len))
1644e1051a39Sopenharmony_ci                return -1;
1645e1051a39Sopenharmony_ci        } else {
1646e1051a39Sopenharmony_ci            if (s390x_aes_gcm(gctx, in, out, len))
1647e1051a39Sopenharmony_ci                return -1;
1648e1051a39Sopenharmony_ci        }
1649e1051a39Sopenharmony_ci        return len;
1650e1051a39Sopenharmony_ci    } else {
1651e1051a39Sopenharmony_ci        gctx->kma.param.taadl <<= 3;
1652e1051a39Sopenharmony_ci        gctx->kma.param.tpcl <<= 3;
1653e1051a39Sopenharmony_ci        s390x_kma(gctx->ares, gctx->areslen, gctx->mres, gctx->mreslen, tmp,
1654e1051a39Sopenharmony_ci                  gctx->fc | S390X_KMA_LAAD | S390X_KMA_LPC, &gctx->kma.param);
1655e1051a39Sopenharmony_ci        /* recall that we already did en-/decrypt gctx->mres
1656e1051a39Sopenharmony_ci         * and returned it to caller... */
1657e1051a39Sopenharmony_ci        OPENSSL_cleanse(tmp, gctx->mreslen);
1658e1051a39Sopenharmony_ci        gctx->iv_set = 0;
1659e1051a39Sopenharmony_ci
1660e1051a39Sopenharmony_ci        enc = EVP_CIPHER_CTX_is_encrypting(ctx);
1661e1051a39Sopenharmony_ci        if (enc) {
1662e1051a39Sopenharmony_ci            gctx->taglen = 16;
1663e1051a39Sopenharmony_ci        } else {
1664e1051a39Sopenharmony_ci            if (gctx->taglen < 0)
1665e1051a39Sopenharmony_ci                return -1;
1666e1051a39Sopenharmony_ci
1667e1051a39Sopenharmony_ci            buf = EVP_CIPHER_CTX_buf_noconst(ctx);
1668e1051a39Sopenharmony_ci            if (CRYPTO_memcmp(buf, gctx->kma.param.t.b, gctx->taglen))
1669e1051a39Sopenharmony_ci                return -1;
1670e1051a39Sopenharmony_ci        }
1671e1051a39Sopenharmony_ci        return 0;
1672e1051a39Sopenharmony_ci    }
1673e1051a39Sopenharmony_ci}
1674e1051a39Sopenharmony_ci
1675e1051a39Sopenharmony_cistatic int s390x_aes_gcm_cleanup(EVP_CIPHER_CTX *c)
1676e1051a39Sopenharmony_ci{
1677e1051a39Sopenharmony_ci    S390X_AES_GCM_CTX *gctx = EVP_C_DATA(S390X_AES_GCM_CTX, c);
1678e1051a39Sopenharmony_ci
1679e1051a39Sopenharmony_ci    if (gctx == NULL)
1680e1051a39Sopenharmony_ci        return 0;
1681e1051a39Sopenharmony_ci
1682e1051a39Sopenharmony_ci    if (gctx->iv != c->iv)
1683e1051a39Sopenharmony_ci        OPENSSL_free(gctx->iv);
1684e1051a39Sopenharmony_ci
1685e1051a39Sopenharmony_ci    OPENSSL_cleanse(gctx, sizeof(*gctx));
1686e1051a39Sopenharmony_ci    return 1;
1687e1051a39Sopenharmony_ci}
1688e1051a39Sopenharmony_ci
1689e1051a39Sopenharmony_ci# define S390X_AES_XTS_CTX              EVP_AES_XTS_CTX
1690e1051a39Sopenharmony_ci
1691e1051a39Sopenharmony_ci# define s390x_aes_xts_init_key aes_xts_init_key
1692e1051a39Sopenharmony_cistatic int s390x_aes_xts_init_key(EVP_CIPHER_CTX *ctx,
1693e1051a39Sopenharmony_ci                                  const unsigned char *key,
1694e1051a39Sopenharmony_ci                                  const unsigned char *iv, int enc);
1695e1051a39Sopenharmony_ci# define s390x_aes_xts_cipher aes_xts_cipher
1696e1051a39Sopenharmony_cistatic int s390x_aes_xts_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
1697e1051a39Sopenharmony_ci                                const unsigned char *in, size_t len);
1698e1051a39Sopenharmony_ci# define s390x_aes_xts_ctrl aes_xts_ctrl
1699e1051a39Sopenharmony_cistatic int s390x_aes_xts_ctrl(EVP_CIPHER_CTX *, int type, int arg, void *ptr);
1700e1051a39Sopenharmony_ci# define s390x_aes_xts_cleanup aes_xts_cleanup
1701e1051a39Sopenharmony_ci
1702e1051a39Sopenharmony_ci/*-
1703e1051a39Sopenharmony_ci * Set nonce and length fields. Code is big-endian.
1704e1051a39Sopenharmony_ci */
1705e1051a39Sopenharmony_cistatic inline void s390x_aes_ccm_setiv(S390X_AES_CCM_CTX *ctx,
1706e1051a39Sopenharmony_ci                                          const unsigned char *nonce,
1707e1051a39Sopenharmony_ci                                          size_t mlen)
1708e1051a39Sopenharmony_ci{
1709e1051a39Sopenharmony_ci    ctx->aes.ccm.nonce.b[0] &= ~S390X_CCM_AAD_FLAG;
1710e1051a39Sopenharmony_ci    ctx->aes.ccm.nonce.g[1] = mlen;
1711e1051a39Sopenharmony_ci    memcpy(ctx->aes.ccm.nonce.b + 1, nonce, 15 - ctx->aes.ccm.l);
1712e1051a39Sopenharmony_ci}
1713e1051a39Sopenharmony_ci
1714e1051a39Sopenharmony_ci/*-
1715e1051a39Sopenharmony_ci * Process additional authenticated data. Code is big-endian.
1716e1051a39Sopenharmony_ci */
1717e1051a39Sopenharmony_cistatic void s390x_aes_ccm_aad(S390X_AES_CCM_CTX *ctx, const unsigned char *aad,
1718e1051a39Sopenharmony_ci                              size_t alen)
1719e1051a39Sopenharmony_ci{
1720e1051a39Sopenharmony_ci    unsigned char *ptr;
1721e1051a39Sopenharmony_ci    int i, rem;
1722e1051a39Sopenharmony_ci
1723e1051a39Sopenharmony_ci    if (!alen)
1724e1051a39Sopenharmony_ci        return;
1725e1051a39Sopenharmony_ci
1726e1051a39Sopenharmony_ci    ctx->aes.ccm.nonce.b[0] |= S390X_CCM_AAD_FLAG;
1727e1051a39Sopenharmony_ci
1728e1051a39Sopenharmony_ci    /* Suppress 'type-punned pointer dereference' warning. */
1729e1051a39Sopenharmony_ci    ptr = ctx->aes.ccm.buf.b;
1730e1051a39Sopenharmony_ci
1731e1051a39Sopenharmony_ci    if (alen < ((1 << 16) - (1 << 8))) {
1732e1051a39Sopenharmony_ci        *(uint16_t *)ptr = alen;
1733e1051a39Sopenharmony_ci        i = 2;
1734e1051a39Sopenharmony_ci    } else if (sizeof(alen) == 8
1735e1051a39Sopenharmony_ci               && alen >= (size_t)1 << (32 % (sizeof(alen) * 8))) {
1736e1051a39Sopenharmony_ci        *(uint16_t *)ptr = 0xffff;
1737e1051a39Sopenharmony_ci        *(uint64_t *)(ptr + 2) = alen;
1738e1051a39Sopenharmony_ci        i = 10;
1739e1051a39Sopenharmony_ci    } else {
1740e1051a39Sopenharmony_ci        *(uint16_t *)ptr = 0xfffe;
1741e1051a39Sopenharmony_ci        *(uint32_t *)(ptr + 2) = alen;
1742e1051a39Sopenharmony_ci        i = 6;
1743e1051a39Sopenharmony_ci    }
1744e1051a39Sopenharmony_ci
1745e1051a39Sopenharmony_ci    while (i < 16 && alen) {
1746e1051a39Sopenharmony_ci        ctx->aes.ccm.buf.b[i] = *aad;
1747e1051a39Sopenharmony_ci        ++aad;
1748e1051a39Sopenharmony_ci        --alen;
1749e1051a39Sopenharmony_ci        ++i;
1750e1051a39Sopenharmony_ci    }
1751e1051a39Sopenharmony_ci    while (i < 16) {
1752e1051a39Sopenharmony_ci        ctx->aes.ccm.buf.b[i] = 0;
1753e1051a39Sopenharmony_ci        ++i;
1754e1051a39Sopenharmony_ci    }
1755e1051a39Sopenharmony_ci
1756e1051a39Sopenharmony_ci    ctx->aes.ccm.kmac_param.icv.g[0] = 0;
1757e1051a39Sopenharmony_ci    ctx->aes.ccm.kmac_param.icv.g[1] = 0;
1758e1051a39Sopenharmony_ci    s390x_kmac(ctx->aes.ccm.nonce.b, 32, ctx->aes.ccm.fc,
1759e1051a39Sopenharmony_ci               &ctx->aes.ccm.kmac_param);
1760e1051a39Sopenharmony_ci    ctx->aes.ccm.blocks += 2;
1761e1051a39Sopenharmony_ci
1762e1051a39Sopenharmony_ci    rem = alen & 0xf;
1763e1051a39Sopenharmony_ci    alen &= ~(size_t)0xf;
1764e1051a39Sopenharmony_ci    if (alen) {
1765e1051a39Sopenharmony_ci        s390x_kmac(aad, alen, ctx->aes.ccm.fc, &ctx->aes.ccm.kmac_param);
1766e1051a39Sopenharmony_ci        ctx->aes.ccm.blocks += alen >> 4;
1767e1051a39Sopenharmony_ci        aad += alen;
1768e1051a39Sopenharmony_ci    }
1769e1051a39Sopenharmony_ci    if (rem) {
1770e1051a39Sopenharmony_ci        for (i = 0; i < rem; i++)
1771e1051a39Sopenharmony_ci            ctx->aes.ccm.kmac_param.icv.b[i] ^= aad[i];
1772e1051a39Sopenharmony_ci
1773e1051a39Sopenharmony_ci        s390x_km(ctx->aes.ccm.kmac_param.icv.b, 16,
1774e1051a39Sopenharmony_ci                 ctx->aes.ccm.kmac_param.icv.b, ctx->aes.ccm.fc,
1775e1051a39Sopenharmony_ci                 ctx->aes.ccm.kmac_param.k);
1776e1051a39Sopenharmony_ci        ctx->aes.ccm.blocks++;
1777e1051a39Sopenharmony_ci    }
1778e1051a39Sopenharmony_ci}
1779e1051a39Sopenharmony_ci
1780e1051a39Sopenharmony_ci/*-
1781e1051a39Sopenharmony_ci * En/de-crypt plain/cipher-text. Compute tag from plaintext. Returns 0 for
1782e1051a39Sopenharmony_ci * success.
1783e1051a39Sopenharmony_ci */
1784e1051a39Sopenharmony_cistatic int s390x_aes_ccm(S390X_AES_CCM_CTX *ctx, const unsigned char *in,
1785e1051a39Sopenharmony_ci                         unsigned char *out, size_t len, int enc)
1786e1051a39Sopenharmony_ci{
1787e1051a39Sopenharmony_ci    size_t n, rem;
1788e1051a39Sopenharmony_ci    unsigned int i, l, num;
1789e1051a39Sopenharmony_ci    unsigned char flags;
1790e1051a39Sopenharmony_ci
1791e1051a39Sopenharmony_ci    flags = ctx->aes.ccm.nonce.b[0];
1792e1051a39Sopenharmony_ci    if (!(flags & S390X_CCM_AAD_FLAG)) {
1793e1051a39Sopenharmony_ci        s390x_km(ctx->aes.ccm.nonce.b, 16, ctx->aes.ccm.kmac_param.icv.b,
1794e1051a39Sopenharmony_ci                 ctx->aes.ccm.fc, ctx->aes.ccm.kmac_param.k);
1795e1051a39Sopenharmony_ci        ctx->aes.ccm.blocks++;
1796e1051a39Sopenharmony_ci    }
1797e1051a39Sopenharmony_ci    l = flags & 0x7;
1798e1051a39Sopenharmony_ci    ctx->aes.ccm.nonce.b[0] = l;
1799e1051a39Sopenharmony_ci
1800e1051a39Sopenharmony_ci    /*-
1801e1051a39Sopenharmony_ci     * Reconstruct length from encoded length field
1802e1051a39Sopenharmony_ci     * and initialize it with counter value.
1803e1051a39Sopenharmony_ci     */
1804e1051a39Sopenharmony_ci    n = 0;
1805e1051a39Sopenharmony_ci    for (i = 15 - l; i < 15; i++) {
1806e1051a39Sopenharmony_ci        n |= ctx->aes.ccm.nonce.b[i];
1807e1051a39Sopenharmony_ci        ctx->aes.ccm.nonce.b[i] = 0;
1808e1051a39Sopenharmony_ci        n <<= 8;
1809e1051a39Sopenharmony_ci    }
1810e1051a39Sopenharmony_ci    n |= ctx->aes.ccm.nonce.b[15];
1811e1051a39Sopenharmony_ci    ctx->aes.ccm.nonce.b[15] = 1;
1812e1051a39Sopenharmony_ci
1813e1051a39Sopenharmony_ci    if (n != len)
1814e1051a39Sopenharmony_ci        return -1;              /* length mismatch */
1815e1051a39Sopenharmony_ci
1816e1051a39Sopenharmony_ci    if (enc) {
1817e1051a39Sopenharmony_ci        /* Two operations per block plus one for tag encryption */
1818e1051a39Sopenharmony_ci        ctx->aes.ccm.blocks += (((len + 15) >> 4) << 1) + 1;
1819e1051a39Sopenharmony_ci        if (ctx->aes.ccm.blocks > (1ULL << 61))
1820e1051a39Sopenharmony_ci            return -2;          /* too much data */
1821e1051a39Sopenharmony_ci    }
1822e1051a39Sopenharmony_ci
1823e1051a39Sopenharmony_ci    num = 0;
1824e1051a39Sopenharmony_ci    rem = len & 0xf;
1825e1051a39Sopenharmony_ci    len &= ~(size_t)0xf;
1826e1051a39Sopenharmony_ci
1827e1051a39Sopenharmony_ci    if (enc) {
1828e1051a39Sopenharmony_ci        /* mac-then-encrypt */
1829e1051a39Sopenharmony_ci        if (len)
1830e1051a39Sopenharmony_ci            s390x_kmac(in, len, ctx->aes.ccm.fc, &ctx->aes.ccm.kmac_param);
1831e1051a39Sopenharmony_ci        if (rem) {
1832e1051a39Sopenharmony_ci            for (i = 0; i < rem; i++)
1833e1051a39Sopenharmony_ci                ctx->aes.ccm.kmac_param.icv.b[i] ^= in[len + i];
1834e1051a39Sopenharmony_ci
1835e1051a39Sopenharmony_ci            s390x_km(ctx->aes.ccm.kmac_param.icv.b, 16,
1836e1051a39Sopenharmony_ci                     ctx->aes.ccm.kmac_param.icv.b, ctx->aes.ccm.fc,
1837e1051a39Sopenharmony_ci                     ctx->aes.ccm.kmac_param.k);
1838e1051a39Sopenharmony_ci        }
1839e1051a39Sopenharmony_ci
1840e1051a39Sopenharmony_ci        CRYPTO_ctr128_encrypt_ctr32(in, out, len + rem, &ctx->aes.key.k,
1841e1051a39Sopenharmony_ci                                    ctx->aes.ccm.nonce.b, ctx->aes.ccm.buf.b,
1842e1051a39Sopenharmony_ci                                    &num, (ctr128_f)AES_ctr32_encrypt);
1843e1051a39Sopenharmony_ci    } else {
1844e1051a39Sopenharmony_ci        /* decrypt-then-mac */
1845e1051a39Sopenharmony_ci        CRYPTO_ctr128_encrypt_ctr32(in, out, len + rem, &ctx->aes.key.k,
1846e1051a39Sopenharmony_ci                                    ctx->aes.ccm.nonce.b, ctx->aes.ccm.buf.b,
1847e1051a39Sopenharmony_ci                                    &num, (ctr128_f)AES_ctr32_encrypt);
1848e1051a39Sopenharmony_ci
1849e1051a39Sopenharmony_ci        if (len)
1850e1051a39Sopenharmony_ci            s390x_kmac(out, len, ctx->aes.ccm.fc, &ctx->aes.ccm.kmac_param);
1851e1051a39Sopenharmony_ci        if (rem) {
1852e1051a39Sopenharmony_ci            for (i = 0; i < rem; i++)
1853e1051a39Sopenharmony_ci                ctx->aes.ccm.kmac_param.icv.b[i] ^= out[len + i];
1854e1051a39Sopenharmony_ci
1855e1051a39Sopenharmony_ci            s390x_km(ctx->aes.ccm.kmac_param.icv.b, 16,
1856e1051a39Sopenharmony_ci                     ctx->aes.ccm.kmac_param.icv.b, ctx->aes.ccm.fc,
1857e1051a39Sopenharmony_ci                     ctx->aes.ccm.kmac_param.k);
1858e1051a39Sopenharmony_ci        }
1859e1051a39Sopenharmony_ci    }
1860e1051a39Sopenharmony_ci    /* encrypt tag */
1861e1051a39Sopenharmony_ci    for (i = 15 - l; i < 16; i++)
1862e1051a39Sopenharmony_ci        ctx->aes.ccm.nonce.b[i] = 0;
1863e1051a39Sopenharmony_ci
1864e1051a39Sopenharmony_ci    s390x_km(ctx->aes.ccm.nonce.b, 16, ctx->aes.ccm.buf.b, ctx->aes.ccm.fc,
1865e1051a39Sopenharmony_ci             ctx->aes.ccm.kmac_param.k);
1866e1051a39Sopenharmony_ci    ctx->aes.ccm.kmac_param.icv.g[0] ^= ctx->aes.ccm.buf.g[0];
1867e1051a39Sopenharmony_ci    ctx->aes.ccm.kmac_param.icv.g[1] ^= ctx->aes.ccm.buf.g[1];
1868e1051a39Sopenharmony_ci
1869e1051a39Sopenharmony_ci    ctx->aes.ccm.nonce.b[0] = flags;    /* restore flags field */
1870e1051a39Sopenharmony_ci    return 0;
1871e1051a39Sopenharmony_ci}
1872e1051a39Sopenharmony_ci
1873e1051a39Sopenharmony_ci/*-
1874e1051a39Sopenharmony_ci * En/de-crypt and authenticate TLS packet. Returns the number of bytes written
1875e1051a39Sopenharmony_ci * if successful. Otherwise -1 is returned.
1876e1051a39Sopenharmony_ci */
1877e1051a39Sopenharmony_cistatic int s390x_aes_ccm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
1878e1051a39Sopenharmony_ci                                    const unsigned char *in, size_t len)
1879e1051a39Sopenharmony_ci{
1880e1051a39Sopenharmony_ci    S390X_AES_CCM_CTX *cctx = EVP_C_DATA(S390X_AES_CCM_CTX, ctx);
1881e1051a39Sopenharmony_ci    unsigned char *ivec = ctx->iv;
1882e1051a39Sopenharmony_ci    unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx);
1883e1051a39Sopenharmony_ci    const int enc = EVP_CIPHER_CTX_is_encrypting(ctx);
1884e1051a39Sopenharmony_ci
1885e1051a39Sopenharmony_ci    if (out != in
1886e1051a39Sopenharmony_ci            || len < (EVP_CCM_TLS_EXPLICIT_IV_LEN + (size_t)cctx->aes.ccm.m))
1887e1051a39Sopenharmony_ci        return -1;
1888e1051a39Sopenharmony_ci
1889e1051a39Sopenharmony_ci    if (enc) {
1890e1051a39Sopenharmony_ci        /* Set explicit iv (sequence number). */
1891e1051a39Sopenharmony_ci        memcpy(out, buf, EVP_CCM_TLS_EXPLICIT_IV_LEN);
1892e1051a39Sopenharmony_ci    }
1893e1051a39Sopenharmony_ci
1894e1051a39Sopenharmony_ci    len -= EVP_CCM_TLS_EXPLICIT_IV_LEN + cctx->aes.ccm.m;
1895e1051a39Sopenharmony_ci    /*-
1896e1051a39Sopenharmony_ci     * Get explicit iv (sequence number). We already have fixed iv
1897e1051a39Sopenharmony_ci     * (server/client_write_iv) here.
1898e1051a39Sopenharmony_ci     */
1899e1051a39Sopenharmony_ci    memcpy(ivec + EVP_CCM_TLS_FIXED_IV_LEN, in, EVP_CCM_TLS_EXPLICIT_IV_LEN);
1900e1051a39Sopenharmony_ci    s390x_aes_ccm_setiv(cctx, ivec, len);
1901e1051a39Sopenharmony_ci
1902e1051a39Sopenharmony_ci    /* Process aad (sequence number|type|version|length) */
1903e1051a39Sopenharmony_ci    s390x_aes_ccm_aad(cctx, buf, cctx->aes.ccm.tls_aad_len);
1904e1051a39Sopenharmony_ci
1905e1051a39Sopenharmony_ci    in += EVP_CCM_TLS_EXPLICIT_IV_LEN;
1906e1051a39Sopenharmony_ci    out += EVP_CCM_TLS_EXPLICIT_IV_LEN;
1907e1051a39Sopenharmony_ci
1908e1051a39Sopenharmony_ci    if (enc) {
1909e1051a39Sopenharmony_ci        if (s390x_aes_ccm(cctx, in, out, len, enc))
1910e1051a39Sopenharmony_ci            return -1;
1911e1051a39Sopenharmony_ci
1912e1051a39Sopenharmony_ci        memcpy(out + len, cctx->aes.ccm.kmac_param.icv.b, cctx->aes.ccm.m);
1913e1051a39Sopenharmony_ci        return len + EVP_CCM_TLS_EXPLICIT_IV_LEN + cctx->aes.ccm.m;
1914e1051a39Sopenharmony_ci    } else {
1915e1051a39Sopenharmony_ci        if (!s390x_aes_ccm(cctx, in, out, len, enc)) {
1916e1051a39Sopenharmony_ci            if (!CRYPTO_memcmp(cctx->aes.ccm.kmac_param.icv.b, in + len,
1917e1051a39Sopenharmony_ci                               cctx->aes.ccm.m))
1918e1051a39Sopenharmony_ci                return len;
1919e1051a39Sopenharmony_ci        }
1920e1051a39Sopenharmony_ci
1921e1051a39Sopenharmony_ci        OPENSSL_cleanse(out, len);
1922e1051a39Sopenharmony_ci        return -1;
1923e1051a39Sopenharmony_ci    }
1924e1051a39Sopenharmony_ci}
1925e1051a39Sopenharmony_ci
1926e1051a39Sopenharmony_ci/*-
1927e1051a39Sopenharmony_ci * Set key and flag field and/or iv. Returns 1 if successful. Otherwise 0 is
1928e1051a39Sopenharmony_ci * returned.
1929e1051a39Sopenharmony_ci */
1930e1051a39Sopenharmony_cistatic int s390x_aes_ccm_init_key(EVP_CIPHER_CTX *ctx,
1931e1051a39Sopenharmony_ci                                  const unsigned char *key,
1932e1051a39Sopenharmony_ci                                  const unsigned char *iv, int enc)
1933e1051a39Sopenharmony_ci{
1934e1051a39Sopenharmony_ci    S390X_AES_CCM_CTX *cctx = EVP_C_DATA(S390X_AES_CCM_CTX, ctx);
1935e1051a39Sopenharmony_ci    int keylen;
1936e1051a39Sopenharmony_ci
1937e1051a39Sopenharmony_ci    if (iv == NULL && key == NULL)
1938e1051a39Sopenharmony_ci        return 1;
1939e1051a39Sopenharmony_ci
1940e1051a39Sopenharmony_ci    if (key != NULL) {
1941e1051a39Sopenharmony_ci        keylen = EVP_CIPHER_CTX_get_key_length(ctx);
1942e1051a39Sopenharmony_ci        cctx->aes.ccm.fc = S390X_AES_FC(keylen);
1943e1051a39Sopenharmony_ci        memcpy(cctx->aes.ccm.kmac_param.k, key, keylen);
1944e1051a39Sopenharmony_ci
1945e1051a39Sopenharmony_ci        /* Store encoded m and l. */
1946e1051a39Sopenharmony_ci        cctx->aes.ccm.nonce.b[0] = ((cctx->aes.ccm.l - 1) & 0x7)
1947e1051a39Sopenharmony_ci                                 | (((cctx->aes.ccm.m - 2) >> 1) & 0x7) << 3;
1948e1051a39Sopenharmony_ci        memset(cctx->aes.ccm.nonce.b + 1, 0,
1949e1051a39Sopenharmony_ci               sizeof(cctx->aes.ccm.nonce.b));
1950e1051a39Sopenharmony_ci        cctx->aes.ccm.blocks = 0;
1951e1051a39Sopenharmony_ci
1952e1051a39Sopenharmony_ci        cctx->aes.ccm.key_set = 1;
1953e1051a39Sopenharmony_ci    }
1954e1051a39Sopenharmony_ci
1955e1051a39Sopenharmony_ci    if (iv != NULL) {
1956e1051a39Sopenharmony_ci        memcpy(ctx->iv, iv, 15 - cctx->aes.ccm.l);
1957e1051a39Sopenharmony_ci
1958e1051a39Sopenharmony_ci        cctx->aes.ccm.iv_set = 1;
1959e1051a39Sopenharmony_ci    }
1960e1051a39Sopenharmony_ci
1961e1051a39Sopenharmony_ci    return 1;
1962e1051a39Sopenharmony_ci}
1963e1051a39Sopenharmony_ci
1964e1051a39Sopenharmony_ci/*-
1965e1051a39Sopenharmony_ci * Called from EVP layer to initialize context, process additional
1966e1051a39Sopenharmony_ci * authenticated data, en/de-crypt plain/cipher-text and authenticate
1967e1051a39Sopenharmony_ci * plaintext or process a TLS packet, depending on context. Returns bytes
1968e1051a39Sopenharmony_ci * written on success. Otherwise -1 is returned.
1969e1051a39Sopenharmony_ci */
1970e1051a39Sopenharmony_cistatic int s390x_aes_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
1971e1051a39Sopenharmony_ci                                const unsigned char *in, size_t len)
1972e1051a39Sopenharmony_ci{
1973e1051a39Sopenharmony_ci    S390X_AES_CCM_CTX *cctx = EVP_C_DATA(S390X_AES_CCM_CTX, ctx);
1974e1051a39Sopenharmony_ci    const int enc = EVP_CIPHER_CTX_is_encrypting(ctx);
1975e1051a39Sopenharmony_ci    int rv;
1976e1051a39Sopenharmony_ci    unsigned char *buf;
1977e1051a39Sopenharmony_ci
1978e1051a39Sopenharmony_ci    if (!cctx->aes.ccm.key_set)
1979e1051a39Sopenharmony_ci        return -1;
1980e1051a39Sopenharmony_ci
1981e1051a39Sopenharmony_ci    if (cctx->aes.ccm.tls_aad_len >= 0)
1982e1051a39Sopenharmony_ci        return s390x_aes_ccm_tls_cipher(ctx, out, in, len);
1983e1051a39Sopenharmony_ci
1984e1051a39Sopenharmony_ci    /*-
1985e1051a39Sopenharmony_ci     * Final(): Does not return any data. Recall that ccm is mac-then-encrypt
1986e1051a39Sopenharmony_ci     * so integrity must be checked already at Update() i.e., before
1987e1051a39Sopenharmony_ci     * potentially corrupted data is output.
1988e1051a39Sopenharmony_ci     */
1989e1051a39Sopenharmony_ci    if (in == NULL && out != NULL)
1990e1051a39Sopenharmony_ci        return 0;
1991e1051a39Sopenharmony_ci
1992e1051a39Sopenharmony_ci    if (!cctx->aes.ccm.iv_set)
1993e1051a39Sopenharmony_ci        return -1;
1994e1051a39Sopenharmony_ci
1995e1051a39Sopenharmony_ci    if (out == NULL) {
1996e1051a39Sopenharmony_ci        /* Update(): Pass message length. */
1997e1051a39Sopenharmony_ci        if (in == NULL) {
1998e1051a39Sopenharmony_ci            s390x_aes_ccm_setiv(cctx, ctx->iv, len);
1999e1051a39Sopenharmony_ci
2000e1051a39Sopenharmony_ci            cctx->aes.ccm.len_set = 1;
2001e1051a39Sopenharmony_ci            return len;
2002e1051a39Sopenharmony_ci        }
2003e1051a39Sopenharmony_ci
2004e1051a39Sopenharmony_ci        /* Update(): Process aad. */
2005e1051a39Sopenharmony_ci        if (!cctx->aes.ccm.len_set && len)
2006e1051a39Sopenharmony_ci            return -1;
2007e1051a39Sopenharmony_ci
2008e1051a39Sopenharmony_ci        s390x_aes_ccm_aad(cctx, in, len);
2009e1051a39Sopenharmony_ci        return len;
2010e1051a39Sopenharmony_ci    }
2011e1051a39Sopenharmony_ci
2012e1051a39Sopenharmony_ci    /* The tag must be set before actually decrypting data */
2013e1051a39Sopenharmony_ci    if (!enc && !cctx->aes.ccm.tag_set)
2014e1051a39Sopenharmony_ci        return -1;
2015e1051a39Sopenharmony_ci
2016e1051a39Sopenharmony_ci    /* Update(): Process message. */
2017e1051a39Sopenharmony_ci
2018e1051a39Sopenharmony_ci    if (!cctx->aes.ccm.len_set) {
2019e1051a39Sopenharmony_ci        /*-
2020e1051a39Sopenharmony_ci         * In case message length was not previously set explicitly via
2021e1051a39Sopenharmony_ci         * Update(), set it now.
2022e1051a39Sopenharmony_ci         */
2023e1051a39Sopenharmony_ci        s390x_aes_ccm_setiv(cctx, ctx->iv, len);
2024e1051a39Sopenharmony_ci
2025e1051a39Sopenharmony_ci        cctx->aes.ccm.len_set = 1;
2026e1051a39Sopenharmony_ci    }
2027e1051a39Sopenharmony_ci
2028e1051a39Sopenharmony_ci    if (enc) {
2029e1051a39Sopenharmony_ci        if (s390x_aes_ccm(cctx, in, out, len, enc))
2030e1051a39Sopenharmony_ci            return -1;
2031e1051a39Sopenharmony_ci
2032e1051a39Sopenharmony_ci        cctx->aes.ccm.tag_set = 1;
2033e1051a39Sopenharmony_ci        return len;
2034e1051a39Sopenharmony_ci    } else {
2035e1051a39Sopenharmony_ci        rv = -1;
2036e1051a39Sopenharmony_ci
2037e1051a39Sopenharmony_ci        if (!s390x_aes_ccm(cctx, in, out, len, enc)) {
2038e1051a39Sopenharmony_ci            buf = EVP_CIPHER_CTX_buf_noconst(ctx);
2039e1051a39Sopenharmony_ci            if (!CRYPTO_memcmp(cctx->aes.ccm.kmac_param.icv.b, buf,
2040e1051a39Sopenharmony_ci                               cctx->aes.ccm.m))
2041e1051a39Sopenharmony_ci                rv = len;
2042e1051a39Sopenharmony_ci        }
2043e1051a39Sopenharmony_ci
2044e1051a39Sopenharmony_ci        if (rv == -1)
2045e1051a39Sopenharmony_ci            OPENSSL_cleanse(out, len);
2046e1051a39Sopenharmony_ci
2047e1051a39Sopenharmony_ci        cctx->aes.ccm.iv_set = 0;
2048e1051a39Sopenharmony_ci        cctx->aes.ccm.tag_set = 0;
2049e1051a39Sopenharmony_ci        cctx->aes.ccm.len_set = 0;
2050e1051a39Sopenharmony_ci        return rv;
2051e1051a39Sopenharmony_ci    }
2052e1051a39Sopenharmony_ci}
2053e1051a39Sopenharmony_ci
2054e1051a39Sopenharmony_ci/*-
2055e1051a39Sopenharmony_ci * Performs various operations on the context structure depending on control
2056e1051a39Sopenharmony_ci * type. Returns 1 for success, 0 for failure and -1 for unknown control type.
2057e1051a39Sopenharmony_ci * Code is big-endian.
2058e1051a39Sopenharmony_ci */
2059e1051a39Sopenharmony_cistatic int s390x_aes_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
2060e1051a39Sopenharmony_ci{
2061e1051a39Sopenharmony_ci    S390X_AES_CCM_CTX *cctx = EVP_C_DATA(S390X_AES_CCM_CTX, c);
2062e1051a39Sopenharmony_ci    unsigned char *buf;
2063e1051a39Sopenharmony_ci    int enc, len;
2064e1051a39Sopenharmony_ci
2065e1051a39Sopenharmony_ci    switch (type) {
2066e1051a39Sopenharmony_ci    case EVP_CTRL_INIT:
2067e1051a39Sopenharmony_ci        cctx->aes.ccm.key_set = 0;
2068e1051a39Sopenharmony_ci        cctx->aes.ccm.iv_set = 0;
2069e1051a39Sopenharmony_ci        cctx->aes.ccm.l = 8;
2070e1051a39Sopenharmony_ci        cctx->aes.ccm.m = 12;
2071e1051a39Sopenharmony_ci        cctx->aes.ccm.tag_set = 0;
2072e1051a39Sopenharmony_ci        cctx->aes.ccm.len_set = 0;
2073e1051a39Sopenharmony_ci        cctx->aes.ccm.tls_aad_len = -1;
2074e1051a39Sopenharmony_ci        return 1;
2075e1051a39Sopenharmony_ci
2076e1051a39Sopenharmony_ci    case EVP_CTRL_GET_IVLEN:
2077e1051a39Sopenharmony_ci        *(int *)ptr = 15 - cctx->aes.ccm.l;
2078e1051a39Sopenharmony_ci        return 1;
2079e1051a39Sopenharmony_ci
2080e1051a39Sopenharmony_ci    case EVP_CTRL_AEAD_TLS1_AAD:
2081e1051a39Sopenharmony_ci        if (arg != EVP_AEAD_TLS1_AAD_LEN)
2082e1051a39Sopenharmony_ci            return 0;
2083e1051a39Sopenharmony_ci
2084e1051a39Sopenharmony_ci        /* Save the aad for later use. */
2085e1051a39Sopenharmony_ci        buf = EVP_CIPHER_CTX_buf_noconst(c);
2086e1051a39Sopenharmony_ci        memcpy(buf, ptr, arg);
2087e1051a39Sopenharmony_ci        cctx->aes.ccm.tls_aad_len = arg;
2088e1051a39Sopenharmony_ci
2089e1051a39Sopenharmony_ci        len = buf[arg - 2] << 8 | buf[arg - 1];
2090e1051a39Sopenharmony_ci        if (len < EVP_CCM_TLS_EXPLICIT_IV_LEN)
2091e1051a39Sopenharmony_ci            return 0;
2092e1051a39Sopenharmony_ci
2093e1051a39Sopenharmony_ci        /* Correct length for explicit iv. */
2094e1051a39Sopenharmony_ci        len -= EVP_CCM_TLS_EXPLICIT_IV_LEN;
2095e1051a39Sopenharmony_ci
2096e1051a39Sopenharmony_ci        enc = EVP_CIPHER_CTX_is_encrypting(c);
2097e1051a39Sopenharmony_ci        if (!enc) {
2098e1051a39Sopenharmony_ci            if (len < cctx->aes.ccm.m)
2099e1051a39Sopenharmony_ci                return 0;
2100e1051a39Sopenharmony_ci
2101e1051a39Sopenharmony_ci            /* Correct length for tag. */
2102e1051a39Sopenharmony_ci            len -= cctx->aes.ccm.m;
2103e1051a39Sopenharmony_ci        }
2104e1051a39Sopenharmony_ci
2105e1051a39Sopenharmony_ci        buf[arg - 2] = len >> 8;
2106e1051a39Sopenharmony_ci        buf[arg - 1] = len & 0xff;
2107e1051a39Sopenharmony_ci
2108e1051a39Sopenharmony_ci        /* Extra padding: tag appended to record. */
2109e1051a39Sopenharmony_ci        return cctx->aes.ccm.m;
2110e1051a39Sopenharmony_ci
2111e1051a39Sopenharmony_ci    case EVP_CTRL_CCM_SET_IV_FIXED:
2112e1051a39Sopenharmony_ci        if (arg != EVP_CCM_TLS_FIXED_IV_LEN)
2113e1051a39Sopenharmony_ci            return 0;
2114e1051a39Sopenharmony_ci
2115e1051a39Sopenharmony_ci        /* Copy to first part of the iv. */
2116e1051a39Sopenharmony_ci        memcpy(c->iv, ptr, arg);
2117e1051a39Sopenharmony_ci        return 1;
2118e1051a39Sopenharmony_ci
2119e1051a39Sopenharmony_ci    case EVP_CTRL_AEAD_SET_IVLEN:
2120e1051a39Sopenharmony_ci        arg = 15 - arg;
2121e1051a39Sopenharmony_ci        /* fall-through */
2122e1051a39Sopenharmony_ci
2123e1051a39Sopenharmony_ci    case EVP_CTRL_CCM_SET_L:
2124e1051a39Sopenharmony_ci        if (arg < 2 || arg > 8)
2125e1051a39Sopenharmony_ci            return 0;
2126e1051a39Sopenharmony_ci
2127e1051a39Sopenharmony_ci        cctx->aes.ccm.l = arg;
2128e1051a39Sopenharmony_ci        return 1;
2129e1051a39Sopenharmony_ci
2130e1051a39Sopenharmony_ci    case EVP_CTRL_AEAD_SET_TAG:
2131e1051a39Sopenharmony_ci        if ((arg & 1) || arg < 4 || arg > 16)
2132e1051a39Sopenharmony_ci            return 0;
2133e1051a39Sopenharmony_ci
2134e1051a39Sopenharmony_ci        enc = EVP_CIPHER_CTX_is_encrypting(c);
2135e1051a39Sopenharmony_ci        if (enc && ptr)
2136e1051a39Sopenharmony_ci            return 0;
2137e1051a39Sopenharmony_ci
2138e1051a39Sopenharmony_ci        if (ptr) {
2139e1051a39Sopenharmony_ci            cctx->aes.ccm.tag_set = 1;
2140e1051a39Sopenharmony_ci            buf = EVP_CIPHER_CTX_buf_noconst(c);
2141e1051a39Sopenharmony_ci            memcpy(buf, ptr, arg);
2142e1051a39Sopenharmony_ci        }
2143e1051a39Sopenharmony_ci
2144e1051a39Sopenharmony_ci        cctx->aes.ccm.m = arg;
2145e1051a39Sopenharmony_ci        return 1;
2146e1051a39Sopenharmony_ci
2147e1051a39Sopenharmony_ci    case EVP_CTRL_AEAD_GET_TAG:
2148e1051a39Sopenharmony_ci        enc = EVP_CIPHER_CTX_is_encrypting(c);
2149e1051a39Sopenharmony_ci        if (!enc || !cctx->aes.ccm.tag_set)
2150e1051a39Sopenharmony_ci            return 0;
2151e1051a39Sopenharmony_ci
2152e1051a39Sopenharmony_ci        if(arg < cctx->aes.ccm.m)
2153e1051a39Sopenharmony_ci            return 0;
2154e1051a39Sopenharmony_ci
2155e1051a39Sopenharmony_ci        memcpy(ptr, cctx->aes.ccm.kmac_param.icv.b, cctx->aes.ccm.m);
2156e1051a39Sopenharmony_ci        cctx->aes.ccm.tag_set = 0;
2157e1051a39Sopenharmony_ci        cctx->aes.ccm.iv_set = 0;
2158e1051a39Sopenharmony_ci        cctx->aes.ccm.len_set = 0;
2159e1051a39Sopenharmony_ci        return 1;
2160e1051a39Sopenharmony_ci
2161e1051a39Sopenharmony_ci    case EVP_CTRL_COPY:
2162e1051a39Sopenharmony_ci        return 1;
2163e1051a39Sopenharmony_ci
2164e1051a39Sopenharmony_ci    default:
2165e1051a39Sopenharmony_ci        return -1;
2166e1051a39Sopenharmony_ci    }
2167e1051a39Sopenharmony_ci}
2168e1051a39Sopenharmony_ci
2169e1051a39Sopenharmony_ci# define s390x_aes_ccm_cleanup aes_ccm_cleanup
2170e1051a39Sopenharmony_ci
2171e1051a39Sopenharmony_ci# ifndef OPENSSL_NO_OCB
2172e1051a39Sopenharmony_ci#  define S390X_AES_OCB_CTX             EVP_AES_OCB_CTX
2173e1051a39Sopenharmony_ci
2174e1051a39Sopenharmony_ci#  define s390x_aes_ocb_init_key aes_ocb_init_key
2175e1051a39Sopenharmony_cistatic int s390x_aes_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
2176e1051a39Sopenharmony_ci                                  const unsigned char *iv, int enc);
2177e1051a39Sopenharmony_ci#  define s390x_aes_ocb_cipher aes_ocb_cipher
2178e1051a39Sopenharmony_cistatic int s390x_aes_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
2179e1051a39Sopenharmony_ci                                const unsigned char *in, size_t len);
2180e1051a39Sopenharmony_ci#  define s390x_aes_ocb_cleanup aes_ocb_cleanup
2181e1051a39Sopenharmony_cistatic int s390x_aes_ocb_cleanup(EVP_CIPHER_CTX *);
2182e1051a39Sopenharmony_ci#  define s390x_aes_ocb_ctrl aes_ocb_ctrl
2183e1051a39Sopenharmony_cistatic int s390x_aes_ocb_ctrl(EVP_CIPHER_CTX *, int type, int arg, void *ptr);
2184e1051a39Sopenharmony_ci# endif
2185e1051a39Sopenharmony_ci
2186e1051a39Sopenharmony_ci# ifndef OPENSSL_NO_SIV
2187e1051a39Sopenharmony_ci#  define S390X_AES_SIV_CTX             EVP_AES_SIV_CTX
2188e1051a39Sopenharmony_ci
2189e1051a39Sopenharmony_ci#  define s390x_aes_siv_init_key aes_siv_init_key
2190e1051a39Sopenharmony_ci#  define s390x_aes_siv_cipher aes_siv_cipher
2191e1051a39Sopenharmony_ci#  define s390x_aes_siv_cleanup aes_siv_cleanup
2192e1051a39Sopenharmony_ci#  define s390x_aes_siv_ctrl aes_siv_ctrl
2193e1051a39Sopenharmony_ci# endif
2194e1051a39Sopenharmony_ci
2195e1051a39Sopenharmony_ci# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,    \
2196e1051a39Sopenharmony_ci                              MODE,flags)                               \
2197e1051a39Sopenharmony_cistatic const EVP_CIPHER s390x_aes_##keylen##_##mode = {                 \
2198e1051a39Sopenharmony_ci    nid##_##keylen##_##nmode,blocksize,                                 \
2199e1051a39Sopenharmony_ci    keylen / 8,                                                         \
2200e1051a39Sopenharmony_ci    ivlen,                                                              \
2201e1051a39Sopenharmony_ci    flags | EVP_CIPH_##MODE##_MODE,                                     \
2202e1051a39Sopenharmony_ci    EVP_ORIG_GLOBAL,                                                    \
2203e1051a39Sopenharmony_ci    s390x_aes_##mode##_init_key,                                        \
2204e1051a39Sopenharmony_ci    s390x_aes_##mode##_cipher,                                          \
2205e1051a39Sopenharmony_ci    NULL,                                                               \
2206e1051a39Sopenharmony_ci    sizeof(S390X_AES_##MODE##_CTX),                                     \
2207e1051a39Sopenharmony_ci    NULL,                                                               \
2208e1051a39Sopenharmony_ci    NULL,                                                               \
2209e1051a39Sopenharmony_ci    NULL,                                                               \
2210e1051a39Sopenharmony_ci    NULL                                                                \
2211e1051a39Sopenharmony_ci};                                                                      \
2212e1051a39Sopenharmony_cistatic const EVP_CIPHER aes_##keylen##_##mode = {                       \
2213e1051a39Sopenharmony_ci    nid##_##keylen##_##nmode,                                           \
2214e1051a39Sopenharmony_ci    blocksize,                                                          \
2215e1051a39Sopenharmony_ci    keylen / 8,                                                         \
2216e1051a39Sopenharmony_ci    ivlen,                                                              \
2217e1051a39Sopenharmony_ci    flags | EVP_CIPH_##MODE##_MODE,                                     \
2218e1051a39Sopenharmony_ci    EVP_ORIG_GLOBAL,                                                    \
2219e1051a39Sopenharmony_ci    aes_init_key,                                                       \
2220e1051a39Sopenharmony_ci    aes_##mode##_cipher,                                                \
2221e1051a39Sopenharmony_ci    NULL,                                                               \
2222e1051a39Sopenharmony_ci    sizeof(EVP_AES_KEY),                                                \
2223e1051a39Sopenharmony_ci    NULL,                                                               \
2224e1051a39Sopenharmony_ci    NULL,                                                               \
2225e1051a39Sopenharmony_ci    NULL,                                                               \
2226e1051a39Sopenharmony_ci    NULL                                                                \
2227e1051a39Sopenharmony_ci};                                                                      \
2228e1051a39Sopenharmony_ciconst EVP_CIPHER *EVP_aes_##keylen##_##mode(void)                       \
2229e1051a39Sopenharmony_ci{                                                                       \
2230e1051a39Sopenharmony_ci    return S390X_aes_##keylen##_##mode##_CAPABLE ?                      \
2231e1051a39Sopenharmony_ci           &s390x_aes_##keylen##_##mode : &aes_##keylen##_##mode;       \
2232e1051a39Sopenharmony_ci}
2233e1051a39Sopenharmony_ci
2234e1051a39Sopenharmony_ci# define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags)\
2235e1051a39Sopenharmony_cistatic const EVP_CIPHER s390x_aes_##keylen##_##mode = {                 \
2236e1051a39Sopenharmony_ci    nid##_##keylen##_##mode,                                            \
2237e1051a39Sopenharmony_ci    blocksize,                                                          \
2238e1051a39Sopenharmony_ci    (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE||EVP_CIPH_##MODE##_MODE==EVP_CIPH_SIV_MODE ? 2 : 1) * keylen / 8,        \
2239e1051a39Sopenharmony_ci    ivlen,                                                              \
2240e1051a39Sopenharmony_ci    flags | EVP_CIPH_##MODE##_MODE,                                     \
2241e1051a39Sopenharmony_ci    EVP_ORIG_GLOBAL,                                                    \
2242e1051a39Sopenharmony_ci    s390x_aes_##mode##_init_key,                                        \
2243e1051a39Sopenharmony_ci    s390x_aes_##mode##_cipher,                                          \
2244e1051a39Sopenharmony_ci    s390x_aes_##mode##_cleanup,                                         \
2245e1051a39Sopenharmony_ci    sizeof(S390X_AES_##MODE##_CTX),                                     \
2246e1051a39Sopenharmony_ci    NULL,                                                               \
2247e1051a39Sopenharmony_ci    NULL,                                                               \
2248e1051a39Sopenharmony_ci    s390x_aes_##mode##_ctrl,                                            \
2249e1051a39Sopenharmony_ci    NULL                                                                \
2250e1051a39Sopenharmony_ci};                                                                      \
2251e1051a39Sopenharmony_cistatic const EVP_CIPHER aes_##keylen##_##mode = {                       \
2252e1051a39Sopenharmony_ci    nid##_##keylen##_##mode,blocksize,                                  \
2253e1051a39Sopenharmony_ci    (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE||EVP_CIPH_##MODE##_MODE==EVP_CIPH_SIV_MODE ? 2 : 1) * keylen / 8,        \
2254e1051a39Sopenharmony_ci    ivlen,                                                              \
2255e1051a39Sopenharmony_ci    flags | EVP_CIPH_##MODE##_MODE,                                     \
2256e1051a39Sopenharmony_ci    EVP_ORIG_GLOBAL,                                                    \
2257e1051a39Sopenharmony_ci    aes_##mode##_init_key,                                              \
2258e1051a39Sopenharmony_ci    aes_##mode##_cipher,                                                \
2259e1051a39Sopenharmony_ci    aes_##mode##_cleanup,                                               \
2260e1051a39Sopenharmony_ci    sizeof(EVP_AES_##MODE##_CTX),                                       \
2261e1051a39Sopenharmony_ci    NULL,                                                               \
2262e1051a39Sopenharmony_ci    NULL,                                                               \
2263e1051a39Sopenharmony_ci    aes_##mode##_ctrl,                                                  \
2264e1051a39Sopenharmony_ci    NULL                                                                \
2265e1051a39Sopenharmony_ci};                                                                      \
2266e1051a39Sopenharmony_ciconst EVP_CIPHER *EVP_aes_##keylen##_##mode(void)                       \
2267e1051a39Sopenharmony_ci{                                                                       \
2268e1051a39Sopenharmony_ci    return S390X_aes_##keylen##_##mode##_CAPABLE ?                      \
2269e1051a39Sopenharmony_ci           &s390x_aes_##keylen##_##mode : &aes_##keylen##_##mode;       \
2270e1051a39Sopenharmony_ci}
2271e1051a39Sopenharmony_ci
2272e1051a39Sopenharmony_ci#else
2273e1051a39Sopenharmony_ci
2274e1051a39Sopenharmony_ci# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \
2275e1051a39Sopenharmony_cistatic const EVP_CIPHER aes_##keylen##_##mode = { \
2276e1051a39Sopenharmony_ci        nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \
2277e1051a39Sopenharmony_ci        flags|EVP_CIPH_##MODE##_MODE,   \
2278e1051a39Sopenharmony_ci        EVP_ORIG_GLOBAL,                \
2279e1051a39Sopenharmony_ci        aes_init_key,                   \
2280e1051a39Sopenharmony_ci        aes_##mode##_cipher,            \
2281e1051a39Sopenharmony_ci        NULL,                           \
2282e1051a39Sopenharmony_ci        sizeof(EVP_AES_KEY),            \
2283e1051a39Sopenharmony_ci        NULL,NULL,NULL,NULL }; \
2284e1051a39Sopenharmony_ciconst EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
2285e1051a39Sopenharmony_ci{ return &aes_##keylen##_##mode; }
2286e1051a39Sopenharmony_ci
2287e1051a39Sopenharmony_ci# define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags) \
2288e1051a39Sopenharmony_cistatic const EVP_CIPHER aes_##keylen##_##mode = { \
2289e1051a39Sopenharmony_ci        nid##_##keylen##_##mode,blocksize, \
2290e1051a39Sopenharmony_ci        (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE||EVP_CIPH_##MODE##_MODE==EVP_CIPH_SIV_MODE?2:1)*keylen/8, \
2291e1051a39Sopenharmony_ci        ivlen,                          \
2292e1051a39Sopenharmony_ci        flags|EVP_CIPH_##MODE##_MODE,   \
2293e1051a39Sopenharmony_ci        EVP_ORIG_GLOBAL,                \
2294e1051a39Sopenharmony_ci        aes_##mode##_init_key,          \
2295e1051a39Sopenharmony_ci        aes_##mode##_cipher,            \
2296e1051a39Sopenharmony_ci        aes_##mode##_cleanup,           \
2297e1051a39Sopenharmony_ci        sizeof(EVP_AES_##MODE##_CTX),   \
2298e1051a39Sopenharmony_ci        NULL,NULL,aes_##mode##_ctrl,NULL }; \
2299e1051a39Sopenharmony_ciconst EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
2300e1051a39Sopenharmony_ci{ return &aes_##keylen##_##mode; }
2301e1051a39Sopenharmony_ci
2302e1051a39Sopenharmony_ci#endif
2303e1051a39Sopenharmony_ci
2304e1051a39Sopenharmony_ci#define BLOCK_CIPHER_generic_pack(nid,keylen,flags)             \
2305e1051a39Sopenharmony_ci        BLOCK_CIPHER_generic(nid,keylen,16,16,cbc,cbc,CBC,flags|EVP_CIPH_FLAG_DEFAULT_ASN1)     \
2306e1051a39Sopenharmony_ci        BLOCK_CIPHER_generic(nid,keylen,16,0,ecb,ecb,ECB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1)      \
2307e1051a39Sopenharmony_ci        BLOCK_CIPHER_generic(nid,keylen,1,16,ofb128,ofb,OFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1)   \
2308e1051a39Sopenharmony_ci        BLOCK_CIPHER_generic(nid,keylen,1,16,cfb128,cfb,CFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1)   \
2309e1051a39Sopenharmony_ci        BLOCK_CIPHER_generic(nid,keylen,1,16,cfb1,cfb1,CFB,flags)       \
2310e1051a39Sopenharmony_ci        BLOCK_CIPHER_generic(nid,keylen,1,16,cfb8,cfb8,CFB,flags)       \
2311e1051a39Sopenharmony_ci        BLOCK_CIPHER_generic(nid,keylen,1,16,ctr,ctr,CTR,flags)
2312e1051a39Sopenharmony_ci
2313e1051a39Sopenharmony_cistatic int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
2314e1051a39Sopenharmony_ci                        const unsigned char *iv, int enc)
2315e1051a39Sopenharmony_ci{
2316e1051a39Sopenharmony_ci    int ret, mode;
2317e1051a39Sopenharmony_ci    EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
2318e1051a39Sopenharmony_ci
2319e1051a39Sopenharmony_ci    mode = EVP_CIPHER_CTX_get_mode(ctx);
2320e1051a39Sopenharmony_ci    if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE)
2321e1051a39Sopenharmony_ci        && !enc) {
2322e1051a39Sopenharmony_ci#ifdef HWAES_CAPABLE
2323e1051a39Sopenharmony_ci        if (HWAES_CAPABLE) {
2324e1051a39Sopenharmony_ci            ret = HWAES_set_decrypt_key(key,
2325e1051a39Sopenharmony_ci                                        EVP_CIPHER_CTX_get_key_length(ctx) * 8,
2326e1051a39Sopenharmony_ci                                        &dat->ks.ks);
2327e1051a39Sopenharmony_ci            dat->block = (block128_f) HWAES_decrypt;
2328e1051a39Sopenharmony_ci            dat->stream.cbc = NULL;
2329e1051a39Sopenharmony_ci# ifdef HWAES_cbc_encrypt
2330e1051a39Sopenharmony_ci            if (mode == EVP_CIPH_CBC_MODE)
2331e1051a39Sopenharmony_ci                dat->stream.cbc = (cbc128_f) HWAES_cbc_encrypt;
2332e1051a39Sopenharmony_ci# endif
2333e1051a39Sopenharmony_ci        } else
2334e1051a39Sopenharmony_ci#endif
2335e1051a39Sopenharmony_ci#ifdef BSAES_CAPABLE
2336e1051a39Sopenharmony_ci        if (BSAES_CAPABLE && mode == EVP_CIPH_CBC_MODE) {
2337e1051a39Sopenharmony_ci            ret = AES_set_decrypt_key(key,
2338e1051a39Sopenharmony_ci                                      EVP_CIPHER_CTX_get_key_length(ctx) * 8,
2339e1051a39Sopenharmony_ci                                      &dat->ks.ks);
2340e1051a39Sopenharmony_ci            dat->block = (block128_f) AES_decrypt;
2341e1051a39Sopenharmony_ci            dat->stream.cbc = (cbc128_f) ossl_bsaes_cbc_encrypt;
2342e1051a39Sopenharmony_ci        } else
2343e1051a39Sopenharmony_ci#endif
2344e1051a39Sopenharmony_ci#ifdef VPAES_CAPABLE
2345e1051a39Sopenharmony_ci        if (VPAES_CAPABLE) {
2346e1051a39Sopenharmony_ci            ret = vpaes_set_decrypt_key(key,
2347e1051a39Sopenharmony_ci                                        EVP_CIPHER_CTX_get_key_length(ctx) * 8,
2348e1051a39Sopenharmony_ci                                        &dat->ks.ks);
2349e1051a39Sopenharmony_ci            dat->block = (block128_f) vpaes_decrypt;
2350e1051a39Sopenharmony_ci            dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
2351e1051a39Sopenharmony_ci                (cbc128_f) vpaes_cbc_encrypt : NULL;
2352e1051a39Sopenharmony_ci        } else
2353e1051a39Sopenharmony_ci#endif
2354e1051a39Sopenharmony_ci        {
2355e1051a39Sopenharmony_ci            ret = AES_set_decrypt_key(key,
2356e1051a39Sopenharmony_ci                                      EVP_CIPHER_CTX_get_key_length(ctx) * 8,
2357e1051a39Sopenharmony_ci                                      &dat->ks.ks);
2358e1051a39Sopenharmony_ci            dat->block = (block128_f) AES_decrypt;
2359e1051a39Sopenharmony_ci            dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
2360e1051a39Sopenharmony_ci                (cbc128_f) AES_cbc_encrypt : NULL;
2361e1051a39Sopenharmony_ci        }
2362e1051a39Sopenharmony_ci    } else
2363e1051a39Sopenharmony_ci#ifdef HWAES_CAPABLE
2364e1051a39Sopenharmony_ci    if (HWAES_CAPABLE) {
2365e1051a39Sopenharmony_ci        ret = HWAES_set_encrypt_key(key,
2366e1051a39Sopenharmony_ci                                    EVP_CIPHER_CTX_get_key_length(ctx) * 8,
2367e1051a39Sopenharmony_ci                                    &dat->ks.ks);
2368e1051a39Sopenharmony_ci        dat->block = (block128_f) HWAES_encrypt;
2369e1051a39Sopenharmony_ci        dat->stream.cbc = NULL;
2370e1051a39Sopenharmony_ci# ifdef HWAES_cbc_encrypt
2371e1051a39Sopenharmony_ci        if (mode == EVP_CIPH_CBC_MODE)
2372e1051a39Sopenharmony_ci            dat->stream.cbc = (cbc128_f) HWAES_cbc_encrypt;
2373e1051a39Sopenharmony_ci        else
2374e1051a39Sopenharmony_ci# endif
2375e1051a39Sopenharmony_ci# ifdef HWAES_ctr32_encrypt_blocks
2376e1051a39Sopenharmony_ci        if (mode == EVP_CIPH_CTR_MODE)
2377e1051a39Sopenharmony_ci            dat->stream.ctr = (ctr128_f) HWAES_ctr32_encrypt_blocks;
2378e1051a39Sopenharmony_ci        else
2379e1051a39Sopenharmony_ci# endif
2380e1051a39Sopenharmony_ci            (void)0;            /* terminate potentially open 'else' */
2381e1051a39Sopenharmony_ci    } else
2382e1051a39Sopenharmony_ci#endif
2383e1051a39Sopenharmony_ci#ifdef BSAES_CAPABLE
2384e1051a39Sopenharmony_ci    if (BSAES_CAPABLE && mode == EVP_CIPH_CTR_MODE) {
2385e1051a39Sopenharmony_ci        ret = AES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
2386e1051a39Sopenharmony_ci                                  &dat->ks.ks);
2387e1051a39Sopenharmony_ci        dat->block = (block128_f) AES_encrypt;
2388e1051a39Sopenharmony_ci        dat->stream.ctr = (ctr128_f) ossl_bsaes_ctr32_encrypt_blocks;
2389e1051a39Sopenharmony_ci    } else
2390e1051a39Sopenharmony_ci#endif
2391e1051a39Sopenharmony_ci#ifdef VPAES_CAPABLE
2392e1051a39Sopenharmony_ci    if (VPAES_CAPABLE) {
2393e1051a39Sopenharmony_ci        ret = vpaes_set_encrypt_key(key,
2394e1051a39Sopenharmony_ci                                    EVP_CIPHER_CTX_get_key_length(ctx) * 8,
2395e1051a39Sopenharmony_ci                                    &dat->ks.ks);
2396e1051a39Sopenharmony_ci        dat->block = (block128_f) vpaes_encrypt;
2397e1051a39Sopenharmony_ci        dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
2398e1051a39Sopenharmony_ci            (cbc128_f) vpaes_cbc_encrypt : NULL;
2399e1051a39Sopenharmony_ci    } else
2400e1051a39Sopenharmony_ci#endif
2401e1051a39Sopenharmony_ci    {
2402e1051a39Sopenharmony_ci        ret = AES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
2403e1051a39Sopenharmony_ci                                  &dat->ks.ks);
2404e1051a39Sopenharmony_ci        dat->block = (block128_f) AES_encrypt;
2405e1051a39Sopenharmony_ci        dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
2406e1051a39Sopenharmony_ci            (cbc128_f) AES_cbc_encrypt : NULL;
2407e1051a39Sopenharmony_ci#ifdef AES_CTR_ASM
2408e1051a39Sopenharmony_ci        if (mode == EVP_CIPH_CTR_MODE)
2409e1051a39Sopenharmony_ci            dat->stream.ctr = (ctr128_f) AES_ctr32_encrypt;
2410e1051a39Sopenharmony_ci#endif
2411e1051a39Sopenharmony_ci    }
2412e1051a39Sopenharmony_ci
2413e1051a39Sopenharmony_ci    if (ret < 0) {
2414e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EVP, EVP_R_AES_KEY_SETUP_FAILED);
2415e1051a39Sopenharmony_ci        return 0;
2416e1051a39Sopenharmony_ci    }
2417e1051a39Sopenharmony_ci
2418e1051a39Sopenharmony_ci    return 1;
2419e1051a39Sopenharmony_ci}
2420e1051a39Sopenharmony_ci
2421e1051a39Sopenharmony_cistatic int aes_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
2422e1051a39Sopenharmony_ci                          const unsigned char *in, size_t len)
2423e1051a39Sopenharmony_ci{
2424e1051a39Sopenharmony_ci    EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
2425e1051a39Sopenharmony_ci
2426e1051a39Sopenharmony_ci    if (dat->stream.cbc)
2427e1051a39Sopenharmony_ci        (*dat->stream.cbc) (in, out, len, &dat->ks, ctx->iv,
2428e1051a39Sopenharmony_ci                            EVP_CIPHER_CTX_is_encrypting(ctx));
2429e1051a39Sopenharmony_ci    else if (EVP_CIPHER_CTX_is_encrypting(ctx))
2430e1051a39Sopenharmony_ci        CRYPTO_cbc128_encrypt(in, out, len, &dat->ks, ctx->iv,
2431e1051a39Sopenharmony_ci                              dat->block);
2432e1051a39Sopenharmony_ci    else
2433e1051a39Sopenharmony_ci        CRYPTO_cbc128_decrypt(in, out, len, &dat->ks,
2434e1051a39Sopenharmony_ci                              ctx->iv, dat->block);
2435e1051a39Sopenharmony_ci
2436e1051a39Sopenharmony_ci    return 1;
2437e1051a39Sopenharmony_ci}
2438e1051a39Sopenharmony_ci
2439e1051a39Sopenharmony_cistatic int aes_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
2440e1051a39Sopenharmony_ci                          const unsigned char *in, size_t len)
2441e1051a39Sopenharmony_ci{
2442e1051a39Sopenharmony_ci    size_t bl = EVP_CIPHER_CTX_get_block_size(ctx);
2443e1051a39Sopenharmony_ci    size_t i;
2444e1051a39Sopenharmony_ci    EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
2445e1051a39Sopenharmony_ci
2446e1051a39Sopenharmony_ci    if (len < bl)
2447e1051a39Sopenharmony_ci        return 1;
2448e1051a39Sopenharmony_ci
2449e1051a39Sopenharmony_ci    for (i = 0, len -= bl; i <= len; i += bl)
2450e1051a39Sopenharmony_ci        (*dat->block) (in + i, out + i, &dat->ks);
2451e1051a39Sopenharmony_ci
2452e1051a39Sopenharmony_ci    return 1;
2453e1051a39Sopenharmony_ci}
2454e1051a39Sopenharmony_ci
2455e1051a39Sopenharmony_cistatic int aes_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
2456e1051a39Sopenharmony_ci                          const unsigned char *in, size_t len)
2457e1051a39Sopenharmony_ci{
2458e1051a39Sopenharmony_ci    EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
2459e1051a39Sopenharmony_ci
2460e1051a39Sopenharmony_ci    int num = EVP_CIPHER_CTX_get_num(ctx);
2461e1051a39Sopenharmony_ci    CRYPTO_ofb128_encrypt(in, out, len, &dat->ks,
2462e1051a39Sopenharmony_ci                          ctx->iv, &num, dat->block);
2463e1051a39Sopenharmony_ci    EVP_CIPHER_CTX_set_num(ctx, num);
2464e1051a39Sopenharmony_ci    return 1;
2465e1051a39Sopenharmony_ci}
2466e1051a39Sopenharmony_ci
2467e1051a39Sopenharmony_cistatic int aes_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
2468e1051a39Sopenharmony_ci                          const unsigned char *in, size_t len)
2469e1051a39Sopenharmony_ci{
2470e1051a39Sopenharmony_ci    EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
2471e1051a39Sopenharmony_ci
2472e1051a39Sopenharmony_ci    int num = EVP_CIPHER_CTX_get_num(ctx);
2473e1051a39Sopenharmony_ci    CRYPTO_cfb128_encrypt(in, out, len, &dat->ks,
2474e1051a39Sopenharmony_ci                          ctx->iv, &num,
2475e1051a39Sopenharmony_ci                          EVP_CIPHER_CTX_is_encrypting(ctx), dat->block);
2476e1051a39Sopenharmony_ci    EVP_CIPHER_CTX_set_num(ctx, num);
2477e1051a39Sopenharmony_ci    return 1;
2478e1051a39Sopenharmony_ci}
2479e1051a39Sopenharmony_ci
2480e1051a39Sopenharmony_cistatic int aes_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
2481e1051a39Sopenharmony_ci                           const unsigned char *in, size_t len)
2482e1051a39Sopenharmony_ci{
2483e1051a39Sopenharmony_ci    EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
2484e1051a39Sopenharmony_ci
2485e1051a39Sopenharmony_ci    int num = EVP_CIPHER_CTX_get_num(ctx);
2486e1051a39Sopenharmony_ci    CRYPTO_cfb128_8_encrypt(in, out, len, &dat->ks,
2487e1051a39Sopenharmony_ci                            ctx->iv, &num,
2488e1051a39Sopenharmony_ci                            EVP_CIPHER_CTX_is_encrypting(ctx), dat->block);
2489e1051a39Sopenharmony_ci    EVP_CIPHER_CTX_set_num(ctx, num);
2490e1051a39Sopenharmony_ci    return 1;
2491e1051a39Sopenharmony_ci}
2492e1051a39Sopenharmony_ci
2493e1051a39Sopenharmony_cistatic int aes_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
2494e1051a39Sopenharmony_ci                           const unsigned char *in, size_t len)
2495e1051a39Sopenharmony_ci{
2496e1051a39Sopenharmony_ci    EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
2497e1051a39Sopenharmony_ci
2498e1051a39Sopenharmony_ci    if (EVP_CIPHER_CTX_test_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS)) {
2499e1051a39Sopenharmony_ci        int num = EVP_CIPHER_CTX_get_num(ctx);
2500e1051a39Sopenharmony_ci        CRYPTO_cfb128_1_encrypt(in, out, len, &dat->ks,
2501e1051a39Sopenharmony_ci                                ctx->iv, &num,
2502e1051a39Sopenharmony_ci                                EVP_CIPHER_CTX_is_encrypting(ctx), dat->block);
2503e1051a39Sopenharmony_ci        EVP_CIPHER_CTX_set_num(ctx, num);
2504e1051a39Sopenharmony_ci        return 1;
2505e1051a39Sopenharmony_ci    }
2506e1051a39Sopenharmony_ci
2507e1051a39Sopenharmony_ci    while (len >= MAXBITCHUNK) {
2508e1051a39Sopenharmony_ci        int num = EVP_CIPHER_CTX_get_num(ctx);
2509e1051a39Sopenharmony_ci        CRYPTO_cfb128_1_encrypt(in, out, MAXBITCHUNK * 8, &dat->ks,
2510e1051a39Sopenharmony_ci                                ctx->iv, &num,
2511e1051a39Sopenharmony_ci                                EVP_CIPHER_CTX_is_encrypting(ctx), dat->block);
2512e1051a39Sopenharmony_ci        EVP_CIPHER_CTX_set_num(ctx, num);
2513e1051a39Sopenharmony_ci        len -= MAXBITCHUNK;
2514e1051a39Sopenharmony_ci        out += MAXBITCHUNK;
2515e1051a39Sopenharmony_ci        in  += MAXBITCHUNK;
2516e1051a39Sopenharmony_ci    }
2517e1051a39Sopenharmony_ci    if (len) {
2518e1051a39Sopenharmony_ci        int num = EVP_CIPHER_CTX_get_num(ctx);
2519e1051a39Sopenharmony_ci        CRYPTO_cfb128_1_encrypt(in, out, len * 8, &dat->ks,
2520e1051a39Sopenharmony_ci                                ctx->iv, &num,
2521e1051a39Sopenharmony_ci                                EVP_CIPHER_CTX_is_encrypting(ctx), dat->block);
2522e1051a39Sopenharmony_ci        EVP_CIPHER_CTX_set_num(ctx, num);
2523e1051a39Sopenharmony_ci    }
2524e1051a39Sopenharmony_ci
2525e1051a39Sopenharmony_ci    return 1;
2526e1051a39Sopenharmony_ci}
2527e1051a39Sopenharmony_ci
2528e1051a39Sopenharmony_cistatic int aes_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
2529e1051a39Sopenharmony_ci                          const unsigned char *in, size_t len)
2530e1051a39Sopenharmony_ci{
2531e1051a39Sopenharmony_ci    int n = EVP_CIPHER_CTX_get_num(ctx);
2532e1051a39Sopenharmony_ci    unsigned int num;
2533e1051a39Sopenharmony_ci    EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
2534e1051a39Sopenharmony_ci
2535e1051a39Sopenharmony_ci    if (n < 0)
2536e1051a39Sopenharmony_ci        return 0;
2537e1051a39Sopenharmony_ci    num = (unsigned int)n;
2538e1051a39Sopenharmony_ci
2539e1051a39Sopenharmony_ci    if (dat->stream.ctr)
2540e1051a39Sopenharmony_ci        CRYPTO_ctr128_encrypt_ctr32(in, out, len, &dat->ks,
2541e1051a39Sopenharmony_ci                                    ctx->iv,
2542e1051a39Sopenharmony_ci                                    EVP_CIPHER_CTX_buf_noconst(ctx),
2543e1051a39Sopenharmony_ci                                    &num, dat->stream.ctr);
2544e1051a39Sopenharmony_ci    else
2545e1051a39Sopenharmony_ci        CRYPTO_ctr128_encrypt(in, out, len, &dat->ks,
2546e1051a39Sopenharmony_ci                              ctx->iv,
2547e1051a39Sopenharmony_ci                              EVP_CIPHER_CTX_buf_noconst(ctx), &num,
2548e1051a39Sopenharmony_ci                              dat->block);
2549e1051a39Sopenharmony_ci    EVP_CIPHER_CTX_set_num(ctx, num);
2550e1051a39Sopenharmony_ci    return 1;
2551e1051a39Sopenharmony_ci}
2552e1051a39Sopenharmony_ci
2553e1051a39Sopenharmony_ciBLOCK_CIPHER_generic_pack(NID_aes, 128, 0)
2554e1051a39Sopenharmony_ci    BLOCK_CIPHER_generic_pack(NID_aes, 192, 0)
2555e1051a39Sopenharmony_ci    BLOCK_CIPHER_generic_pack(NID_aes, 256, 0)
2556e1051a39Sopenharmony_ci
2557e1051a39Sopenharmony_cistatic int aes_gcm_cleanup(EVP_CIPHER_CTX *c)
2558e1051a39Sopenharmony_ci{
2559e1051a39Sopenharmony_ci    EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,c);
2560e1051a39Sopenharmony_ci    if (gctx == NULL)
2561e1051a39Sopenharmony_ci        return 0;
2562e1051a39Sopenharmony_ci    OPENSSL_cleanse(&gctx->gcm, sizeof(gctx->gcm));
2563e1051a39Sopenharmony_ci    if (gctx->iv != c->iv)
2564e1051a39Sopenharmony_ci        OPENSSL_free(gctx->iv);
2565e1051a39Sopenharmony_ci    return 1;
2566e1051a39Sopenharmony_ci}
2567e1051a39Sopenharmony_ci
2568e1051a39Sopenharmony_cistatic int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
2569e1051a39Sopenharmony_ci{
2570e1051a39Sopenharmony_ci    EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,c);
2571e1051a39Sopenharmony_ci    switch (type) {
2572e1051a39Sopenharmony_ci    case EVP_CTRL_INIT:
2573e1051a39Sopenharmony_ci        gctx->key_set = 0;
2574e1051a39Sopenharmony_ci        gctx->iv_set = 0;
2575e1051a39Sopenharmony_ci        gctx->ivlen = EVP_CIPHER_get_iv_length(c->cipher);
2576e1051a39Sopenharmony_ci        gctx->iv = c->iv;
2577e1051a39Sopenharmony_ci        gctx->taglen = -1;
2578e1051a39Sopenharmony_ci        gctx->iv_gen = 0;
2579e1051a39Sopenharmony_ci        gctx->tls_aad_len = -1;
2580e1051a39Sopenharmony_ci        return 1;
2581e1051a39Sopenharmony_ci
2582e1051a39Sopenharmony_ci    case EVP_CTRL_GET_IVLEN:
2583e1051a39Sopenharmony_ci        *(int *)ptr = gctx->ivlen;
2584e1051a39Sopenharmony_ci        return 1;
2585e1051a39Sopenharmony_ci
2586e1051a39Sopenharmony_ci    case EVP_CTRL_AEAD_SET_IVLEN:
2587e1051a39Sopenharmony_ci        if (arg <= 0)
2588e1051a39Sopenharmony_ci            return 0;
2589e1051a39Sopenharmony_ci        /* Allocate memory for IV if needed */
2590e1051a39Sopenharmony_ci        if ((arg > EVP_MAX_IV_LENGTH) && (arg > gctx->ivlen)) {
2591e1051a39Sopenharmony_ci            if (gctx->iv != c->iv)
2592e1051a39Sopenharmony_ci                OPENSSL_free(gctx->iv);
2593e1051a39Sopenharmony_ci            if ((gctx->iv = OPENSSL_malloc(arg)) == NULL) {
2594e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
2595e1051a39Sopenharmony_ci                return 0;
2596e1051a39Sopenharmony_ci            }
2597e1051a39Sopenharmony_ci        }
2598e1051a39Sopenharmony_ci        gctx->ivlen = arg;
2599e1051a39Sopenharmony_ci        return 1;
2600e1051a39Sopenharmony_ci
2601e1051a39Sopenharmony_ci    case EVP_CTRL_AEAD_SET_TAG:
2602e1051a39Sopenharmony_ci        if (arg <= 0 || arg > 16 || c->encrypt)
2603e1051a39Sopenharmony_ci            return 0;
2604e1051a39Sopenharmony_ci        memcpy(c->buf, ptr, arg);
2605e1051a39Sopenharmony_ci        gctx->taglen = arg;
2606e1051a39Sopenharmony_ci        return 1;
2607e1051a39Sopenharmony_ci
2608e1051a39Sopenharmony_ci    case EVP_CTRL_AEAD_GET_TAG:
2609e1051a39Sopenharmony_ci        if (arg <= 0 || arg > 16 || !c->encrypt
2610e1051a39Sopenharmony_ci            || gctx->taglen < 0)
2611e1051a39Sopenharmony_ci            return 0;
2612e1051a39Sopenharmony_ci        memcpy(ptr, c->buf, arg);
2613e1051a39Sopenharmony_ci        return 1;
2614e1051a39Sopenharmony_ci
2615e1051a39Sopenharmony_ci    case EVP_CTRL_GCM_SET_IV_FIXED:
2616e1051a39Sopenharmony_ci        /* Special case: -1 length restores whole IV */
2617e1051a39Sopenharmony_ci        if (arg == -1) {
2618e1051a39Sopenharmony_ci            memcpy(gctx->iv, ptr, gctx->ivlen);
2619e1051a39Sopenharmony_ci            gctx->iv_gen = 1;
2620e1051a39Sopenharmony_ci            return 1;
2621e1051a39Sopenharmony_ci        }
2622e1051a39Sopenharmony_ci        /*
2623e1051a39Sopenharmony_ci         * Fixed field must be at least 4 bytes and invocation field at least
2624e1051a39Sopenharmony_ci         * 8.
2625e1051a39Sopenharmony_ci         */
2626e1051a39Sopenharmony_ci        if ((arg < 4) || (gctx->ivlen - arg) < 8)
2627e1051a39Sopenharmony_ci            return 0;
2628e1051a39Sopenharmony_ci        if (arg)
2629e1051a39Sopenharmony_ci            memcpy(gctx->iv, ptr, arg);
2630e1051a39Sopenharmony_ci        if (c->encrypt && RAND_bytes(gctx->iv + arg, gctx->ivlen - arg) <= 0)
2631e1051a39Sopenharmony_ci            return 0;
2632e1051a39Sopenharmony_ci        gctx->iv_gen = 1;
2633e1051a39Sopenharmony_ci        return 1;
2634e1051a39Sopenharmony_ci
2635e1051a39Sopenharmony_ci    case EVP_CTRL_GCM_IV_GEN:
2636e1051a39Sopenharmony_ci        if (gctx->iv_gen == 0 || gctx->key_set == 0)
2637e1051a39Sopenharmony_ci            return 0;
2638e1051a39Sopenharmony_ci        CRYPTO_gcm128_setiv(&gctx->gcm, gctx->iv, gctx->ivlen);
2639e1051a39Sopenharmony_ci        if (arg <= 0 || arg > gctx->ivlen)
2640e1051a39Sopenharmony_ci            arg = gctx->ivlen;
2641e1051a39Sopenharmony_ci        memcpy(ptr, gctx->iv + gctx->ivlen - arg, arg);
2642e1051a39Sopenharmony_ci        /*
2643e1051a39Sopenharmony_ci         * Invocation field will be at least 8 bytes in size and so no need
2644e1051a39Sopenharmony_ci         * to check wrap around or increment more than last 8 bytes.
2645e1051a39Sopenharmony_ci         */
2646e1051a39Sopenharmony_ci        ctr64_inc(gctx->iv + gctx->ivlen - 8);
2647e1051a39Sopenharmony_ci        gctx->iv_set = 1;
2648e1051a39Sopenharmony_ci        return 1;
2649e1051a39Sopenharmony_ci
2650e1051a39Sopenharmony_ci    case EVP_CTRL_GCM_SET_IV_INV:
2651e1051a39Sopenharmony_ci        if (gctx->iv_gen == 0 || gctx->key_set == 0 || c->encrypt)
2652e1051a39Sopenharmony_ci            return 0;
2653e1051a39Sopenharmony_ci        memcpy(gctx->iv + gctx->ivlen - arg, ptr, arg);
2654e1051a39Sopenharmony_ci        CRYPTO_gcm128_setiv(&gctx->gcm, gctx->iv, gctx->ivlen);
2655e1051a39Sopenharmony_ci        gctx->iv_set = 1;
2656e1051a39Sopenharmony_ci        return 1;
2657e1051a39Sopenharmony_ci
2658e1051a39Sopenharmony_ci    case EVP_CTRL_AEAD_TLS1_AAD:
2659e1051a39Sopenharmony_ci        /* Save the AAD for later use */
2660e1051a39Sopenharmony_ci        if (arg != EVP_AEAD_TLS1_AAD_LEN)
2661e1051a39Sopenharmony_ci            return 0;
2662e1051a39Sopenharmony_ci        memcpy(c->buf, ptr, arg);
2663e1051a39Sopenharmony_ci        gctx->tls_aad_len = arg;
2664e1051a39Sopenharmony_ci        gctx->tls_enc_records = 0;
2665e1051a39Sopenharmony_ci        {
2666e1051a39Sopenharmony_ci            unsigned int len = c->buf[arg - 2] << 8 | c->buf[arg - 1];
2667e1051a39Sopenharmony_ci            /* Correct length for explicit IV */
2668e1051a39Sopenharmony_ci            if (len < EVP_GCM_TLS_EXPLICIT_IV_LEN)
2669e1051a39Sopenharmony_ci                return 0;
2670e1051a39Sopenharmony_ci            len -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
2671e1051a39Sopenharmony_ci            /* If decrypting correct for tag too */
2672e1051a39Sopenharmony_ci            if (!c->encrypt) {
2673e1051a39Sopenharmony_ci                if (len < EVP_GCM_TLS_TAG_LEN)
2674e1051a39Sopenharmony_ci                    return 0;
2675e1051a39Sopenharmony_ci                len -= EVP_GCM_TLS_TAG_LEN;
2676e1051a39Sopenharmony_ci            }
2677e1051a39Sopenharmony_ci            c->buf[arg - 2] = len >> 8;
2678e1051a39Sopenharmony_ci            c->buf[arg - 1] = len & 0xff;
2679e1051a39Sopenharmony_ci        }
2680e1051a39Sopenharmony_ci        /* Extra padding: tag appended to record */
2681e1051a39Sopenharmony_ci        return EVP_GCM_TLS_TAG_LEN;
2682e1051a39Sopenharmony_ci
2683e1051a39Sopenharmony_ci    case EVP_CTRL_COPY:
2684e1051a39Sopenharmony_ci        {
2685e1051a39Sopenharmony_ci            EVP_CIPHER_CTX *out = ptr;
2686e1051a39Sopenharmony_ci            EVP_AES_GCM_CTX *gctx_out = EVP_C_DATA(EVP_AES_GCM_CTX,out);
2687e1051a39Sopenharmony_ci            if (gctx->gcm.key) {
2688e1051a39Sopenharmony_ci                if (gctx->gcm.key != &gctx->ks)
2689e1051a39Sopenharmony_ci                    return 0;
2690e1051a39Sopenharmony_ci                gctx_out->gcm.key = &gctx_out->ks;
2691e1051a39Sopenharmony_ci            }
2692e1051a39Sopenharmony_ci            if (gctx->iv == c->iv)
2693e1051a39Sopenharmony_ci                gctx_out->iv = out->iv;
2694e1051a39Sopenharmony_ci            else {
2695e1051a39Sopenharmony_ci                if ((gctx_out->iv = OPENSSL_malloc(gctx->ivlen)) == NULL) {
2696e1051a39Sopenharmony_ci                    ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
2697e1051a39Sopenharmony_ci                    return 0;
2698e1051a39Sopenharmony_ci                }
2699e1051a39Sopenharmony_ci                memcpy(gctx_out->iv, gctx->iv, gctx->ivlen);
2700e1051a39Sopenharmony_ci            }
2701e1051a39Sopenharmony_ci            return 1;
2702e1051a39Sopenharmony_ci        }
2703e1051a39Sopenharmony_ci
2704e1051a39Sopenharmony_ci    default:
2705e1051a39Sopenharmony_ci        return -1;
2706e1051a39Sopenharmony_ci
2707e1051a39Sopenharmony_ci    }
2708e1051a39Sopenharmony_ci}
2709e1051a39Sopenharmony_ci
2710e1051a39Sopenharmony_cistatic int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
2711e1051a39Sopenharmony_ci                            const unsigned char *iv, int enc)
2712e1051a39Sopenharmony_ci{
2713e1051a39Sopenharmony_ci    EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx);
2714e1051a39Sopenharmony_ci    if (!iv && !key)
2715e1051a39Sopenharmony_ci        return 1;
2716e1051a39Sopenharmony_ci    if (key) {
2717e1051a39Sopenharmony_ci        do {
2718e1051a39Sopenharmony_ci#ifdef HWAES_CAPABLE
2719e1051a39Sopenharmony_ci            if (HWAES_CAPABLE) {
2720e1051a39Sopenharmony_ci                HWAES_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks);
2721e1051a39Sopenharmony_ci                CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks,
2722e1051a39Sopenharmony_ci                                   (block128_f) HWAES_encrypt);
2723e1051a39Sopenharmony_ci# ifdef HWAES_ctr32_encrypt_blocks
2724e1051a39Sopenharmony_ci                gctx->ctr = (ctr128_f) HWAES_ctr32_encrypt_blocks;
2725e1051a39Sopenharmony_ci# else
2726e1051a39Sopenharmony_ci                gctx->ctr = NULL;
2727e1051a39Sopenharmony_ci# endif
2728e1051a39Sopenharmony_ci                break;
2729e1051a39Sopenharmony_ci            } else
2730e1051a39Sopenharmony_ci#endif
2731e1051a39Sopenharmony_ci#ifdef BSAES_CAPABLE
2732e1051a39Sopenharmony_ci            if (BSAES_CAPABLE) {
2733e1051a39Sopenharmony_ci                AES_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks);
2734e1051a39Sopenharmony_ci                CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks,
2735e1051a39Sopenharmony_ci                                   (block128_f) AES_encrypt);
2736e1051a39Sopenharmony_ci                gctx->ctr = (ctr128_f) ossl_bsaes_ctr32_encrypt_blocks;
2737e1051a39Sopenharmony_ci                break;
2738e1051a39Sopenharmony_ci            } else
2739e1051a39Sopenharmony_ci#endif
2740e1051a39Sopenharmony_ci#ifdef VPAES_CAPABLE
2741e1051a39Sopenharmony_ci            if (VPAES_CAPABLE) {
2742e1051a39Sopenharmony_ci                vpaes_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks);
2743e1051a39Sopenharmony_ci                CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks,
2744e1051a39Sopenharmony_ci                                   (block128_f) vpaes_encrypt);
2745e1051a39Sopenharmony_ci                gctx->ctr = NULL;
2746e1051a39Sopenharmony_ci                break;
2747e1051a39Sopenharmony_ci            } else
2748e1051a39Sopenharmony_ci#endif
2749e1051a39Sopenharmony_ci                (void)0;        /* terminate potentially open 'else' */
2750e1051a39Sopenharmony_ci
2751e1051a39Sopenharmony_ci            AES_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks);
2752e1051a39Sopenharmony_ci            CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks,
2753e1051a39Sopenharmony_ci                               (block128_f) AES_encrypt);
2754e1051a39Sopenharmony_ci#ifdef AES_CTR_ASM
2755e1051a39Sopenharmony_ci            gctx->ctr = (ctr128_f) AES_ctr32_encrypt;
2756e1051a39Sopenharmony_ci#else
2757e1051a39Sopenharmony_ci            gctx->ctr = NULL;
2758e1051a39Sopenharmony_ci#endif
2759e1051a39Sopenharmony_ci        } while (0);
2760e1051a39Sopenharmony_ci
2761e1051a39Sopenharmony_ci        /*
2762e1051a39Sopenharmony_ci         * If we have an iv can set it directly, otherwise use saved IV.
2763e1051a39Sopenharmony_ci         */
2764e1051a39Sopenharmony_ci        if (iv == NULL && gctx->iv_set)
2765e1051a39Sopenharmony_ci            iv = gctx->iv;
2766e1051a39Sopenharmony_ci        if (iv) {
2767e1051a39Sopenharmony_ci            CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen);
2768e1051a39Sopenharmony_ci            gctx->iv_set = 1;
2769e1051a39Sopenharmony_ci        }
2770e1051a39Sopenharmony_ci        gctx->key_set = 1;
2771e1051a39Sopenharmony_ci    } else {
2772e1051a39Sopenharmony_ci        /* If key set use IV, otherwise copy */
2773e1051a39Sopenharmony_ci        if (gctx->key_set)
2774e1051a39Sopenharmony_ci            CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen);
2775e1051a39Sopenharmony_ci        else
2776e1051a39Sopenharmony_ci            memcpy(gctx->iv, iv, gctx->ivlen);
2777e1051a39Sopenharmony_ci        gctx->iv_set = 1;
2778e1051a39Sopenharmony_ci        gctx->iv_gen = 0;
2779e1051a39Sopenharmony_ci    }
2780e1051a39Sopenharmony_ci    return 1;
2781e1051a39Sopenharmony_ci}
2782e1051a39Sopenharmony_ci
2783e1051a39Sopenharmony_ci/*
2784e1051a39Sopenharmony_ci * Handle TLS GCM packet format. This consists of the last portion of the IV
2785e1051a39Sopenharmony_ci * followed by the payload and finally the tag. On encrypt generate IV,
2786e1051a39Sopenharmony_ci * encrypt payload and write the tag. On verify retrieve IV, decrypt payload
2787e1051a39Sopenharmony_ci * and verify tag.
2788e1051a39Sopenharmony_ci */
2789e1051a39Sopenharmony_ci
2790e1051a39Sopenharmony_cistatic int aes_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
2791e1051a39Sopenharmony_ci                              const unsigned char *in, size_t len)
2792e1051a39Sopenharmony_ci{
2793e1051a39Sopenharmony_ci    EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx);
2794e1051a39Sopenharmony_ci    int rv = -1;
2795e1051a39Sopenharmony_ci    /* Encrypt/decrypt must be performed in place */
2796e1051a39Sopenharmony_ci    if (out != in
2797e1051a39Sopenharmony_ci        || len < (EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN))
2798e1051a39Sopenharmony_ci        return -1;
2799e1051a39Sopenharmony_ci
2800e1051a39Sopenharmony_ci    /*
2801e1051a39Sopenharmony_ci     * Check for too many keys as per FIPS 140-2 IG A.5 "Key/IV Pair Uniqueness
2802e1051a39Sopenharmony_ci     * Requirements from SP 800-38D".  The requirements is for one party to the
2803e1051a39Sopenharmony_ci     * communication to fail after 2^64 - 1 keys.  We do this on the encrypting
2804e1051a39Sopenharmony_ci     * side only.
2805e1051a39Sopenharmony_ci     */
2806e1051a39Sopenharmony_ci    if (ctx->encrypt && ++gctx->tls_enc_records == 0) {
2807e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EVP, EVP_R_TOO_MANY_RECORDS);
2808e1051a39Sopenharmony_ci        goto err;
2809e1051a39Sopenharmony_ci    }
2810e1051a39Sopenharmony_ci
2811e1051a39Sopenharmony_ci    /*
2812e1051a39Sopenharmony_ci     * Set IV from start of buffer or generate IV and write to start of
2813e1051a39Sopenharmony_ci     * buffer.
2814e1051a39Sopenharmony_ci     */
2815e1051a39Sopenharmony_ci    if (EVP_CIPHER_CTX_ctrl(ctx, ctx->encrypt ? EVP_CTRL_GCM_IV_GEN
2816e1051a39Sopenharmony_ci                                              : EVP_CTRL_GCM_SET_IV_INV,
2817e1051a39Sopenharmony_ci                            EVP_GCM_TLS_EXPLICIT_IV_LEN, out) <= 0)
2818e1051a39Sopenharmony_ci        goto err;
2819e1051a39Sopenharmony_ci    /* Use saved AAD */
2820e1051a39Sopenharmony_ci    if (CRYPTO_gcm128_aad(&gctx->gcm, ctx->buf, gctx->tls_aad_len))
2821e1051a39Sopenharmony_ci        goto err;
2822e1051a39Sopenharmony_ci    /* Fix buffer and length to point to payload */
2823e1051a39Sopenharmony_ci    in += EVP_GCM_TLS_EXPLICIT_IV_LEN;
2824e1051a39Sopenharmony_ci    out += EVP_GCM_TLS_EXPLICIT_IV_LEN;
2825e1051a39Sopenharmony_ci    len -= EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
2826e1051a39Sopenharmony_ci    if (ctx->encrypt) {
2827e1051a39Sopenharmony_ci        /* Encrypt payload */
2828e1051a39Sopenharmony_ci        if (gctx->ctr) {
2829e1051a39Sopenharmony_ci            size_t bulk = 0;
2830e1051a39Sopenharmony_ci#if defined(AES_GCM_ASM)
2831e1051a39Sopenharmony_ci            if (len >= 32 && AES_GCM_ASM(gctx)) {
2832e1051a39Sopenharmony_ci                if (CRYPTO_gcm128_encrypt(&gctx->gcm, NULL, NULL, 0))
2833e1051a39Sopenharmony_ci                    return -1;
2834e1051a39Sopenharmony_ci
2835e1051a39Sopenharmony_ci                bulk = AES_gcm_encrypt(in, out, len,
2836e1051a39Sopenharmony_ci                                       gctx->gcm.key,
2837e1051a39Sopenharmony_ci                                       gctx->gcm.Yi.c, gctx->gcm.Xi.u);
2838e1051a39Sopenharmony_ci                gctx->gcm.len.u[1] += bulk;
2839e1051a39Sopenharmony_ci            }
2840e1051a39Sopenharmony_ci#endif
2841e1051a39Sopenharmony_ci            if (CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm,
2842e1051a39Sopenharmony_ci                                            in + bulk,
2843e1051a39Sopenharmony_ci                                            out + bulk,
2844e1051a39Sopenharmony_ci                                            len - bulk, gctx->ctr))
2845e1051a39Sopenharmony_ci                goto err;
2846e1051a39Sopenharmony_ci        } else {
2847e1051a39Sopenharmony_ci            size_t bulk = 0;
2848e1051a39Sopenharmony_ci#if defined(AES_GCM_ASM2)
2849e1051a39Sopenharmony_ci            if (len >= 32 && AES_GCM_ASM2(gctx)) {
2850e1051a39Sopenharmony_ci                if (CRYPTO_gcm128_encrypt(&gctx->gcm, NULL, NULL, 0))
2851e1051a39Sopenharmony_ci                    return -1;
2852e1051a39Sopenharmony_ci
2853e1051a39Sopenharmony_ci                bulk = AES_gcm_encrypt(in, out, len,
2854e1051a39Sopenharmony_ci                                       gctx->gcm.key,
2855e1051a39Sopenharmony_ci                                       gctx->gcm.Yi.c, gctx->gcm.Xi.u);
2856e1051a39Sopenharmony_ci                gctx->gcm.len.u[1] += bulk;
2857e1051a39Sopenharmony_ci            }
2858e1051a39Sopenharmony_ci#endif
2859e1051a39Sopenharmony_ci            if (CRYPTO_gcm128_encrypt(&gctx->gcm,
2860e1051a39Sopenharmony_ci                                      in + bulk, out + bulk, len - bulk))
2861e1051a39Sopenharmony_ci                goto err;
2862e1051a39Sopenharmony_ci        }
2863e1051a39Sopenharmony_ci        out += len;
2864e1051a39Sopenharmony_ci        /* Finally write tag */
2865e1051a39Sopenharmony_ci        CRYPTO_gcm128_tag(&gctx->gcm, out, EVP_GCM_TLS_TAG_LEN);
2866e1051a39Sopenharmony_ci        rv = len + EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
2867e1051a39Sopenharmony_ci    } else {
2868e1051a39Sopenharmony_ci        /* Decrypt */
2869e1051a39Sopenharmony_ci        if (gctx->ctr) {
2870e1051a39Sopenharmony_ci            size_t bulk = 0;
2871e1051a39Sopenharmony_ci#if defined(AES_GCM_ASM)
2872e1051a39Sopenharmony_ci            if (len >= 16 && AES_GCM_ASM(gctx)) {
2873e1051a39Sopenharmony_ci                if (CRYPTO_gcm128_decrypt(&gctx->gcm, NULL, NULL, 0))
2874e1051a39Sopenharmony_ci                    return -1;
2875e1051a39Sopenharmony_ci
2876e1051a39Sopenharmony_ci                bulk = AES_gcm_decrypt(in, out, len,
2877e1051a39Sopenharmony_ci                                       gctx->gcm.key,
2878e1051a39Sopenharmony_ci                                       gctx->gcm.Yi.c, gctx->gcm.Xi.u);
2879e1051a39Sopenharmony_ci                gctx->gcm.len.u[1] += bulk;
2880e1051a39Sopenharmony_ci            }
2881e1051a39Sopenharmony_ci#endif
2882e1051a39Sopenharmony_ci            if (CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm,
2883e1051a39Sopenharmony_ci                                            in + bulk,
2884e1051a39Sopenharmony_ci                                            out + bulk,
2885e1051a39Sopenharmony_ci                                            len - bulk, gctx->ctr))
2886e1051a39Sopenharmony_ci                goto err;
2887e1051a39Sopenharmony_ci        } else {
2888e1051a39Sopenharmony_ci            size_t bulk = 0;
2889e1051a39Sopenharmony_ci#if defined(AES_GCM_ASM2)
2890e1051a39Sopenharmony_ci            if (len >= 16 && AES_GCM_ASM2(gctx)) {
2891e1051a39Sopenharmony_ci                if (CRYPTO_gcm128_decrypt(&gctx->gcm, NULL, NULL, 0))
2892e1051a39Sopenharmony_ci                    return -1;
2893e1051a39Sopenharmony_ci
2894e1051a39Sopenharmony_ci                bulk = AES_gcm_decrypt(in, out, len,
2895e1051a39Sopenharmony_ci                                       gctx->gcm.key,
2896e1051a39Sopenharmony_ci                                       gctx->gcm.Yi.c, gctx->gcm.Xi.u);
2897e1051a39Sopenharmony_ci                gctx->gcm.len.u[1] += bulk;
2898e1051a39Sopenharmony_ci            }
2899e1051a39Sopenharmony_ci#endif
2900e1051a39Sopenharmony_ci            if (CRYPTO_gcm128_decrypt(&gctx->gcm,
2901e1051a39Sopenharmony_ci                                      in + bulk, out + bulk, len - bulk))
2902e1051a39Sopenharmony_ci                goto err;
2903e1051a39Sopenharmony_ci        }
2904e1051a39Sopenharmony_ci        /* Retrieve tag */
2905e1051a39Sopenharmony_ci        CRYPTO_gcm128_tag(&gctx->gcm, ctx->buf, EVP_GCM_TLS_TAG_LEN);
2906e1051a39Sopenharmony_ci        /* If tag mismatch wipe buffer */
2907e1051a39Sopenharmony_ci        if (CRYPTO_memcmp(ctx->buf, in + len, EVP_GCM_TLS_TAG_LEN)) {
2908e1051a39Sopenharmony_ci            OPENSSL_cleanse(out, len);
2909e1051a39Sopenharmony_ci            goto err;
2910e1051a39Sopenharmony_ci        }
2911e1051a39Sopenharmony_ci        rv = len;
2912e1051a39Sopenharmony_ci    }
2913e1051a39Sopenharmony_ci
2914e1051a39Sopenharmony_ci err:
2915e1051a39Sopenharmony_ci    gctx->iv_set = 0;
2916e1051a39Sopenharmony_ci    gctx->tls_aad_len = -1;
2917e1051a39Sopenharmony_ci    return rv;
2918e1051a39Sopenharmony_ci}
2919e1051a39Sopenharmony_ci
2920e1051a39Sopenharmony_ci#ifdef FIPS_MODULE
2921e1051a39Sopenharmony_ci/*
2922e1051a39Sopenharmony_ci * See SP800-38D (GCM) Section 8 "Uniqueness requirement on IVS and keys"
2923e1051a39Sopenharmony_ci *
2924e1051a39Sopenharmony_ci * See also 8.2.2 RBG-based construction.
2925e1051a39Sopenharmony_ci * Random construction consists of a free field (which can be NULL) and a
2926e1051a39Sopenharmony_ci * random field which will use a DRBG that can return at least 96 bits of
2927e1051a39Sopenharmony_ci * entropy strength. (The DRBG must be seeded by the FIPS module).
2928e1051a39Sopenharmony_ci */
2929e1051a39Sopenharmony_cistatic int aes_gcm_iv_generate(EVP_AES_GCM_CTX *gctx, int offset)
2930e1051a39Sopenharmony_ci{
2931e1051a39Sopenharmony_ci    int sz = gctx->ivlen - offset;
2932e1051a39Sopenharmony_ci
2933e1051a39Sopenharmony_ci    /* Must be at least 96 bits */
2934e1051a39Sopenharmony_ci    if (sz <= 0 || gctx->ivlen < 12)
2935e1051a39Sopenharmony_ci        return 0;
2936e1051a39Sopenharmony_ci
2937e1051a39Sopenharmony_ci    /* Use DRBG to generate random iv */
2938e1051a39Sopenharmony_ci    if (RAND_bytes(gctx->iv + offset, sz) <= 0)
2939e1051a39Sopenharmony_ci        return 0;
2940e1051a39Sopenharmony_ci    return 1;
2941e1051a39Sopenharmony_ci}
2942e1051a39Sopenharmony_ci#endif /* FIPS_MODULE */
2943e1051a39Sopenharmony_ci
2944e1051a39Sopenharmony_cistatic int aes_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
2945e1051a39Sopenharmony_ci                          const unsigned char *in, size_t len)
2946e1051a39Sopenharmony_ci{
2947e1051a39Sopenharmony_ci    EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx);
2948e1051a39Sopenharmony_ci
2949e1051a39Sopenharmony_ci    /* If not set up, return error */
2950e1051a39Sopenharmony_ci    if (!gctx->key_set)
2951e1051a39Sopenharmony_ci        return -1;
2952e1051a39Sopenharmony_ci
2953e1051a39Sopenharmony_ci    if (gctx->tls_aad_len >= 0)
2954e1051a39Sopenharmony_ci        return aes_gcm_tls_cipher(ctx, out, in, len);
2955e1051a39Sopenharmony_ci
2956e1051a39Sopenharmony_ci#ifdef FIPS_MODULE
2957e1051a39Sopenharmony_ci    /*
2958e1051a39Sopenharmony_ci     * FIPS requires generation of AES-GCM IV's inside the FIPS module.
2959e1051a39Sopenharmony_ci     * The IV can still be set externally (the security policy will state that
2960e1051a39Sopenharmony_ci     * this is not FIPS compliant). There are some applications
2961e1051a39Sopenharmony_ci     * where setting the IV externally is the only option available.
2962e1051a39Sopenharmony_ci     */
2963e1051a39Sopenharmony_ci    if (!gctx->iv_set) {
2964e1051a39Sopenharmony_ci        if (!ctx->encrypt || !aes_gcm_iv_generate(gctx, 0))
2965e1051a39Sopenharmony_ci            return -1;
2966e1051a39Sopenharmony_ci        CRYPTO_gcm128_setiv(&gctx->gcm, gctx->iv, gctx->ivlen);
2967e1051a39Sopenharmony_ci        gctx->iv_set = 1;
2968e1051a39Sopenharmony_ci        gctx->iv_gen_rand = 1;
2969e1051a39Sopenharmony_ci    }
2970e1051a39Sopenharmony_ci#else
2971e1051a39Sopenharmony_ci    if (!gctx->iv_set)
2972e1051a39Sopenharmony_ci        return -1;
2973e1051a39Sopenharmony_ci#endif /* FIPS_MODULE */
2974e1051a39Sopenharmony_ci
2975e1051a39Sopenharmony_ci    if (in) {
2976e1051a39Sopenharmony_ci        if (out == NULL) {
2977e1051a39Sopenharmony_ci            if (CRYPTO_gcm128_aad(&gctx->gcm, in, len))
2978e1051a39Sopenharmony_ci                return -1;
2979e1051a39Sopenharmony_ci        } else if (ctx->encrypt) {
2980e1051a39Sopenharmony_ci            if (gctx->ctr) {
2981e1051a39Sopenharmony_ci                size_t bulk = 0;
2982e1051a39Sopenharmony_ci#if defined(AES_GCM_ASM)
2983e1051a39Sopenharmony_ci                if (len >= 32 && AES_GCM_ASM(gctx)) {
2984e1051a39Sopenharmony_ci                    size_t res = (16 - gctx->gcm.mres) % 16;
2985e1051a39Sopenharmony_ci
2986e1051a39Sopenharmony_ci                    if (CRYPTO_gcm128_encrypt(&gctx->gcm, in, out, res))
2987e1051a39Sopenharmony_ci                        return -1;
2988e1051a39Sopenharmony_ci
2989e1051a39Sopenharmony_ci                    bulk = AES_gcm_encrypt(in + res,
2990e1051a39Sopenharmony_ci                                           out + res, len - res,
2991e1051a39Sopenharmony_ci                                           gctx->gcm.key, gctx->gcm.Yi.c,
2992e1051a39Sopenharmony_ci                                           gctx->gcm.Xi.u);
2993e1051a39Sopenharmony_ci                    gctx->gcm.len.u[1] += bulk;
2994e1051a39Sopenharmony_ci                    bulk += res;
2995e1051a39Sopenharmony_ci                }
2996e1051a39Sopenharmony_ci#endif
2997e1051a39Sopenharmony_ci                if (CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm,
2998e1051a39Sopenharmony_ci                                                in + bulk,
2999e1051a39Sopenharmony_ci                                                out + bulk,
3000e1051a39Sopenharmony_ci                                                len - bulk, gctx->ctr))
3001e1051a39Sopenharmony_ci                    return -1;
3002e1051a39Sopenharmony_ci            } else {
3003e1051a39Sopenharmony_ci                size_t bulk = 0;
3004e1051a39Sopenharmony_ci#if defined(AES_GCM_ASM2)
3005e1051a39Sopenharmony_ci                if (len >= 32 && AES_GCM_ASM2(gctx)) {
3006e1051a39Sopenharmony_ci                    size_t res = (16 - gctx->gcm.mres) % 16;
3007e1051a39Sopenharmony_ci
3008e1051a39Sopenharmony_ci                    if (CRYPTO_gcm128_encrypt(&gctx->gcm, in, out, res))
3009e1051a39Sopenharmony_ci                        return -1;
3010e1051a39Sopenharmony_ci
3011e1051a39Sopenharmony_ci                    bulk = AES_gcm_encrypt(in + res,
3012e1051a39Sopenharmony_ci                                           out + res, len - res,
3013e1051a39Sopenharmony_ci                                           gctx->gcm.key, gctx->gcm.Yi.c,
3014e1051a39Sopenharmony_ci                                           gctx->gcm.Xi.u);
3015e1051a39Sopenharmony_ci                    gctx->gcm.len.u[1] += bulk;
3016e1051a39Sopenharmony_ci                    bulk += res;
3017e1051a39Sopenharmony_ci                }
3018e1051a39Sopenharmony_ci#endif
3019e1051a39Sopenharmony_ci                if (CRYPTO_gcm128_encrypt(&gctx->gcm,
3020e1051a39Sopenharmony_ci                                          in + bulk, out + bulk, len - bulk))
3021e1051a39Sopenharmony_ci                    return -1;
3022e1051a39Sopenharmony_ci            }
3023e1051a39Sopenharmony_ci        } else {
3024e1051a39Sopenharmony_ci            if (gctx->ctr) {
3025e1051a39Sopenharmony_ci                size_t bulk = 0;
3026e1051a39Sopenharmony_ci#if defined(AES_GCM_ASM)
3027e1051a39Sopenharmony_ci                if (len >= 16 && AES_GCM_ASM(gctx)) {
3028e1051a39Sopenharmony_ci                    size_t res = (16 - gctx->gcm.mres) % 16;
3029e1051a39Sopenharmony_ci
3030e1051a39Sopenharmony_ci                    if (CRYPTO_gcm128_decrypt(&gctx->gcm, in, out, res))
3031e1051a39Sopenharmony_ci                        return -1;
3032e1051a39Sopenharmony_ci
3033e1051a39Sopenharmony_ci                    bulk = AES_gcm_decrypt(in + res,
3034e1051a39Sopenharmony_ci                                           out + res, len - res,
3035e1051a39Sopenharmony_ci                                           gctx->gcm.key,
3036e1051a39Sopenharmony_ci                                           gctx->gcm.Yi.c, gctx->gcm.Xi.u);
3037e1051a39Sopenharmony_ci                    gctx->gcm.len.u[1] += bulk;
3038e1051a39Sopenharmony_ci                    bulk += res;
3039e1051a39Sopenharmony_ci                }
3040e1051a39Sopenharmony_ci#endif
3041e1051a39Sopenharmony_ci                if (CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm,
3042e1051a39Sopenharmony_ci                                                in + bulk,
3043e1051a39Sopenharmony_ci                                                out + bulk,
3044e1051a39Sopenharmony_ci                                                len - bulk, gctx->ctr))
3045e1051a39Sopenharmony_ci                    return -1;
3046e1051a39Sopenharmony_ci            } else {
3047e1051a39Sopenharmony_ci                size_t bulk = 0;
3048e1051a39Sopenharmony_ci#if defined(AES_GCM_ASM2)
3049e1051a39Sopenharmony_ci                if (len >= 16 && AES_GCM_ASM2(gctx)) {
3050e1051a39Sopenharmony_ci                    size_t res = (16 - gctx->gcm.mres) % 16;
3051e1051a39Sopenharmony_ci
3052e1051a39Sopenharmony_ci                    if (CRYPTO_gcm128_decrypt(&gctx->gcm, in, out, res))
3053e1051a39Sopenharmony_ci                        return -1;
3054e1051a39Sopenharmony_ci
3055e1051a39Sopenharmony_ci                    bulk = AES_gcm_decrypt(in + res,
3056e1051a39Sopenharmony_ci                                           out + res, len - res,
3057e1051a39Sopenharmony_ci                                           gctx->gcm.key,
3058e1051a39Sopenharmony_ci                                           gctx->gcm.Yi.c, gctx->gcm.Xi.u);
3059e1051a39Sopenharmony_ci                    gctx->gcm.len.u[1] += bulk;
3060e1051a39Sopenharmony_ci                    bulk += res;
3061e1051a39Sopenharmony_ci                }
3062e1051a39Sopenharmony_ci#endif
3063e1051a39Sopenharmony_ci                if (CRYPTO_gcm128_decrypt(&gctx->gcm,
3064e1051a39Sopenharmony_ci                                          in + bulk, out + bulk, len - bulk))
3065e1051a39Sopenharmony_ci                    return -1;
3066e1051a39Sopenharmony_ci            }
3067e1051a39Sopenharmony_ci        }
3068e1051a39Sopenharmony_ci        return len;
3069e1051a39Sopenharmony_ci    } else {
3070e1051a39Sopenharmony_ci        if (!ctx->encrypt) {
3071e1051a39Sopenharmony_ci            if (gctx->taglen < 0)
3072e1051a39Sopenharmony_ci                return -1;
3073e1051a39Sopenharmony_ci            if (CRYPTO_gcm128_finish(&gctx->gcm, ctx->buf, gctx->taglen) != 0)
3074e1051a39Sopenharmony_ci                return -1;
3075e1051a39Sopenharmony_ci            gctx->iv_set = 0;
3076e1051a39Sopenharmony_ci            return 0;
3077e1051a39Sopenharmony_ci        }
3078e1051a39Sopenharmony_ci        CRYPTO_gcm128_tag(&gctx->gcm, ctx->buf, 16);
3079e1051a39Sopenharmony_ci        gctx->taglen = 16;
3080e1051a39Sopenharmony_ci        /* Don't reuse the IV */
3081e1051a39Sopenharmony_ci        gctx->iv_set = 0;
3082e1051a39Sopenharmony_ci        return 0;
3083e1051a39Sopenharmony_ci    }
3084e1051a39Sopenharmony_ci
3085e1051a39Sopenharmony_ci}
3086e1051a39Sopenharmony_ci
3087e1051a39Sopenharmony_ci#define CUSTOM_FLAGS    (EVP_CIPH_FLAG_DEFAULT_ASN1 \
3088e1051a39Sopenharmony_ci                | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \
3089e1051a39Sopenharmony_ci                | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \
3090e1051a39Sopenharmony_ci                | EVP_CIPH_CUSTOM_COPY | EVP_CIPH_CUSTOM_IV_LENGTH)
3091e1051a39Sopenharmony_ci
3092e1051a39Sopenharmony_ciBLOCK_CIPHER_custom(NID_aes, 128, 1, 12, gcm, GCM,
3093e1051a39Sopenharmony_ci                    EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS)
3094e1051a39Sopenharmony_ci    BLOCK_CIPHER_custom(NID_aes, 192, 1, 12, gcm, GCM,
3095e1051a39Sopenharmony_ci                    EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS)
3096e1051a39Sopenharmony_ci    BLOCK_CIPHER_custom(NID_aes, 256, 1, 12, gcm, GCM,
3097e1051a39Sopenharmony_ci                    EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS)
3098e1051a39Sopenharmony_ci
3099e1051a39Sopenharmony_cistatic int aes_xts_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
3100e1051a39Sopenharmony_ci{
3101e1051a39Sopenharmony_ci    EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX, c);
3102e1051a39Sopenharmony_ci
3103e1051a39Sopenharmony_ci    if (type == EVP_CTRL_COPY) {
3104e1051a39Sopenharmony_ci        EVP_CIPHER_CTX *out = ptr;
3105e1051a39Sopenharmony_ci        EVP_AES_XTS_CTX *xctx_out = EVP_C_DATA(EVP_AES_XTS_CTX,out);
3106e1051a39Sopenharmony_ci
3107e1051a39Sopenharmony_ci        if (xctx->xts.key1) {
3108e1051a39Sopenharmony_ci            if (xctx->xts.key1 != &xctx->ks1)
3109e1051a39Sopenharmony_ci                return 0;
3110e1051a39Sopenharmony_ci            xctx_out->xts.key1 = &xctx_out->ks1;
3111e1051a39Sopenharmony_ci        }
3112e1051a39Sopenharmony_ci        if (xctx->xts.key2) {
3113e1051a39Sopenharmony_ci            if (xctx->xts.key2 != &xctx->ks2)
3114e1051a39Sopenharmony_ci                return 0;
3115e1051a39Sopenharmony_ci            xctx_out->xts.key2 = &xctx_out->ks2;
3116e1051a39Sopenharmony_ci        }
3117e1051a39Sopenharmony_ci        return 1;
3118e1051a39Sopenharmony_ci    } else if (type != EVP_CTRL_INIT)
3119e1051a39Sopenharmony_ci        return -1;
3120e1051a39Sopenharmony_ci    /* key1 and key2 are used as an indicator both key and IV are set */
3121e1051a39Sopenharmony_ci    xctx->xts.key1 = NULL;
3122e1051a39Sopenharmony_ci    xctx->xts.key2 = NULL;
3123e1051a39Sopenharmony_ci    return 1;
3124e1051a39Sopenharmony_ci}
3125e1051a39Sopenharmony_ci
3126e1051a39Sopenharmony_cistatic int aes_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
3127e1051a39Sopenharmony_ci                            const unsigned char *iv, int enc)
3128e1051a39Sopenharmony_ci{
3129e1051a39Sopenharmony_ci    EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,ctx);
3130e1051a39Sopenharmony_ci
3131e1051a39Sopenharmony_ci    if (!iv && !key)
3132e1051a39Sopenharmony_ci        return 1;
3133e1051a39Sopenharmony_ci
3134e1051a39Sopenharmony_ci    if (key) {
3135e1051a39Sopenharmony_ci        do {
3136e1051a39Sopenharmony_ci            /* The key is two half length keys in reality */
3137e1051a39Sopenharmony_ci            const int bytes = EVP_CIPHER_CTX_get_key_length(ctx) / 2;
3138e1051a39Sopenharmony_ci            const int bits = bytes * 8;
3139e1051a39Sopenharmony_ci
3140e1051a39Sopenharmony_ci            /*
3141e1051a39Sopenharmony_ci             * Verify that the two keys are different.
3142e1051a39Sopenharmony_ci             *
3143e1051a39Sopenharmony_ci             * This addresses the vulnerability described in Rogaway's
3144e1051a39Sopenharmony_ci             * September 2004 paper:
3145e1051a39Sopenharmony_ci             *
3146e1051a39Sopenharmony_ci             *      "Efficient Instantiations of Tweakable Blockciphers and
3147e1051a39Sopenharmony_ci             *       Refinements to Modes OCB and PMAC".
3148e1051a39Sopenharmony_ci             *      (http://web.cs.ucdavis.edu/~rogaway/papers/offsets.pdf)
3149e1051a39Sopenharmony_ci             *
3150e1051a39Sopenharmony_ci             * FIPS 140-2 IG A.9 XTS-AES Key Generation Requirements states
3151e1051a39Sopenharmony_ci             * that:
3152e1051a39Sopenharmony_ci             *      "The check for Key_1 != Key_2 shall be done at any place
3153e1051a39Sopenharmony_ci             *       BEFORE using the keys in the XTS-AES algorithm to process
3154e1051a39Sopenharmony_ci             *       data with them."
3155e1051a39Sopenharmony_ci             */
3156e1051a39Sopenharmony_ci            if ((!allow_insecure_decrypt || enc)
3157e1051a39Sopenharmony_ci                    && CRYPTO_memcmp(key, key + bytes, bytes) == 0) {
3158e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_EVP, EVP_R_XTS_DUPLICATED_KEYS);
3159e1051a39Sopenharmony_ci                return 0;
3160e1051a39Sopenharmony_ci            }
3161e1051a39Sopenharmony_ci
3162e1051a39Sopenharmony_ci#ifdef AES_XTS_ASM
3163e1051a39Sopenharmony_ci            xctx->stream = enc ? AES_xts_encrypt : AES_xts_decrypt;
3164e1051a39Sopenharmony_ci#else
3165e1051a39Sopenharmony_ci            xctx->stream = NULL;
3166e1051a39Sopenharmony_ci#endif
3167e1051a39Sopenharmony_ci            /* key_len is two AES keys */
3168e1051a39Sopenharmony_ci#ifdef HWAES_CAPABLE
3169e1051a39Sopenharmony_ci            if (HWAES_CAPABLE) {
3170e1051a39Sopenharmony_ci                if (enc) {
3171e1051a39Sopenharmony_ci                    HWAES_set_encrypt_key(key, bits, &xctx->ks1.ks);
3172e1051a39Sopenharmony_ci                    xctx->xts.block1 = (block128_f) HWAES_encrypt;
3173e1051a39Sopenharmony_ci# ifdef HWAES_xts_encrypt
3174e1051a39Sopenharmony_ci                    xctx->stream = HWAES_xts_encrypt;
3175e1051a39Sopenharmony_ci# endif
3176e1051a39Sopenharmony_ci                } else {
3177e1051a39Sopenharmony_ci                    HWAES_set_decrypt_key(key, bits, &xctx->ks1.ks);
3178e1051a39Sopenharmony_ci                    xctx->xts.block1 = (block128_f) HWAES_decrypt;
3179e1051a39Sopenharmony_ci# ifdef HWAES_xts_decrypt
3180e1051a39Sopenharmony_ci                    xctx->stream = HWAES_xts_decrypt;
3181e1051a39Sopenharmony_ci#endif
3182e1051a39Sopenharmony_ci                }
3183e1051a39Sopenharmony_ci
3184e1051a39Sopenharmony_ci                HWAES_set_encrypt_key(key + bytes, bits, &xctx->ks2.ks);
3185e1051a39Sopenharmony_ci                xctx->xts.block2 = (block128_f) HWAES_encrypt;
3186e1051a39Sopenharmony_ci
3187e1051a39Sopenharmony_ci                xctx->xts.key1 = &xctx->ks1;
3188e1051a39Sopenharmony_ci                break;
3189e1051a39Sopenharmony_ci            } else
3190e1051a39Sopenharmony_ci#endif
3191e1051a39Sopenharmony_ci#ifdef BSAES_CAPABLE
3192e1051a39Sopenharmony_ci            if (BSAES_CAPABLE)
3193e1051a39Sopenharmony_ci                xctx->stream = enc ? ossl_bsaes_xts_encrypt : ossl_bsaes_xts_decrypt;
3194e1051a39Sopenharmony_ci            else
3195e1051a39Sopenharmony_ci#endif
3196e1051a39Sopenharmony_ci#ifdef VPAES_CAPABLE
3197e1051a39Sopenharmony_ci            if (VPAES_CAPABLE) {
3198e1051a39Sopenharmony_ci                if (enc) {
3199e1051a39Sopenharmony_ci                    vpaes_set_encrypt_key(key, bits, &xctx->ks1.ks);
3200e1051a39Sopenharmony_ci                    xctx->xts.block1 = (block128_f) vpaes_encrypt;
3201e1051a39Sopenharmony_ci                } else {
3202e1051a39Sopenharmony_ci                    vpaes_set_decrypt_key(key, bits, &xctx->ks1.ks);
3203e1051a39Sopenharmony_ci                    xctx->xts.block1 = (block128_f) vpaes_decrypt;
3204e1051a39Sopenharmony_ci                }
3205e1051a39Sopenharmony_ci
3206e1051a39Sopenharmony_ci                vpaes_set_encrypt_key(key + bytes, bits, &xctx->ks2.ks);
3207e1051a39Sopenharmony_ci                xctx->xts.block2 = (block128_f) vpaes_encrypt;
3208e1051a39Sopenharmony_ci
3209e1051a39Sopenharmony_ci                xctx->xts.key1 = &xctx->ks1;
3210e1051a39Sopenharmony_ci                break;
3211e1051a39Sopenharmony_ci            } else
3212e1051a39Sopenharmony_ci#endif
3213e1051a39Sopenharmony_ci                (void)0;        /* terminate potentially open 'else' */
3214e1051a39Sopenharmony_ci
3215e1051a39Sopenharmony_ci            if (enc) {
3216e1051a39Sopenharmony_ci                AES_set_encrypt_key(key, bits, &xctx->ks1.ks);
3217e1051a39Sopenharmony_ci                xctx->xts.block1 = (block128_f) AES_encrypt;
3218e1051a39Sopenharmony_ci            } else {
3219e1051a39Sopenharmony_ci                AES_set_decrypt_key(key, bits, &xctx->ks1.ks);
3220e1051a39Sopenharmony_ci                xctx->xts.block1 = (block128_f) AES_decrypt;
3221e1051a39Sopenharmony_ci            }
3222e1051a39Sopenharmony_ci
3223e1051a39Sopenharmony_ci            AES_set_encrypt_key(key + bytes, bits, &xctx->ks2.ks);
3224e1051a39Sopenharmony_ci            xctx->xts.block2 = (block128_f) AES_encrypt;
3225e1051a39Sopenharmony_ci
3226e1051a39Sopenharmony_ci            xctx->xts.key1 = &xctx->ks1;
3227e1051a39Sopenharmony_ci        } while (0);
3228e1051a39Sopenharmony_ci    }
3229e1051a39Sopenharmony_ci
3230e1051a39Sopenharmony_ci    if (iv) {
3231e1051a39Sopenharmony_ci        xctx->xts.key2 = &xctx->ks2;
3232e1051a39Sopenharmony_ci        memcpy(ctx->iv, iv, 16);
3233e1051a39Sopenharmony_ci    }
3234e1051a39Sopenharmony_ci
3235e1051a39Sopenharmony_ci    return 1;
3236e1051a39Sopenharmony_ci}
3237e1051a39Sopenharmony_ci
3238e1051a39Sopenharmony_cistatic int aes_xts_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
3239e1051a39Sopenharmony_ci                          const unsigned char *in, size_t len)
3240e1051a39Sopenharmony_ci{
3241e1051a39Sopenharmony_ci    EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,ctx);
3242e1051a39Sopenharmony_ci
3243e1051a39Sopenharmony_ci    if (xctx->xts.key1 == NULL
3244e1051a39Sopenharmony_ci            || xctx->xts.key2 == NULL
3245e1051a39Sopenharmony_ci            || out == NULL
3246e1051a39Sopenharmony_ci            || in == NULL
3247e1051a39Sopenharmony_ci            || len < AES_BLOCK_SIZE)
3248e1051a39Sopenharmony_ci        return 0;
3249e1051a39Sopenharmony_ci
3250e1051a39Sopenharmony_ci    /*
3251e1051a39Sopenharmony_ci     * Impose a limit of 2^20 blocks per data unit as specified by
3252e1051a39Sopenharmony_ci     * IEEE Std 1619-2018.  The earlier and obsolete IEEE Std 1619-2007
3253e1051a39Sopenharmony_ci     * indicated that this was a SHOULD NOT rather than a MUST NOT.
3254e1051a39Sopenharmony_ci     * NIST SP 800-38E mandates the same limit.
3255e1051a39Sopenharmony_ci     */
3256e1051a39Sopenharmony_ci    if (len > XTS_MAX_BLOCKS_PER_DATA_UNIT * AES_BLOCK_SIZE) {
3257e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EVP, EVP_R_XTS_DATA_UNIT_IS_TOO_LARGE);
3258e1051a39Sopenharmony_ci        return 0;
3259e1051a39Sopenharmony_ci    }
3260e1051a39Sopenharmony_ci
3261e1051a39Sopenharmony_ci    if (xctx->stream)
3262e1051a39Sopenharmony_ci        (*xctx->stream) (in, out, len,
3263e1051a39Sopenharmony_ci                         xctx->xts.key1, xctx->xts.key2,
3264e1051a39Sopenharmony_ci                         ctx->iv);
3265e1051a39Sopenharmony_ci    else if (CRYPTO_xts128_encrypt(&xctx->xts, ctx->iv, in, out, len,
3266e1051a39Sopenharmony_ci                                   EVP_CIPHER_CTX_is_encrypting(ctx)))
3267e1051a39Sopenharmony_ci        return 0;
3268e1051a39Sopenharmony_ci    return 1;
3269e1051a39Sopenharmony_ci}
3270e1051a39Sopenharmony_ci
3271e1051a39Sopenharmony_ci#define aes_xts_cleanup NULL
3272e1051a39Sopenharmony_ci
3273e1051a39Sopenharmony_ci#define XTS_FLAGS       (EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CUSTOM_IV \
3274e1051a39Sopenharmony_ci                         | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \
3275e1051a39Sopenharmony_ci                         | EVP_CIPH_CUSTOM_COPY)
3276e1051a39Sopenharmony_ci
3277e1051a39Sopenharmony_ciBLOCK_CIPHER_custom(NID_aes, 128, 1, 16, xts, XTS, XTS_FLAGS)
3278e1051a39Sopenharmony_ci    BLOCK_CIPHER_custom(NID_aes, 256, 1, 16, xts, XTS, XTS_FLAGS)
3279e1051a39Sopenharmony_ci
3280e1051a39Sopenharmony_cistatic int aes_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
3281e1051a39Sopenharmony_ci{
3282e1051a39Sopenharmony_ci    EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,c);
3283e1051a39Sopenharmony_ci    switch (type) {
3284e1051a39Sopenharmony_ci    case EVP_CTRL_INIT:
3285e1051a39Sopenharmony_ci        cctx->key_set = 0;
3286e1051a39Sopenharmony_ci        cctx->iv_set = 0;
3287e1051a39Sopenharmony_ci        cctx->L = 8;
3288e1051a39Sopenharmony_ci        cctx->M = 12;
3289e1051a39Sopenharmony_ci        cctx->tag_set = 0;
3290e1051a39Sopenharmony_ci        cctx->len_set = 0;
3291e1051a39Sopenharmony_ci        cctx->tls_aad_len = -1;
3292e1051a39Sopenharmony_ci        return 1;
3293e1051a39Sopenharmony_ci
3294e1051a39Sopenharmony_ci    case EVP_CTRL_GET_IVLEN:
3295e1051a39Sopenharmony_ci        *(int *)ptr = 15 - cctx->L;
3296e1051a39Sopenharmony_ci        return 1;
3297e1051a39Sopenharmony_ci
3298e1051a39Sopenharmony_ci    case EVP_CTRL_AEAD_TLS1_AAD:
3299e1051a39Sopenharmony_ci        /* Save the AAD for later use */
3300e1051a39Sopenharmony_ci        if (arg != EVP_AEAD_TLS1_AAD_LEN)
3301e1051a39Sopenharmony_ci            return 0;
3302e1051a39Sopenharmony_ci        memcpy(EVP_CIPHER_CTX_buf_noconst(c), ptr, arg);
3303e1051a39Sopenharmony_ci        cctx->tls_aad_len = arg;
3304e1051a39Sopenharmony_ci        {
3305e1051a39Sopenharmony_ci            uint16_t len =
3306e1051a39Sopenharmony_ci                EVP_CIPHER_CTX_buf_noconst(c)[arg - 2] << 8
3307e1051a39Sopenharmony_ci                | EVP_CIPHER_CTX_buf_noconst(c)[arg - 1];
3308e1051a39Sopenharmony_ci            /* Correct length for explicit IV */
3309e1051a39Sopenharmony_ci            if (len < EVP_CCM_TLS_EXPLICIT_IV_LEN)
3310e1051a39Sopenharmony_ci                return 0;
3311e1051a39Sopenharmony_ci            len -= EVP_CCM_TLS_EXPLICIT_IV_LEN;
3312e1051a39Sopenharmony_ci            /* If decrypting correct for tag too */
3313e1051a39Sopenharmony_ci            if (!EVP_CIPHER_CTX_is_encrypting(c)) {
3314e1051a39Sopenharmony_ci                if (len < cctx->M)
3315e1051a39Sopenharmony_ci                    return 0;
3316e1051a39Sopenharmony_ci                len -= cctx->M;
3317e1051a39Sopenharmony_ci            }
3318e1051a39Sopenharmony_ci            EVP_CIPHER_CTX_buf_noconst(c)[arg - 2] = len >> 8;
3319e1051a39Sopenharmony_ci            EVP_CIPHER_CTX_buf_noconst(c)[arg - 1] = len & 0xff;
3320e1051a39Sopenharmony_ci        }
3321e1051a39Sopenharmony_ci        /* Extra padding: tag appended to record */
3322e1051a39Sopenharmony_ci        return cctx->M;
3323e1051a39Sopenharmony_ci
3324e1051a39Sopenharmony_ci    case EVP_CTRL_CCM_SET_IV_FIXED:
3325e1051a39Sopenharmony_ci        /* Sanity check length */
3326e1051a39Sopenharmony_ci        if (arg != EVP_CCM_TLS_FIXED_IV_LEN)
3327e1051a39Sopenharmony_ci            return 0;
3328e1051a39Sopenharmony_ci        /* Just copy to first part of IV */
3329e1051a39Sopenharmony_ci        memcpy(c->iv, ptr, arg);
3330e1051a39Sopenharmony_ci        return 1;
3331e1051a39Sopenharmony_ci
3332e1051a39Sopenharmony_ci    case EVP_CTRL_AEAD_SET_IVLEN:
3333e1051a39Sopenharmony_ci        arg = 15 - arg;
3334e1051a39Sopenharmony_ci        /* fall thru */
3335e1051a39Sopenharmony_ci    case EVP_CTRL_CCM_SET_L:
3336e1051a39Sopenharmony_ci        if (arg < 2 || arg > 8)
3337e1051a39Sopenharmony_ci            return 0;
3338e1051a39Sopenharmony_ci        cctx->L = arg;
3339e1051a39Sopenharmony_ci        return 1;
3340e1051a39Sopenharmony_ci
3341e1051a39Sopenharmony_ci    case EVP_CTRL_AEAD_SET_TAG:
3342e1051a39Sopenharmony_ci        if ((arg & 1) || arg < 4 || arg > 16)
3343e1051a39Sopenharmony_ci            return 0;
3344e1051a39Sopenharmony_ci        if (EVP_CIPHER_CTX_is_encrypting(c) && ptr)
3345e1051a39Sopenharmony_ci            return 0;
3346e1051a39Sopenharmony_ci        if (ptr) {
3347e1051a39Sopenharmony_ci            cctx->tag_set = 1;
3348e1051a39Sopenharmony_ci            memcpy(EVP_CIPHER_CTX_buf_noconst(c), ptr, arg);
3349e1051a39Sopenharmony_ci        }
3350e1051a39Sopenharmony_ci        cctx->M = arg;
3351e1051a39Sopenharmony_ci        return 1;
3352e1051a39Sopenharmony_ci
3353e1051a39Sopenharmony_ci    case EVP_CTRL_AEAD_GET_TAG:
3354e1051a39Sopenharmony_ci        if (!EVP_CIPHER_CTX_is_encrypting(c) || !cctx->tag_set)
3355e1051a39Sopenharmony_ci            return 0;
3356e1051a39Sopenharmony_ci        if (!CRYPTO_ccm128_tag(&cctx->ccm, ptr, (size_t)arg))
3357e1051a39Sopenharmony_ci            return 0;
3358e1051a39Sopenharmony_ci        cctx->tag_set = 0;
3359e1051a39Sopenharmony_ci        cctx->iv_set = 0;
3360e1051a39Sopenharmony_ci        cctx->len_set = 0;
3361e1051a39Sopenharmony_ci        return 1;
3362e1051a39Sopenharmony_ci
3363e1051a39Sopenharmony_ci    case EVP_CTRL_COPY:
3364e1051a39Sopenharmony_ci        {
3365e1051a39Sopenharmony_ci            EVP_CIPHER_CTX *out = ptr;
3366e1051a39Sopenharmony_ci            EVP_AES_CCM_CTX *cctx_out = EVP_C_DATA(EVP_AES_CCM_CTX,out);
3367e1051a39Sopenharmony_ci            if (cctx->ccm.key) {
3368e1051a39Sopenharmony_ci                if (cctx->ccm.key != &cctx->ks)
3369e1051a39Sopenharmony_ci                    return 0;
3370e1051a39Sopenharmony_ci                cctx_out->ccm.key = &cctx_out->ks;
3371e1051a39Sopenharmony_ci            }
3372e1051a39Sopenharmony_ci            return 1;
3373e1051a39Sopenharmony_ci        }
3374e1051a39Sopenharmony_ci
3375e1051a39Sopenharmony_ci    default:
3376e1051a39Sopenharmony_ci        return -1;
3377e1051a39Sopenharmony_ci
3378e1051a39Sopenharmony_ci    }
3379e1051a39Sopenharmony_ci}
3380e1051a39Sopenharmony_ci
3381e1051a39Sopenharmony_cistatic int aes_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
3382e1051a39Sopenharmony_ci                            const unsigned char *iv, int enc)
3383e1051a39Sopenharmony_ci{
3384e1051a39Sopenharmony_ci    EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx);
3385e1051a39Sopenharmony_ci    if (!iv && !key)
3386e1051a39Sopenharmony_ci        return 1;
3387e1051a39Sopenharmony_ci    if (key)
3388e1051a39Sopenharmony_ci        do {
3389e1051a39Sopenharmony_ci#ifdef HWAES_CAPABLE
3390e1051a39Sopenharmony_ci            if (HWAES_CAPABLE) {
3391e1051a39Sopenharmony_ci                HWAES_set_encrypt_key(key,
3392e1051a39Sopenharmony_ci                                      EVP_CIPHER_CTX_get_key_length(ctx) * 8,
3393e1051a39Sopenharmony_ci                                      &cctx->ks.ks);
3394e1051a39Sopenharmony_ci
3395e1051a39Sopenharmony_ci                CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L,
3396e1051a39Sopenharmony_ci                                   &cctx->ks, (block128_f) HWAES_encrypt);
3397e1051a39Sopenharmony_ci                cctx->str = NULL;
3398e1051a39Sopenharmony_ci                cctx->key_set = 1;
3399e1051a39Sopenharmony_ci                break;
3400e1051a39Sopenharmony_ci            } else
3401e1051a39Sopenharmony_ci#endif
3402e1051a39Sopenharmony_ci#ifdef VPAES_CAPABLE
3403e1051a39Sopenharmony_ci            if (VPAES_CAPABLE) {
3404e1051a39Sopenharmony_ci                vpaes_set_encrypt_key(key,
3405e1051a39Sopenharmony_ci                                      EVP_CIPHER_CTX_get_key_length(ctx) * 8,
3406e1051a39Sopenharmony_ci                                      &cctx->ks.ks);
3407e1051a39Sopenharmony_ci                CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L,
3408e1051a39Sopenharmony_ci                                   &cctx->ks, (block128_f) vpaes_encrypt);
3409e1051a39Sopenharmony_ci                cctx->str = NULL;
3410e1051a39Sopenharmony_ci                cctx->key_set = 1;
3411e1051a39Sopenharmony_ci                break;
3412e1051a39Sopenharmony_ci            }
3413e1051a39Sopenharmony_ci#endif
3414e1051a39Sopenharmony_ci            AES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
3415e1051a39Sopenharmony_ci                                &cctx->ks.ks);
3416e1051a39Sopenharmony_ci            CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L,
3417e1051a39Sopenharmony_ci                               &cctx->ks, (block128_f) AES_encrypt);
3418e1051a39Sopenharmony_ci            cctx->str = NULL;
3419e1051a39Sopenharmony_ci            cctx->key_set = 1;
3420e1051a39Sopenharmony_ci        } while (0);
3421e1051a39Sopenharmony_ci    if (iv) {
3422e1051a39Sopenharmony_ci        memcpy(ctx->iv, iv, 15 - cctx->L);
3423e1051a39Sopenharmony_ci        cctx->iv_set = 1;
3424e1051a39Sopenharmony_ci    }
3425e1051a39Sopenharmony_ci    return 1;
3426e1051a39Sopenharmony_ci}
3427e1051a39Sopenharmony_ci
3428e1051a39Sopenharmony_cistatic int aes_ccm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
3429e1051a39Sopenharmony_ci                              const unsigned char *in, size_t len)
3430e1051a39Sopenharmony_ci{
3431e1051a39Sopenharmony_ci    EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx);
3432e1051a39Sopenharmony_ci    CCM128_CONTEXT *ccm = &cctx->ccm;
3433e1051a39Sopenharmony_ci    /* Encrypt/decrypt must be performed in place */
3434e1051a39Sopenharmony_ci    if (out != in || len < (EVP_CCM_TLS_EXPLICIT_IV_LEN + (size_t)cctx->M))
3435e1051a39Sopenharmony_ci        return -1;
3436e1051a39Sopenharmony_ci    /* If encrypting set explicit IV from sequence number (start of AAD) */
3437e1051a39Sopenharmony_ci    if (EVP_CIPHER_CTX_is_encrypting(ctx))
3438e1051a39Sopenharmony_ci        memcpy(out, EVP_CIPHER_CTX_buf_noconst(ctx),
3439e1051a39Sopenharmony_ci               EVP_CCM_TLS_EXPLICIT_IV_LEN);
3440e1051a39Sopenharmony_ci    /* Get rest of IV from explicit IV */
3441e1051a39Sopenharmony_ci    memcpy(ctx->iv + EVP_CCM_TLS_FIXED_IV_LEN, in,
3442e1051a39Sopenharmony_ci           EVP_CCM_TLS_EXPLICIT_IV_LEN);
3443e1051a39Sopenharmony_ci    /* Correct length value */
3444e1051a39Sopenharmony_ci    len -= EVP_CCM_TLS_EXPLICIT_IV_LEN + cctx->M;
3445e1051a39Sopenharmony_ci    if (CRYPTO_ccm128_setiv(ccm, ctx->iv, 15 - cctx->L,
3446e1051a39Sopenharmony_ci                            len))
3447e1051a39Sopenharmony_ci            return -1;
3448e1051a39Sopenharmony_ci    /* Use saved AAD */
3449e1051a39Sopenharmony_ci    CRYPTO_ccm128_aad(ccm, EVP_CIPHER_CTX_buf_noconst(ctx),
3450e1051a39Sopenharmony_ci                      cctx->tls_aad_len);
3451e1051a39Sopenharmony_ci    /* Fix buffer to point to payload */
3452e1051a39Sopenharmony_ci    in += EVP_CCM_TLS_EXPLICIT_IV_LEN;
3453e1051a39Sopenharmony_ci    out += EVP_CCM_TLS_EXPLICIT_IV_LEN;
3454e1051a39Sopenharmony_ci    if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
3455e1051a39Sopenharmony_ci        if (cctx->str ? CRYPTO_ccm128_encrypt_ccm64(ccm, in, out, len,
3456e1051a39Sopenharmony_ci                                                    cctx->str) :
3457e1051a39Sopenharmony_ci            CRYPTO_ccm128_encrypt(ccm, in, out, len))
3458e1051a39Sopenharmony_ci            return -1;
3459e1051a39Sopenharmony_ci        if (!CRYPTO_ccm128_tag(ccm, out + len, cctx->M))
3460e1051a39Sopenharmony_ci            return -1;
3461e1051a39Sopenharmony_ci        return len + EVP_CCM_TLS_EXPLICIT_IV_LEN + cctx->M;
3462e1051a39Sopenharmony_ci    } else {
3463e1051a39Sopenharmony_ci        if (cctx->str ? !CRYPTO_ccm128_decrypt_ccm64(ccm, in, out, len,
3464e1051a39Sopenharmony_ci                                                     cctx->str) :
3465e1051a39Sopenharmony_ci            !CRYPTO_ccm128_decrypt(ccm, in, out, len)) {
3466e1051a39Sopenharmony_ci            unsigned char tag[16];
3467e1051a39Sopenharmony_ci            if (CRYPTO_ccm128_tag(ccm, tag, cctx->M)) {
3468e1051a39Sopenharmony_ci                if (!CRYPTO_memcmp(tag, in + len, cctx->M))
3469e1051a39Sopenharmony_ci                    return len;
3470e1051a39Sopenharmony_ci            }
3471e1051a39Sopenharmony_ci        }
3472e1051a39Sopenharmony_ci        OPENSSL_cleanse(out, len);
3473e1051a39Sopenharmony_ci        return -1;
3474e1051a39Sopenharmony_ci    }
3475e1051a39Sopenharmony_ci}
3476e1051a39Sopenharmony_ci
3477e1051a39Sopenharmony_cistatic int aes_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
3478e1051a39Sopenharmony_ci                          const unsigned char *in, size_t len)
3479e1051a39Sopenharmony_ci{
3480e1051a39Sopenharmony_ci    EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx);
3481e1051a39Sopenharmony_ci    CCM128_CONTEXT *ccm = &cctx->ccm;
3482e1051a39Sopenharmony_ci    /* If not set up, return error */
3483e1051a39Sopenharmony_ci    if (!cctx->key_set)
3484e1051a39Sopenharmony_ci        return -1;
3485e1051a39Sopenharmony_ci
3486e1051a39Sopenharmony_ci    if (cctx->tls_aad_len >= 0)
3487e1051a39Sopenharmony_ci        return aes_ccm_tls_cipher(ctx, out, in, len);
3488e1051a39Sopenharmony_ci
3489e1051a39Sopenharmony_ci    /* EVP_*Final() doesn't return any data */
3490e1051a39Sopenharmony_ci    if (in == NULL && out != NULL)
3491e1051a39Sopenharmony_ci        return 0;
3492e1051a39Sopenharmony_ci
3493e1051a39Sopenharmony_ci    if (!cctx->iv_set)
3494e1051a39Sopenharmony_ci        return -1;
3495e1051a39Sopenharmony_ci
3496e1051a39Sopenharmony_ci    if (!out) {
3497e1051a39Sopenharmony_ci        if (!in) {
3498e1051a39Sopenharmony_ci            if (CRYPTO_ccm128_setiv(ccm, ctx->iv,
3499e1051a39Sopenharmony_ci                                    15 - cctx->L, len))
3500e1051a39Sopenharmony_ci                return -1;
3501e1051a39Sopenharmony_ci            cctx->len_set = 1;
3502e1051a39Sopenharmony_ci            return len;
3503e1051a39Sopenharmony_ci        }
3504e1051a39Sopenharmony_ci        /* If have AAD need message length */
3505e1051a39Sopenharmony_ci        if (!cctx->len_set && len)
3506e1051a39Sopenharmony_ci            return -1;
3507e1051a39Sopenharmony_ci        CRYPTO_ccm128_aad(ccm, in, len);
3508e1051a39Sopenharmony_ci        return len;
3509e1051a39Sopenharmony_ci    }
3510e1051a39Sopenharmony_ci
3511e1051a39Sopenharmony_ci    /* The tag must be set before actually decrypting data */
3512e1051a39Sopenharmony_ci    if (!EVP_CIPHER_CTX_is_encrypting(ctx) && !cctx->tag_set)
3513e1051a39Sopenharmony_ci        return -1;
3514e1051a39Sopenharmony_ci
3515e1051a39Sopenharmony_ci    /* If not set length yet do it */
3516e1051a39Sopenharmony_ci    if (!cctx->len_set) {
3517e1051a39Sopenharmony_ci        if (CRYPTO_ccm128_setiv(ccm, ctx->iv, 15 - cctx->L, len))
3518e1051a39Sopenharmony_ci            return -1;
3519e1051a39Sopenharmony_ci        cctx->len_set = 1;
3520e1051a39Sopenharmony_ci    }
3521e1051a39Sopenharmony_ci    if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
3522e1051a39Sopenharmony_ci        if (cctx->str ? CRYPTO_ccm128_encrypt_ccm64(ccm, in, out, len,
3523e1051a39Sopenharmony_ci                                                    cctx->str) :
3524e1051a39Sopenharmony_ci            CRYPTO_ccm128_encrypt(ccm, in, out, len))
3525e1051a39Sopenharmony_ci            return -1;
3526e1051a39Sopenharmony_ci        cctx->tag_set = 1;
3527e1051a39Sopenharmony_ci        return len;
3528e1051a39Sopenharmony_ci    } else {
3529e1051a39Sopenharmony_ci        int rv = -1;
3530e1051a39Sopenharmony_ci        if (cctx->str ? !CRYPTO_ccm128_decrypt_ccm64(ccm, in, out, len,
3531e1051a39Sopenharmony_ci                                                     cctx->str) :
3532e1051a39Sopenharmony_ci            !CRYPTO_ccm128_decrypt(ccm, in, out, len)) {
3533e1051a39Sopenharmony_ci            unsigned char tag[16];
3534e1051a39Sopenharmony_ci            if (CRYPTO_ccm128_tag(ccm, tag, cctx->M)) {
3535e1051a39Sopenharmony_ci                if (!CRYPTO_memcmp(tag, EVP_CIPHER_CTX_buf_noconst(ctx),
3536e1051a39Sopenharmony_ci                                   cctx->M))
3537e1051a39Sopenharmony_ci                    rv = len;
3538e1051a39Sopenharmony_ci            }
3539e1051a39Sopenharmony_ci        }
3540e1051a39Sopenharmony_ci        if (rv == -1)
3541e1051a39Sopenharmony_ci            OPENSSL_cleanse(out, len);
3542e1051a39Sopenharmony_ci        cctx->iv_set = 0;
3543e1051a39Sopenharmony_ci        cctx->tag_set = 0;
3544e1051a39Sopenharmony_ci        cctx->len_set = 0;
3545e1051a39Sopenharmony_ci        return rv;
3546e1051a39Sopenharmony_ci    }
3547e1051a39Sopenharmony_ci}
3548e1051a39Sopenharmony_ci
3549e1051a39Sopenharmony_ci#define aes_ccm_cleanup NULL
3550e1051a39Sopenharmony_ci
3551e1051a39Sopenharmony_ciBLOCK_CIPHER_custom(NID_aes, 128, 1, 12, ccm, CCM,
3552e1051a39Sopenharmony_ci                    EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS)
3553e1051a39Sopenharmony_ciBLOCK_CIPHER_custom(NID_aes, 192, 1, 12, ccm, CCM,
3554e1051a39Sopenharmony_ci                    EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS)
3555e1051a39Sopenharmony_ciBLOCK_CIPHER_custom(NID_aes, 256, 1, 12, ccm, CCM,
3556e1051a39Sopenharmony_ci                    EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS)
3557e1051a39Sopenharmony_ci
3558e1051a39Sopenharmony_citypedef struct {
3559e1051a39Sopenharmony_ci    union {
3560e1051a39Sopenharmony_ci        OSSL_UNION_ALIGN;
3561e1051a39Sopenharmony_ci        AES_KEY ks;
3562e1051a39Sopenharmony_ci    } ks;
3563e1051a39Sopenharmony_ci    /* Indicates if IV has been set */
3564e1051a39Sopenharmony_ci    unsigned char *iv;
3565e1051a39Sopenharmony_ci} EVP_AES_WRAP_CTX;
3566e1051a39Sopenharmony_ci
3567e1051a39Sopenharmony_cistatic int aes_wrap_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
3568e1051a39Sopenharmony_ci                             const unsigned char *iv, int enc)
3569e1051a39Sopenharmony_ci{
3570e1051a39Sopenharmony_ci    int len;
3571e1051a39Sopenharmony_ci    EVP_AES_WRAP_CTX *wctx = EVP_C_DATA(EVP_AES_WRAP_CTX,ctx);
3572e1051a39Sopenharmony_ci
3573e1051a39Sopenharmony_ci    if (iv == NULL && key == NULL)
3574e1051a39Sopenharmony_ci        return 1;
3575e1051a39Sopenharmony_ci    if (key != NULL) {
3576e1051a39Sopenharmony_ci        if (EVP_CIPHER_CTX_is_encrypting(ctx))
3577e1051a39Sopenharmony_ci            AES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
3578e1051a39Sopenharmony_ci                                &wctx->ks.ks);
3579e1051a39Sopenharmony_ci        else
3580e1051a39Sopenharmony_ci            AES_set_decrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
3581e1051a39Sopenharmony_ci                                &wctx->ks.ks);
3582e1051a39Sopenharmony_ci        if (iv == NULL)
3583e1051a39Sopenharmony_ci            wctx->iv = NULL;
3584e1051a39Sopenharmony_ci    }
3585e1051a39Sopenharmony_ci    if (iv != NULL) {
3586e1051a39Sopenharmony_ci        if ((len = EVP_CIPHER_CTX_get_iv_length(ctx)) < 0)
3587e1051a39Sopenharmony_ci            return 0;
3588e1051a39Sopenharmony_ci        memcpy(ctx->iv, iv, len);
3589e1051a39Sopenharmony_ci        wctx->iv = ctx->iv;
3590e1051a39Sopenharmony_ci    }
3591e1051a39Sopenharmony_ci    return 1;
3592e1051a39Sopenharmony_ci}
3593e1051a39Sopenharmony_ci
3594e1051a39Sopenharmony_cistatic int aes_wrap_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
3595e1051a39Sopenharmony_ci                           const unsigned char *in, size_t inlen)
3596e1051a39Sopenharmony_ci{
3597e1051a39Sopenharmony_ci    EVP_AES_WRAP_CTX *wctx = EVP_C_DATA(EVP_AES_WRAP_CTX,ctx);
3598e1051a39Sopenharmony_ci    size_t rv;
3599e1051a39Sopenharmony_ci    /* AES wrap with padding has IV length of 4, without padding 8 */
3600e1051a39Sopenharmony_ci    int pad = EVP_CIPHER_CTX_get_iv_length(ctx) == 4;
3601e1051a39Sopenharmony_ci    /* No final operation so always return zero length */
3602e1051a39Sopenharmony_ci    if (!in)
3603e1051a39Sopenharmony_ci        return 0;
3604e1051a39Sopenharmony_ci    /* Input length must always be non-zero */
3605e1051a39Sopenharmony_ci    if (!inlen)
3606e1051a39Sopenharmony_ci        return -1;
3607e1051a39Sopenharmony_ci    /* If decrypting need at least 16 bytes and multiple of 8 */
3608e1051a39Sopenharmony_ci    if (!EVP_CIPHER_CTX_is_encrypting(ctx) && (inlen < 16 || inlen & 0x7))
3609e1051a39Sopenharmony_ci        return -1;
3610e1051a39Sopenharmony_ci    /* If not padding input must be multiple of 8 */
3611e1051a39Sopenharmony_ci    if (!pad && inlen & 0x7)
3612e1051a39Sopenharmony_ci        return -1;
3613e1051a39Sopenharmony_ci    if (ossl_is_partially_overlapping(out, in, inlen)) {
3614e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EVP, EVP_R_PARTIALLY_OVERLAPPING);
3615e1051a39Sopenharmony_ci        return 0;
3616e1051a39Sopenharmony_ci    }
3617e1051a39Sopenharmony_ci    if (!out) {
3618e1051a39Sopenharmony_ci        if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
3619e1051a39Sopenharmony_ci            /* If padding round up to multiple of 8 */
3620e1051a39Sopenharmony_ci            if (pad)
3621e1051a39Sopenharmony_ci                inlen = (inlen + 7) / 8 * 8;
3622e1051a39Sopenharmony_ci            /* 8 byte prefix */
3623e1051a39Sopenharmony_ci            return inlen + 8;
3624e1051a39Sopenharmony_ci        } else {
3625e1051a39Sopenharmony_ci            /*
3626e1051a39Sopenharmony_ci             * If not padding output will be exactly 8 bytes smaller than
3627e1051a39Sopenharmony_ci             * input. If padding it will be at least 8 bytes smaller but we
3628e1051a39Sopenharmony_ci             * don't know how much.
3629e1051a39Sopenharmony_ci             */
3630e1051a39Sopenharmony_ci            return inlen - 8;
3631e1051a39Sopenharmony_ci        }
3632e1051a39Sopenharmony_ci    }
3633e1051a39Sopenharmony_ci    if (pad) {
3634e1051a39Sopenharmony_ci        if (EVP_CIPHER_CTX_is_encrypting(ctx))
3635e1051a39Sopenharmony_ci            rv = CRYPTO_128_wrap_pad(&wctx->ks.ks, wctx->iv,
3636e1051a39Sopenharmony_ci                                     out, in, inlen,
3637e1051a39Sopenharmony_ci                                     (block128_f) AES_encrypt);
3638e1051a39Sopenharmony_ci        else
3639e1051a39Sopenharmony_ci            rv = CRYPTO_128_unwrap_pad(&wctx->ks.ks, wctx->iv,
3640e1051a39Sopenharmony_ci                                       out, in, inlen,
3641e1051a39Sopenharmony_ci                                       (block128_f) AES_decrypt);
3642e1051a39Sopenharmony_ci    } else {
3643e1051a39Sopenharmony_ci        if (EVP_CIPHER_CTX_is_encrypting(ctx))
3644e1051a39Sopenharmony_ci            rv = CRYPTO_128_wrap(&wctx->ks.ks, wctx->iv,
3645e1051a39Sopenharmony_ci                                 out, in, inlen, (block128_f) AES_encrypt);
3646e1051a39Sopenharmony_ci        else
3647e1051a39Sopenharmony_ci            rv = CRYPTO_128_unwrap(&wctx->ks.ks, wctx->iv,
3648e1051a39Sopenharmony_ci                                   out, in, inlen, (block128_f) AES_decrypt);
3649e1051a39Sopenharmony_ci    }
3650e1051a39Sopenharmony_ci    return rv ? (int)rv : -1;
3651e1051a39Sopenharmony_ci}
3652e1051a39Sopenharmony_ci
3653e1051a39Sopenharmony_ci#define WRAP_FLAGS      (EVP_CIPH_WRAP_MODE \
3654e1051a39Sopenharmony_ci                | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \
3655e1051a39Sopenharmony_ci                | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_FLAG_DEFAULT_ASN1)
3656e1051a39Sopenharmony_ci
3657e1051a39Sopenharmony_cistatic const EVP_CIPHER aes_128_wrap = {
3658e1051a39Sopenharmony_ci    NID_id_aes128_wrap,
3659e1051a39Sopenharmony_ci    8, 16, 8, WRAP_FLAGS, EVP_ORIG_GLOBAL,
3660e1051a39Sopenharmony_ci    aes_wrap_init_key, aes_wrap_cipher,
3661e1051a39Sopenharmony_ci    NULL,
3662e1051a39Sopenharmony_ci    sizeof(EVP_AES_WRAP_CTX),
3663e1051a39Sopenharmony_ci    NULL, NULL, NULL, NULL
3664e1051a39Sopenharmony_ci};
3665e1051a39Sopenharmony_ci
3666e1051a39Sopenharmony_ciconst EVP_CIPHER *EVP_aes_128_wrap(void)
3667e1051a39Sopenharmony_ci{
3668e1051a39Sopenharmony_ci    return &aes_128_wrap;
3669e1051a39Sopenharmony_ci}
3670e1051a39Sopenharmony_ci
3671e1051a39Sopenharmony_cistatic const EVP_CIPHER aes_192_wrap = {
3672e1051a39Sopenharmony_ci    NID_id_aes192_wrap,
3673e1051a39Sopenharmony_ci    8, 24, 8, WRAP_FLAGS, EVP_ORIG_GLOBAL,
3674e1051a39Sopenharmony_ci    aes_wrap_init_key, aes_wrap_cipher,
3675e1051a39Sopenharmony_ci    NULL,
3676e1051a39Sopenharmony_ci    sizeof(EVP_AES_WRAP_CTX),
3677e1051a39Sopenharmony_ci    NULL, NULL, NULL, NULL
3678e1051a39Sopenharmony_ci};
3679e1051a39Sopenharmony_ci
3680e1051a39Sopenharmony_ciconst EVP_CIPHER *EVP_aes_192_wrap(void)
3681e1051a39Sopenharmony_ci{
3682e1051a39Sopenharmony_ci    return &aes_192_wrap;
3683e1051a39Sopenharmony_ci}
3684e1051a39Sopenharmony_ci
3685e1051a39Sopenharmony_cistatic const EVP_CIPHER aes_256_wrap = {
3686e1051a39Sopenharmony_ci    NID_id_aes256_wrap,
3687e1051a39Sopenharmony_ci    8, 32, 8, WRAP_FLAGS, EVP_ORIG_GLOBAL,
3688e1051a39Sopenharmony_ci    aes_wrap_init_key, aes_wrap_cipher,
3689e1051a39Sopenharmony_ci    NULL,
3690e1051a39Sopenharmony_ci    sizeof(EVP_AES_WRAP_CTX),
3691e1051a39Sopenharmony_ci    NULL, NULL, NULL, NULL
3692e1051a39Sopenharmony_ci};
3693e1051a39Sopenharmony_ci
3694e1051a39Sopenharmony_ciconst EVP_CIPHER *EVP_aes_256_wrap(void)
3695e1051a39Sopenharmony_ci{
3696e1051a39Sopenharmony_ci    return &aes_256_wrap;
3697e1051a39Sopenharmony_ci}
3698e1051a39Sopenharmony_ci
3699e1051a39Sopenharmony_cistatic const EVP_CIPHER aes_128_wrap_pad = {
3700e1051a39Sopenharmony_ci    NID_id_aes128_wrap_pad,
3701e1051a39Sopenharmony_ci    8, 16, 4, WRAP_FLAGS, EVP_ORIG_GLOBAL,
3702e1051a39Sopenharmony_ci    aes_wrap_init_key, aes_wrap_cipher,
3703e1051a39Sopenharmony_ci    NULL,
3704e1051a39Sopenharmony_ci    sizeof(EVP_AES_WRAP_CTX),
3705e1051a39Sopenharmony_ci    NULL, NULL, NULL, NULL
3706e1051a39Sopenharmony_ci};
3707e1051a39Sopenharmony_ci
3708e1051a39Sopenharmony_ciconst EVP_CIPHER *EVP_aes_128_wrap_pad(void)
3709e1051a39Sopenharmony_ci{
3710e1051a39Sopenharmony_ci    return &aes_128_wrap_pad;
3711e1051a39Sopenharmony_ci}
3712e1051a39Sopenharmony_ci
3713e1051a39Sopenharmony_cistatic const EVP_CIPHER aes_192_wrap_pad = {
3714e1051a39Sopenharmony_ci    NID_id_aes192_wrap_pad,
3715e1051a39Sopenharmony_ci    8, 24, 4, WRAP_FLAGS, EVP_ORIG_GLOBAL,
3716e1051a39Sopenharmony_ci    aes_wrap_init_key, aes_wrap_cipher,
3717e1051a39Sopenharmony_ci    NULL,
3718e1051a39Sopenharmony_ci    sizeof(EVP_AES_WRAP_CTX),
3719e1051a39Sopenharmony_ci    NULL, NULL, NULL, NULL
3720e1051a39Sopenharmony_ci};
3721e1051a39Sopenharmony_ci
3722e1051a39Sopenharmony_ciconst EVP_CIPHER *EVP_aes_192_wrap_pad(void)
3723e1051a39Sopenharmony_ci{
3724e1051a39Sopenharmony_ci    return &aes_192_wrap_pad;
3725e1051a39Sopenharmony_ci}
3726e1051a39Sopenharmony_ci
3727e1051a39Sopenharmony_cistatic const EVP_CIPHER aes_256_wrap_pad = {
3728e1051a39Sopenharmony_ci    NID_id_aes256_wrap_pad,
3729e1051a39Sopenharmony_ci    8, 32, 4, WRAP_FLAGS, EVP_ORIG_GLOBAL,
3730e1051a39Sopenharmony_ci    aes_wrap_init_key, aes_wrap_cipher,
3731e1051a39Sopenharmony_ci    NULL,
3732e1051a39Sopenharmony_ci    sizeof(EVP_AES_WRAP_CTX),
3733e1051a39Sopenharmony_ci    NULL, NULL, NULL, NULL
3734e1051a39Sopenharmony_ci};
3735e1051a39Sopenharmony_ci
3736e1051a39Sopenharmony_ciconst EVP_CIPHER *EVP_aes_256_wrap_pad(void)
3737e1051a39Sopenharmony_ci{
3738e1051a39Sopenharmony_ci    return &aes_256_wrap_pad;
3739e1051a39Sopenharmony_ci}
3740e1051a39Sopenharmony_ci
3741e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_OCB
3742e1051a39Sopenharmony_cistatic int aes_ocb_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
3743e1051a39Sopenharmony_ci{
3744e1051a39Sopenharmony_ci    EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,c);
3745e1051a39Sopenharmony_ci    EVP_CIPHER_CTX *newc;
3746e1051a39Sopenharmony_ci    EVP_AES_OCB_CTX *new_octx;
3747e1051a39Sopenharmony_ci
3748e1051a39Sopenharmony_ci    switch (type) {
3749e1051a39Sopenharmony_ci    case EVP_CTRL_INIT:
3750e1051a39Sopenharmony_ci        octx->key_set = 0;
3751e1051a39Sopenharmony_ci        octx->iv_set = 0;
3752e1051a39Sopenharmony_ci        octx->ivlen = EVP_CIPHER_get_iv_length(c->cipher);
3753e1051a39Sopenharmony_ci        octx->iv = c->iv;
3754e1051a39Sopenharmony_ci        octx->taglen = 16;
3755e1051a39Sopenharmony_ci        octx->data_buf_len = 0;
3756e1051a39Sopenharmony_ci        octx->aad_buf_len = 0;
3757e1051a39Sopenharmony_ci        return 1;
3758e1051a39Sopenharmony_ci
3759e1051a39Sopenharmony_ci    case EVP_CTRL_GET_IVLEN:
3760e1051a39Sopenharmony_ci        *(int *)ptr = octx->ivlen;
3761e1051a39Sopenharmony_ci        return 1;
3762e1051a39Sopenharmony_ci
3763e1051a39Sopenharmony_ci    case EVP_CTRL_AEAD_SET_IVLEN:
3764e1051a39Sopenharmony_ci        /* IV len must be 1 to 15 */
3765e1051a39Sopenharmony_ci        if (arg <= 0 || arg > 15)
3766e1051a39Sopenharmony_ci            return 0;
3767e1051a39Sopenharmony_ci
3768e1051a39Sopenharmony_ci        octx->ivlen = arg;
3769e1051a39Sopenharmony_ci        return 1;
3770e1051a39Sopenharmony_ci
3771e1051a39Sopenharmony_ci    case EVP_CTRL_AEAD_SET_TAG:
3772e1051a39Sopenharmony_ci        if (ptr == NULL) {
3773e1051a39Sopenharmony_ci            /* Tag len must be 0 to 16 */
3774e1051a39Sopenharmony_ci            if (arg < 0 || arg > 16)
3775e1051a39Sopenharmony_ci                return 0;
3776e1051a39Sopenharmony_ci
3777e1051a39Sopenharmony_ci            octx->taglen = arg;
3778e1051a39Sopenharmony_ci            return 1;
3779e1051a39Sopenharmony_ci        }
3780e1051a39Sopenharmony_ci        if (arg != octx->taglen || EVP_CIPHER_CTX_is_encrypting(c))
3781e1051a39Sopenharmony_ci            return 0;
3782e1051a39Sopenharmony_ci        memcpy(octx->tag, ptr, arg);
3783e1051a39Sopenharmony_ci        return 1;
3784e1051a39Sopenharmony_ci
3785e1051a39Sopenharmony_ci    case EVP_CTRL_AEAD_GET_TAG:
3786e1051a39Sopenharmony_ci        if (arg != octx->taglen || !EVP_CIPHER_CTX_is_encrypting(c))
3787e1051a39Sopenharmony_ci            return 0;
3788e1051a39Sopenharmony_ci
3789e1051a39Sopenharmony_ci        memcpy(ptr, octx->tag, arg);
3790e1051a39Sopenharmony_ci        return 1;
3791e1051a39Sopenharmony_ci
3792e1051a39Sopenharmony_ci    case EVP_CTRL_COPY:
3793e1051a39Sopenharmony_ci        newc = (EVP_CIPHER_CTX *)ptr;
3794e1051a39Sopenharmony_ci        new_octx = EVP_C_DATA(EVP_AES_OCB_CTX,newc);
3795e1051a39Sopenharmony_ci        return CRYPTO_ocb128_copy_ctx(&new_octx->ocb, &octx->ocb,
3796e1051a39Sopenharmony_ci                                      &new_octx->ksenc.ks,
3797e1051a39Sopenharmony_ci                                      &new_octx->ksdec.ks);
3798e1051a39Sopenharmony_ci
3799e1051a39Sopenharmony_ci    default:
3800e1051a39Sopenharmony_ci        return -1;
3801e1051a39Sopenharmony_ci
3802e1051a39Sopenharmony_ci    }
3803e1051a39Sopenharmony_ci}
3804e1051a39Sopenharmony_ci
3805e1051a39Sopenharmony_cistatic int aes_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
3806e1051a39Sopenharmony_ci                            const unsigned char *iv, int enc)
3807e1051a39Sopenharmony_ci{
3808e1051a39Sopenharmony_ci    EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,ctx);
3809e1051a39Sopenharmony_ci    if (!iv && !key)
3810e1051a39Sopenharmony_ci        return 1;
3811e1051a39Sopenharmony_ci    if (key) {
3812e1051a39Sopenharmony_ci        do {
3813e1051a39Sopenharmony_ci            /*
3814e1051a39Sopenharmony_ci             * We set both the encrypt and decrypt key here because decrypt
3815e1051a39Sopenharmony_ci             * needs both. We could possibly optimise to remove setting the
3816e1051a39Sopenharmony_ci             * decrypt for an encryption operation.
3817e1051a39Sopenharmony_ci             */
3818e1051a39Sopenharmony_ci# ifdef HWAES_CAPABLE
3819e1051a39Sopenharmony_ci            if (HWAES_CAPABLE) {
3820e1051a39Sopenharmony_ci                HWAES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
3821e1051a39Sopenharmony_ci                                      &octx->ksenc.ks);
3822e1051a39Sopenharmony_ci                HWAES_set_decrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
3823e1051a39Sopenharmony_ci                                      &octx->ksdec.ks);
3824e1051a39Sopenharmony_ci                if (!CRYPTO_ocb128_init(&octx->ocb,
3825e1051a39Sopenharmony_ci                                        &octx->ksenc.ks, &octx->ksdec.ks,
3826e1051a39Sopenharmony_ci                                        (block128_f) HWAES_encrypt,
3827e1051a39Sopenharmony_ci                                        (block128_f) HWAES_decrypt,
3828e1051a39Sopenharmony_ci                                        enc ? HWAES_ocb_encrypt
3829e1051a39Sopenharmony_ci                                            : HWAES_ocb_decrypt))
3830e1051a39Sopenharmony_ci                    return 0;
3831e1051a39Sopenharmony_ci                break;
3832e1051a39Sopenharmony_ci            }
3833e1051a39Sopenharmony_ci# endif
3834e1051a39Sopenharmony_ci# ifdef VPAES_CAPABLE
3835e1051a39Sopenharmony_ci            if (VPAES_CAPABLE) {
3836e1051a39Sopenharmony_ci                vpaes_set_encrypt_key(key,
3837e1051a39Sopenharmony_ci                                      EVP_CIPHER_CTX_get_key_length(ctx) * 8,
3838e1051a39Sopenharmony_ci                                      &octx->ksenc.ks);
3839e1051a39Sopenharmony_ci                vpaes_set_decrypt_key(key,
3840e1051a39Sopenharmony_ci                                      EVP_CIPHER_CTX_get_key_length(ctx) * 8,
3841e1051a39Sopenharmony_ci                                      &octx->ksdec.ks);
3842e1051a39Sopenharmony_ci                if (!CRYPTO_ocb128_init(&octx->ocb,
3843e1051a39Sopenharmony_ci                                        &octx->ksenc.ks, &octx->ksdec.ks,
3844e1051a39Sopenharmony_ci                                        (block128_f) vpaes_encrypt,
3845e1051a39Sopenharmony_ci                                        (block128_f) vpaes_decrypt,
3846e1051a39Sopenharmony_ci                                        NULL))
3847e1051a39Sopenharmony_ci                    return 0;
3848e1051a39Sopenharmony_ci                break;
3849e1051a39Sopenharmony_ci            }
3850e1051a39Sopenharmony_ci# endif
3851e1051a39Sopenharmony_ci            AES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
3852e1051a39Sopenharmony_ci                                &octx->ksenc.ks);
3853e1051a39Sopenharmony_ci            AES_set_decrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
3854e1051a39Sopenharmony_ci                                &octx->ksdec.ks);
3855e1051a39Sopenharmony_ci            if (!CRYPTO_ocb128_init(&octx->ocb,
3856e1051a39Sopenharmony_ci                                    &octx->ksenc.ks, &octx->ksdec.ks,
3857e1051a39Sopenharmony_ci                                    (block128_f) AES_encrypt,
3858e1051a39Sopenharmony_ci                                    (block128_f) AES_decrypt,
3859e1051a39Sopenharmony_ci                                    NULL))
3860e1051a39Sopenharmony_ci                return 0;
3861e1051a39Sopenharmony_ci        }
3862e1051a39Sopenharmony_ci        while (0);
3863e1051a39Sopenharmony_ci
3864e1051a39Sopenharmony_ci        /*
3865e1051a39Sopenharmony_ci         * If we have an iv we can set it directly, otherwise use saved IV.
3866e1051a39Sopenharmony_ci         */
3867e1051a39Sopenharmony_ci        if (iv == NULL && octx->iv_set)
3868e1051a39Sopenharmony_ci            iv = octx->iv;
3869e1051a39Sopenharmony_ci        if (iv) {
3870e1051a39Sopenharmony_ci            if (CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen)
3871e1051a39Sopenharmony_ci                != 1)
3872e1051a39Sopenharmony_ci                return 0;
3873e1051a39Sopenharmony_ci            octx->iv_set = 1;
3874e1051a39Sopenharmony_ci        }
3875e1051a39Sopenharmony_ci        octx->key_set = 1;
3876e1051a39Sopenharmony_ci    } else {
3877e1051a39Sopenharmony_ci        /* If key set use IV, otherwise copy */
3878e1051a39Sopenharmony_ci        if (octx->key_set)
3879e1051a39Sopenharmony_ci            CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen);
3880e1051a39Sopenharmony_ci        else
3881e1051a39Sopenharmony_ci            memcpy(octx->iv, iv, octx->ivlen);
3882e1051a39Sopenharmony_ci        octx->iv_set = 1;
3883e1051a39Sopenharmony_ci    }
3884e1051a39Sopenharmony_ci    return 1;
3885e1051a39Sopenharmony_ci}
3886e1051a39Sopenharmony_ci
3887e1051a39Sopenharmony_cistatic int aes_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
3888e1051a39Sopenharmony_ci                          const unsigned char *in, size_t len)
3889e1051a39Sopenharmony_ci{
3890e1051a39Sopenharmony_ci    unsigned char *buf;
3891e1051a39Sopenharmony_ci    int *buf_len;
3892e1051a39Sopenharmony_ci    int written_len = 0;
3893e1051a39Sopenharmony_ci    size_t trailing_len;
3894e1051a39Sopenharmony_ci    EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,ctx);
3895e1051a39Sopenharmony_ci
3896e1051a39Sopenharmony_ci    /* If IV or Key not set then return error */
3897e1051a39Sopenharmony_ci    if (!octx->iv_set)
3898e1051a39Sopenharmony_ci        return -1;
3899e1051a39Sopenharmony_ci
3900e1051a39Sopenharmony_ci    if (!octx->key_set)
3901e1051a39Sopenharmony_ci        return -1;
3902e1051a39Sopenharmony_ci
3903e1051a39Sopenharmony_ci    if (in != NULL) {
3904e1051a39Sopenharmony_ci        /*
3905e1051a39Sopenharmony_ci         * Need to ensure we are only passing full blocks to low level OCB
3906e1051a39Sopenharmony_ci         * routines. We do it here rather than in EVP_EncryptUpdate/
3907e1051a39Sopenharmony_ci         * EVP_DecryptUpdate because we need to pass full blocks of AAD too
3908e1051a39Sopenharmony_ci         * and those routines don't support that
3909e1051a39Sopenharmony_ci         */
3910e1051a39Sopenharmony_ci
3911e1051a39Sopenharmony_ci        /* Are we dealing with AAD or normal data here? */
3912e1051a39Sopenharmony_ci        if (out == NULL) {
3913e1051a39Sopenharmony_ci            buf = octx->aad_buf;
3914e1051a39Sopenharmony_ci            buf_len = &(octx->aad_buf_len);
3915e1051a39Sopenharmony_ci        } else {
3916e1051a39Sopenharmony_ci            buf = octx->data_buf;
3917e1051a39Sopenharmony_ci            buf_len = &(octx->data_buf_len);
3918e1051a39Sopenharmony_ci
3919e1051a39Sopenharmony_ci            if (ossl_is_partially_overlapping(out + *buf_len, in, len)) {
3920e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_EVP, EVP_R_PARTIALLY_OVERLAPPING);
3921e1051a39Sopenharmony_ci                return 0;
3922e1051a39Sopenharmony_ci            }
3923e1051a39Sopenharmony_ci        }
3924e1051a39Sopenharmony_ci
3925e1051a39Sopenharmony_ci        /*
3926e1051a39Sopenharmony_ci         * If we've got a partially filled buffer from a previous call then
3927e1051a39Sopenharmony_ci         * use that data first
3928e1051a39Sopenharmony_ci         */
3929e1051a39Sopenharmony_ci        if (*buf_len > 0) {
3930e1051a39Sopenharmony_ci            unsigned int remaining;
3931e1051a39Sopenharmony_ci
3932e1051a39Sopenharmony_ci            remaining = AES_BLOCK_SIZE - (*buf_len);
3933e1051a39Sopenharmony_ci            if (remaining > len) {
3934e1051a39Sopenharmony_ci                memcpy(buf + (*buf_len), in, len);
3935e1051a39Sopenharmony_ci                *(buf_len) += len;
3936e1051a39Sopenharmony_ci                return 0;
3937e1051a39Sopenharmony_ci            }
3938e1051a39Sopenharmony_ci            memcpy(buf + (*buf_len), in, remaining);
3939e1051a39Sopenharmony_ci
3940e1051a39Sopenharmony_ci            /*
3941e1051a39Sopenharmony_ci             * If we get here we've filled the buffer, so process it
3942e1051a39Sopenharmony_ci             */
3943e1051a39Sopenharmony_ci            len -= remaining;
3944e1051a39Sopenharmony_ci            in += remaining;
3945e1051a39Sopenharmony_ci            if (out == NULL) {
3946e1051a39Sopenharmony_ci                if (!CRYPTO_ocb128_aad(&octx->ocb, buf, AES_BLOCK_SIZE))
3947e1051a39Sopenharmony_ci                    return -1;
3948e1051a39Sopenharmony_ci            } else if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
3949e1051a39Sopenharmony_ci                if (!CRYPTO_ocb128_encrypt(&octx->ocb, buf, out,
3950e1051a39Sopenharmony_ci                                           AES_BLOCK_SIZE))
3951e1051a39Sopenharmony_ci                    return -1;
3952e1051a39Sopenharmony_ci            } else {
3953e1051a39Sopenharmony_ci                if (!CRYPTO_ocb128_decrypt(&octx->ocb, buf, out,
3954e1051a39Sopenharmony_ci                                           AES_BLOCK_SIZE))
3955e1051a39Sopenharmony_ci                    return -1;
3956e1051a39Sopenharmony_ci            }
3957e1051a39Sopenharmony_ci            written_len = AES_BLOCK_SIZE;
3958e1051a39Sopenharmony_ci            *buf_len = 0;
3959e1051a39Sopenharmony_ci            if (out != NULL)
3960e1051a39Sopenharmony_ci                out += AES_BLOCK_SIZE;
3961e1051a39Sopenharmony_ci        }
3962e1051a39Sopenharmony_ci
3963e1051a39Sopenharmony_ci        /* Do we have a partial block to handle at the end? */
3964e1051a39Sopenharmony_ci        trailing_len = len % AES_BLOCK_SIZE;
3965e1051a39Sopenharmony_ci
3966e1051a39Sopenharmony_ci        /*
3967e1051a39Sopenharmony_ci         * If we've got some full blocks to handle, then process these first
3968e1051a39Sopenharmony_ci         */
3969e1051a39Sopenharmony_ci        if (len != trailing_len) {
3970e1051a39Sopenharmony_ci            if (out == NULL) {
3971e1051a39Sopenharmony_ci                if (!CRYPTO_ocb128_aad(&octx->ocb, in, len - trailing_len))
3972e1051a39Sopenharmony_ci                    return -1;
3973e1051a39Sopenharmony_ci            } else if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
3974e1051a39Sopenharmony_ci                if (!CRYPTO_ocb128_encrypt
3975e1051a39Sopenharmony_ci                    (&octx->ocb, in, out, len - trailing_len))
3976e1051a39Sopenharmony_ci                    return -1;
3977e1051a39Sopenharmony_ci            } else {
3978e1051a39Sopenharmony_ci                if (!CRYPTO_ocb128_decrypt
3979e1051a39Sopenharmony_ci                    (&octx->ocb, in, out, len - trailing_len))
3980e1051a39Sopenharmony_ci                    return -1;
3981e1051a39Sopenharmony_ci            }
3982e1051a39Sopenharmony_ci            written_len += len - trailing_len;
3983e1051a39Sopenharmony_ci            in += len - trailing_len;
3984e1051a39Sopenharmony_ci        }
3985e1051a39Sopenharmony_ci
3986e1051a39Sopenharmony_ci        /* Handle any trailing partial block */
3987e1051a39Sopenharmony_ci        if (trailing_len > 0) {
3988e1051a39Sopenharmony_ci            memcpy(buf, in, trailing_len);
3989e1051a39Sopenharmony_ci            *buf_len = trailing_len;
3990e1051a39Sopenharmony_ci        }
3991e1051a39Sopenharmony_ci
3992e1051a39Sopenharmony_ci        return written_len;
3993e1051a39Sopenharmony_ci    } else {
3994e1051a39Sopenharmony_ci        /*
3995e1051a39Sopenharmony_ci         * First of all empty the buffer of any partial block that we might
3996e1051a39Sopenharmony_ci         * have been provided - both for data and AAD
3997e1051a39Sopenharmony_ci         */
3998e1051a39Sopenharmony_ci        if (octx->data_buf_len > 0) {
3999e1051a39Sopenharmony_ci            if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
4000e1051a39Sopenharmony_ci                if (!CRYPTO_ocb128_encrypt(&octx->ocb, octx->data_buf, out,
4001e1051a39Sopenharmony_ci                                           octx->data_buf_len))
4002e1051a39Sopenharmony_ci                    return -1;
4003e1051a39Sopenharmony_ci            } else {
4004e1051a39Sopenharmony_ci                if (!CRYPTO_ocb128_decrypt(&octx->ocb, octx->data_buf, out,
4005e1051a39Sopenharmony_ci                                           octx->data_buf_len))
4006e1051a39Sopenharmony_ci                    return -1;
4007e1051a39Sopenharmony_ci            }
4008e1051a39Sopenharmony_ci            written_len = octx->data_buf_len;
4009e1051a39Sopenharmony_ci            octx->data_buf_len = 0;
4010e1051a39Sopenharmony_ci        }
4011e1051a39Sopenharmony_ci        if (octx->aad_buf_len > 0) {
4012e1051a39Sopenharmony_ci            if (!CRYPTO_ocb128_aad
4013e1051a39Sopenharmony_ci                (&octx->ocb, octx->aad_buf, octx->aad_buf_len))
4014e1051a39Sopenharmony_ci                return -1;
4015e1051a39Sopenharmony_ci            octx->aad_buf_len = 0;
4016e1051a39Sopenharmony_ci        }
4017e1051a39Sopenharmony_ci        /* If decrypting then verify */
4018e1051a39Sopenharmony_ci        if (!EVP_CIPHER_CTX_is_encrypting(ctx)) {
4019e1051a39Sopenharmony_ci            if (octx->taglen < 0)
4020e1051a39Sopenharmony_ci                return -1;
4021e1051a39Sopenharmony_ci            if (CRYPTO_ocb128_finish(&octx->ocb,
4022e1051a39Sopenharmony_ci                                     octx->tag, octx->taglen) != 0)
4023e1051a39Sopenharmony_ci                return -1;
4024e1051a39Sopenharmony_ci            octx->iv_set = 0;
4025e1051a39Sopenharmony_ci            return written_len;
4026e1051a39Sopenharmony_ci        }
4027e1051a39Sopenharmony_ci        /* If encrypting then just get the tag */
4028e1051a39Sopenharmony_ci        if (CRYPTO_ocb128_tag(&octx->ocb, octx->tag, 16) != 1)
4029e1051a39Sopenharmony_ci            return -1;
4030e1051a39Sopenharmony_ci        /* Don't reuse the IV */
4031e1051a39Sopenharmony_ci        octx->iv_set = 0;
4032e1051a39Sopenharmony_ci        return written_len;
4033e1051a39Sopenharmony_ci    }
4034e1051a39Sopenharmony_ci}
4035e1051a39Sopenharmony_ci
4036e1051a39Sopenharmony_cistatic int aes_ocb_cleanup(EVP_CIPHER_CTX *c)
4037e1051a39Sopenharmony_ci{
4038e1051a39Sopenharmony_ci    EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,c);
4039e1051a39Sopenharmony_ci    CRYPTO_ocb128_cleanup(&octx->ocb);
4040e1051a39Sopenharmony_ci    return 1;
4041e1051a39Sopenharmony_ci}
4042e1051a39Sopenharmony_ci
4043e1051a39Sopenharmony_ciBLOCK_CIPHER_custom(NID_aes, 128, 16, 12, ocb, OCB,
4044e1051a39Sopenharmony_ci                    EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS)
4045e1051a39Sopenharmony_ciBLOCK_CIPHER_custom(NID_aes, 192, 16, 12, ocb, OCB,
4046e1051a39Sopenharmony_ci                    EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS)
4047e1051a39Sopenharmony_ciBLOCK_CIPHER_custom(NID_aes, 256, 16, 12, ocb, OCB,
4048e1051a39Sopenharmony_ci                    EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS)
4049e1051a39Sopenharmony_ci#endif                         /* OPENSSL_NO_OCB */
4050