xref: /freebsd/crypto/openssl/crypto/evp/e_aes.c (revision e0c4386e7e71d93b0edc0c8fa156263fc4a8b0b6)
1e71b7053SJung-uk Kim /*
2*e0c4386eSCy Schubert  * Copyright 2001-2024 The OpenSSL Project Authors. All Rights Reserved.
35c87c606SMark Murray  *
4b077aed3SPierre Pronchery  * Licensed under the Apache License 2.0 (the "License").  You may not use
5e71b7053SJung-uk Kim  * this file except in compliance with the License.  You can obtain a copy
6e71b7053SJung-uk Kim  * in the file LICENSE in the source distribution or at
7e71b7053SJung-uk Kim  * https://www.openssl.org/source/license.html
85c87c606SMark Murray  */
95c87c606SMark Murray 
10b077aed3SPierre Pronchery /*
11b077aed3SPierre Pronchery  * This file uses the low level AES functions (which are deprecated for
12b077aed3SPierre Pronchery  * non-internal use) in order to implement the EVP AES ciphers.
13b077aed3SPierre Pronchery  */
14b077aed3SPierre Pronchery #include "internal/deprecated.h"
15b077aed3SPierre Pronchery 
16b077aed3SPierre Pronchery #include <string.h>
17b077aed3SPierre Pronchery #include <assert.h>
183b4e3dcbSSimon L. B. Nielsen #include <openssl/opensslconf.h>
19ed6b93beSJung-uk Kim #include <openssl/crypto.h>
205c87c606SMark Murray #include <openssl/evp.h>
215c87c606SMark Murray #include <openssl/err.h>
225c87c606SMark Murray #include <openssl/aes.h>
231f13597dSJung-uk Kim #include <openssl/rand.h>
24b077aed3SPierre Pronchery #include <openssl/cmac.h>
25b077aed3SPierre Pronchery #include "crypto/evp.h"
26b077aed3SPierre Pronchery #include "internal/cryptlib.h"
27b077aed3SPierre Pronchery #include "crypto/modes.h"
28b077aed3SPierre Pronchery #include "crypto/siv.h"
29b077aed3SPierre Pronchery #include "crypto/aes_platform.h"
3017f01e99SJung-uk Kim #include "evp_local.h"
317bded2dbSJung-uk Kim 
326f9291ceSJung-uk Kim typedef struct {
337bded2dbSJung-uk Kim     union {
34b077aed3SPierre Pronchery         OSSL_UNION_ALIGN;
355c87c606SMark Murray         AES_KEY ks;
367bded2dbSJung-uk Kim     } ks;
371f13597dSJung-uk Kim     block128_f block;
381f13597dSJung-uk Kim     union {
391f13597dSJung-uk Kim         cbc128_f cbc;
401f13597dSJung-uk Kim         ctr128_f ctr;
411f13597dSJung-uk Kim     } stream;
425c87c606SMark Murray } EVP_AES_KEY;
435c87c606SMark Murray 
446f9291ceSJung-uk Kim typedef struct {
457bded2dbSJung-uk Kim     union {
46b077aed3SPierre Pronchery         OSSL_UNION_ALIGN;
477bded2dbSJung-uk Kim         AES_KEY ks;
487bded2dbSJung-uk Kim     } ks;                       /* AES key schedule to use */
491f13597dSJung-uk Kim     int key_set;                /* Set if key initialised */
501f13597dSJung-uk Kim     int iv_set;                 /* Set if an iv is set */
511f13597dSJung-uk Kim     GCM128_CONTEXT gcm;
521f13597dSJung-uk Kim     unsigned char *iv;          /* Temporary IV store */
531f13597dSJung-uk Kim     int ivlen;                  /* IV length */
541f13597dSJung-uk Kim     int taglen;
551f13597dSJung-uk Kim     int iv_gen;                 /* It is OK to generate IVs */
56b077aed3SPierre Pronchery     int iv_gen_rand;            /* No IV was specified, so generate a rand IV */
571f13597dSJung-uk Kim     int tls_aad_len;            /* TLS AAD length */
58b077aed3SPierre Pronchery     uint64_t tls_enc_records;   /* Number of TLS records encrypted */
591f13597dSJung-uk Kim     ctr128_f ctr;
601f13597dSJung-uk Kim } EVP_AES_GCM_CTX;
615c87c606SMark Murray 
626f9291ceSJung-uk Kim typedef struct {
637bded2dbSJung-uk Kim     union {
64b077aed3SPierre Pronchery         OSSL_UNION_ALIGN;
657bded2dbSJung-uk Kim         AES_KEY ks;
667bded2dbSJung-uk Kim     } ks1, ks2;                 /* AES key schedules to use */
671f13597dSJung-uk Kim     XTS128_CONTEXT xts;
681f13597dSJung-uk Kim     void (*stream) (const unsigned char *in,
691f13597dSJung-uk Kim                     unsigned char *out, size_t length,
701f13597dSJung-uk Kim                     const AES_KEY *key1, const AES_KEY *key2,
711f13597dSJung-uk Kim                     const unsigned char iv[16]);
721f13597dSJung-uk Kim } EVP_AES_XTS_CTX;
735c87c606SMark Murray 
74b077aed3SPierre Pronchery #ifdef FIPS_MODULE
75b077aed3SPierre Pronchery static const int allow_insecure_decrypt = 0;
76b077aed3SPierre Pronchery #else
77b077aed3SPierre Pronchery static const int allow_insecure_decrypt = 1;
78b077aed3SPierre Pronchery #endif
79b077aed3SPierre Pronchery 
806f9291ceSJung-uk Kim typedef struct {
817bded2dbSJung-uk Kim     union {
82b077aed3SPierre Pronchery         OSSL_UNION_ALIGN;
837bded2dbSJung-uk Kim         AES_KEY ks;
847bded2dbSJung-uk Kim     } ks;                       /* AES key schedule to use */
851f13597dSJung-uk Kim     int key_set;                /* Set if key initialised */
861f13597dSJung-uk Kim     int iv_set;                 /* Set if an iv is set */
871f13597dSJung-uk Kim     int tag_set;                /* Set if tag is valid */
881f13597dSJung-uk Kim     int len_set;                /* Set if message length set */
891f13597dSJung-uk Kim     int L, M;                   /* L and M parameters from RFC3610 */
90e71b7053SJung-uk Kim     int tls_aad_len;            /* TLS AAD length */
911f13597dSJung-uk Kim     CCM128_CONTEXT ccm;
921f13597dSJung-uk Kim     ccm128_f str;
931f13597dSJung-uk Kim } EVP_AES_CCM_CTX;
946be8ae07SJacques Vidrine 
95e71b7053SJung-uk Kim #ifndef OPENSSL_NO_OCB
96e71b7053SJung-uk Kim typedef struct {
97e71b7053SJung-uk Kim     union {
98b077aed3SPierre Pronchery         OSSL_UNION_ALIGN;
99e71b7053SJung-uk Kim         AES_KEY ks;
100e71b7053SJung-uk Kim     } ksenc;                    /* AES key schedule to use for encryption */
101e71b7053SJung-uk Kim     union {
102b077aed3SPierre Pronchery         OSSL_UNION_ALIGN;
103e71b7053SJung-uk Kim         AES_KEY ks;
104e71b7053SJung-uk Kim     } ksdec;                    /* AES key schedule to use for decryption */
105e71b7053SJung-uk Kim     int key_set;                /* Set if key initialised */
106e71b7053SJung-uk Kim     int iv_set;                 /* Set if an iv is set */
107e71b7053SJung-uk Kim     OCB128_CONTEXT ocb;
108e71b7053SJung-uk Kim     unsigned char *iv;          /* Temporary IV store */
109e71b7053SJung-uk Kim     unsigned char tag[16];
110e71b7053SJung-uk Kim     unsigned char data_buf[16]; /* Store partial data blocks */
111e71b7053SJung-uk Kim     unsigned char aad_buf[16];  /* Store partial AAD blocks */
112e71b7053SJung-uk Kim     int data_buf_len;
113e71b7053SJung-uk Kim     int aad_buf_len;
114e71b7053SJung-uk Kim     int ivlen;                  /* IV length */
115e71b7053SJung-uk Kim     int taglen;
116e71b7053SJung-uk Kim } EVP_AES_OCB_CTX;
117e71b7053SJung-uk Kim #endif
118e71b7053SJung-uk Kim 
1191f13597dSJung-uk Kim #define MAXBITCHUNK     ((size_t)1<<(sizeof(size_t)*8-4))
1206be8ae07SJacques Vidrine 
121e71b7053SJung-uk Kim /* increment counter (64-bit int) by 1 */
ctr64_inc(unsigned char * counter)122e71b7053SJung-uk Kim static void ctr64_inc(unsigned char *counter)
123e71b7053SJung-uk Kim {
124e71b7053SJung-uk Kim     int n = 8;
125e71b7053SJung-uk Kim     unsigned char c;
126e71b7053SJung-uk Kim 
127e71b7053SJung-uk Kim     do {
128e71b7053SJung-uk Kim         --n;
129e71b7053SJung-uk Kim         c = counter[n];
130e71b7053SJung-uk Kim         ++c;
131e71b7053SJung-uk Kim         counter[n] = c;
132e71b7053SJung-uk Kim         if (c)
133e71b7053SJung-uk Kim             return;
134e71b7053SJung-uk Kim     } while (n);
135e71b7053SJung-uk Kim }
136e71b7053SJung-uk Kim 
137b077aed3SPierre Pronchery #if defined(AESNI_CAPABLE)
1387bded2dbSJung-uk Kim # if defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)
1397bded2dbSJung-uk Kim #  define AES_GCM_ASM2(gctx)      (gctx->gcm.block==(block128_f)aesni_encrypt && \
1407bded2dbSJung-uk Kim                                  gctx->gcm.ghash==gcm_ghash_avx)
1417bded2dbSJung-uk Kim #  undef AES_GCM_ASM2          /* minor size optimization */
1427bded2dbSJung-uk Kim # endif
1437bded2dbSJung-uk Kim 
aesni_init_key(EVP_CIPHER_CTX * ctx,const unsigned char * key,const unsigned char * iv,int enc)1441f13597dSJung-uk Kim static int aesni_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
1451f13597dSJung-uk Kim                           const unsigned char *iv, int enc)
1461f13597dSJung-uk Kim {
1471f13597dSJung-uk Kim     int ret, mode;
148e71b7053SJung-uk Kim     EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
1491f13597dSJung-uk Kim 
150b077aed3SPierre Pronchery     mode = EVP_CIPHER_CTX_get_mode(ctx);
1511f13597dSJung-uk Kim     if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE)
1526f9291ceSJung-uk Kim         && !enc) {
153b077aed3SPierre Pronchery         ret = aesni_set_decrypt_key(key,
154b077aed3SPierre Pronchery                                     EVP_CIPHER_CTX_get_key_length(ctx) * 8,
155e71b7053SJung-uk Kim                                     &dat->ks.ks);
1561f13597dSJung-uk Kim         dat->block = (block128_f) aesni_decrypt;
1571f13597dSJung-uk Kim         dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
1586f9291ceSJung-uk Kim             (cbc128_f) aesni_cbc_encrypt : NULL;
1596f9291ceSJung-uk Kim     } else {
160b077aed3SPierre Pronchery         ret = aesni_set_encrypt_key(key,
161b077aed3SPierre Pronchery                                     EVP_CIPHER_CTX_get_key_length(ctx) * 8,
162e71b7053SJung-uk Kim                                     &dat->ks.ks);
1631f13597dSJung-uk Kim         dat->block = (block128_f) aesni_encrypt;
1641f13597dSJung-uk Kim         if (mode == EVP_CIPH_CBC_MODE)
1651f13597dSJung-uk Kim             dat->stream.cbc = (cbc128_f) aesni_cbc_encrypt;
1661f13597dSJung-uk Kim         else if (mode == EVP_CIPH_CTR_MODE)
1671f13597dSJung-uk Kim             dat->stream.ctr = (ctr128_f) aesni_ctr32_encrypt_blocks;
1681f13597dSJung-uk Kim         else
1691f13597dSJung-uk Kim             dat->stream.cbc = NULL;
1701f13597dSJung-uk Kim     }
1711f13597dSJung-uk Kim 
1726f9291ceSJung-uk Kim     if (ret < 0) {
173b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, EVP_R_AES_KEY_SETUP_FAILED);
1741f13597dSJung-uk Kim         return 0;
1751f13597dSJung-uk Kim     }
1761f13597dSJung-uk Kim 
1771f13597dSJung-uk Kim     return 1;
1781f13597dSJung-uk Kim }
1791f13597dSJung-uk Kim 
aesni_cbc_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t len)1801f13597dSJung-uk Kim static int aesni_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
1811f13597dSJung-uk Kim                             const unsigned char *in, size_t len)
1821f13597dSJung-uk Kim {
183e71b7053SJung-uk Kim     aesni_cbc_encrypt(in, out, len, &EVP_C_DATA(EVP_AES_KEY,ctx)->ks.ks,
184b077aed3SPierre Pronchery                       ctx->iv, EVP_CIPHER_CTX_is_encrypting(ctx));
1851f13597dSJung-uk Kim 
1861f13597dSJung-uk Kim     return 1;
1871f13597dSJung-uk Kim }
1881f13597dSJung-uk Kim 
aesni_ecb_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t len)1891f13597dSJung-uk Kim static int aesni_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
1901f13597dSJung-uk Kim                             const unsigned char *in, size_t len)
1911f13597dSJung-uk Kim {
192b077aed3SPierre Pronchery     size_t bl = EVP_CIPHER_CTX_get_block_size(ctx);
1931f13597dSJung-uk Kim 
1946f9291ceSJung-uk Kim     if (len < bl)
1956f9291ceSJung-uk Kim         return 1;
1961f13597dSJung-uk Kim 
197e71b7053SJung-uk Kim     aesni_ecb_encrypt(in, out, len, &EVP_C_DATA(EVP_AES_KEY,ctx)->ks.ks,
198b077aed3SPierre Pronchery                       EVP_CIPHER_CTX_is_encrypting(ctx));
1991f13597dSJung-uk Kim 
2001f13597dSJung-uk Kim     return 1;
2011f13597dSJung-uk Kim }
2021f13597dSJung-uk Kim 
2031f13597dSJung-uk Kim # define aesni_ofb_cipher aes_ofb_cipher
2041f13597dSJung-uk Kim static int aesni_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
2051f13597dSJung-uk Kim                             const unsigned char *in, size_t len);
2061f13597dSJung-uk Kim 
2071f13597dSJung-uk Kim # define aesni_cfb_cipher aes_cfb_cipher
2081f13597dSJung-uk Kim static int aesni_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
2091f13597dSJung-uk Kim                             const unsigned char *in, size_t len);
2101f13597dSJung-uk Kim 
2111f13597dSJung-uk Kim # define aesni_cfb8_cipher aes_cfb8_cipher
2121f13597dSJung-uk Kim static int aesni_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
2131f13597dSJung-uk Kim                              const unsigned char *in, size_t len);
2141f13597dSJung-uk Kim 
2151f13597dSJung-uk Kim # define aesni_cfb1_cipher aes_cfb1_cipher
2161f13597dSJung-uk Kim static int aesni_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
2171f13597dSJung-uk Kim                              const unsigned char *in, size_t len);
2181f13597dSJung-uk Kim 
2191f13597dSJung-uk Kim # define aesni_ctr_cipher aes_ctr_cipher
2201f13597dSJung-uk Kim static int aesni_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
2211f13597dSJung-uk Kim                             const unsigned char *in, size_t len);
2221f13597dSJung-uk Kim 
aesni_gcm_init_key(EVP_CIPHER_CTX * ctx,const unsigned char * key,const unsigned char * iv,int enc)2231f13597dSJung-uk Kim static int aesni_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
2241f13597dSJung-uk Kim                               const unsigned char *iv, int enc)
2251f13597dSJung-uk Kim {
226e71b7053SJung-uk Kim     EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx);
2271f13597dSJung-uk Kim     if (!iv && !key)
2281f13597dSJung-uk Kim         return 1;
2296f9291ceSJung-uk Kim     if (key) {
230b077aed3SPierre Pronchery         aesni_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
231e71b7053SJung-uk Kim                               &gctx->ks.ks);
2326f9291ceSJung-uk Kim         CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, (block128_f) aesni_encrypt);
2331f13597dSJung-uk Kim         gctx->ctr = (ctr128_f) aesni_ctr32_encrypt_blocks;
2346f9291ceSJung-uk Kim         /*
2356f9291ceSJung-uk Kim          * If we have an iv can set it directly, otherwise use saved IV.
2361f13597dSJung-uk Kim          */
2371f13597dSJung-uk Kim         if (iv == NULL && gctx->iv_set)
2381f13597dSJung-uk Kim             iv = gctx->iv;
2396f9291ceSJung-uk Kim         if (iv) {
2401f13597dSJung-uk Kim             CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen);
2411f13597dSJung-uk Kim             gctx->iv_set = 1;
2421f13597dSJung-uk Kim         }
2431f13597dSJung-uk Kim         gctx->key_set = 1;
2446f9291ceSJung-uk Kim     } else {
2451f13597dSJung-uk Kim         /* If key set use IV, otherwise copy */
2461f13597dSJung-uk Kim         if (gctx->key_set)
2471f13597dSJung-uk Kim             CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen);
2481f13597dSJung-uk Kim         else
2491f13597dSJung-uk Kim             memcpy(gctx->iv, iv, gctx->ivlen);
2501f13597dSJung-uk Kim         gctx->iv_set = 1;
2511f13597dSJung-uk Kim         gctx->iv_gen = 0;
2521f13597dSJung-uk Kim     }
2531f13597dSJung-uk Kim     return 1;
2541f13597dSJung-uk Kim }
2551f13597dSJung-uk Kim 
2561f13597dSJung-uk Kim # define aesni_gcm_cipher aes_gcm_cipher
2571f13597dSJung-uk Kim static int aesni_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
2581f13597dSJung-uk Kim                             const unsigned char *in, size_t len);
2591f13597dSJung-uk Kim 
aesni_xts_init_key(EVP_CIPHER_CTX * ctx,const unsigned char * key,const unsigned char * iv,int enc)2601f13597dSJung-uk Kim static int aesni_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
2611f13597dSJung-uk Kim                               const unsigned char *iv, int enc)
2621f13597dSJung-uk Kim {
263e71b7053SJung-uk Kim     EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,ctx);
264da327cd2SJung-uk Kim 
2651f13597dSJung-uk Kim     if (!iv && !key)
2661f13597dSJung-uk Kim         return 1;
2671f13597dSJung-uk Kim 
2686f9291ceSJung-uk Kim     if (key) {
269da327cd2SJung-uk Kim         /* The key is two half length keys in reality */
270b077aed3SPierre Pronchery         const int bytes = EVP_CIPHER_CTX_get_key_length(ctx) / 2;
271b077aed3SPierre Pronchery         const int bits = bytes * 8;
272da327cd2SJung-uk Kim 
273da327cd2SJung-uk Kim         /*
274da327cd2SJung-uk Kim          * Verify that the two keys are different.
275da327cd2SJung-uk Kim          *
276da327cd2SJung-uk Kim          * This addresses Rogaway's vulnerability.
277da327cd2SJung-uk Kim          * See comment in aes_xts_init_key() below.
278da327cd2SJung-uk Kim          */
279b077aed3SPierre Pronchery         if ((!allow_insecure_decrypt || enc)
280b077aed3SPierre Pronchery                 && CRYPTO_memcmp(key, key + bytes, bytes) == 0) {
281b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_EVP, EVP_R_XTS_DUPLICATED_KEYS);
282da327cd2SJung-uk Kim             return 0;
283da327cd2SJung-uk Kim         }
284da327cd2SJung-uk Kim 
2851f13597dSJung-uk Kim         /* key_len is two AES keys */
2866f9291ceSJung-uk Kim         if (enc) {
287b077aed3SPierre Pronchery             aesni_set_encrypt_key(key, bits, &xctx->ks1.ks);
2881f13597dSJung-uk Kim             xctx->xts.block1 = (block128_f) aesni_encrypt;
2891f13597dSJung-uk Kim             xctx->stream = aesni_xts_encrypt;
2906f9291ceSJung-uk Kim         } else {
291b077aed3SPierre Pronchery             aesni_set_decrypt_key(key, bits, &xctx->ks1.ks);
2921f13597dSJung-uk Kim             xctx->xts.block1 = (block128_f) aesni_decrypt;
2931f13597dSJung-uk Kim             xctx->stream = aesni_xts_decrypt;
2941f13597dSJung-uk Kim         }
2951f13597dSJung-uk Kim 
296b077aed3SPierre Pronchery         aesni_set_encrypt_key(key + bytes, bits, &xctx->ks2.ks);
2971f13597dSJung-uk Kim         xctx->xts.block2 = (block128_f) aesni_encrypt;
2981f13597dSJung-uk Kim 
2991f13597dSJung-uk Kim         xctx->xts.key1 = &xctx->ks1;
3001f13597dSJung-uk Kim     }
3011f13597dSJung-uk Kim 
3026f9291ceSJung-uk Kim     if (iv) {
3031f13597dSJung-uk Kim         xctx->xts.key2 = &xctx->ks2;
304b077aed3SPierre Pronchery         memcpy(ctx->iv, iv, 16);
3051f13597dSJung-uk Kim     }
3061f13597dSJung-uk Kim 
3071f13597dSJung-uk Kim     return 1;
3081f13597dSJung-uk Kim }
3091f13597dSJung-uk Kim 
3101f13597dSJung-uk Kim # define aesni_xts_cipher aes_xts_cipher
3111f13597dSJung-uk Kim static int aesni_xts_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
3121f13597dSJung-uk Kim                             const unsigned char *in, size_t len);
3131f13597dSJung-uk Kim 
aesni_ccm_init_key(EVP_CIPHER_CTX * ctx,const unsigned char * key,const unsigned char * iv,int enc)3141f13597dSJung-uk Kim static int aesni_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
3151f13597dSJung-uk Kim                               const unsigned char *iv, int enc)
3161f13597dSJung-uk Kim {
317e71b7053SJung-uk Kim     EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx);
3181f13597dSJung-uk Kim     if (!iv && !key)
3191f13597dSJung-uk Kim         return 1;
3206f9291ceSJung-uk Kim     if (key) {
321b077aed3SPierre Pronchery         aesni_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
322e71b7053SJung-uk Kim                               &cctx->ks.ks);
3231f13597dSJung-uk Kim         CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L,
3241f13597dSJung-uk Kim                            &cctx->ks, (block128_f) aesni_encrypt);
3251f13597dSJung-uk Kim         cctx->str = enc ? (ccm128_f) aesni_ccm64_encrypt_blocks :
3261f13597dSJung-uk Kim             (ccm128_f) aesni_ccm64_decrypt_blocks;
3271f13597dSJung-uk Kim         cctx->key_set = 1;
3281f13597dSJung-uk Kim     }
3296f9291ceSJung-uk Kim     if (iv) {
330b077aed3SPierre Pronchery         memcpy(ctx->iv, iv, 15 - cctx->L);
3311f13597dSJung-uk Kim         cctx->iv_set = 1;
3321f13597dSJung-uk Kim     }
3331f13597dSJung-uk Kim     return 1;
3341f13597dSJung-uk Kim }
3351f13597dSJung-uk Kim 
3361f13597dSJung-uk Kim # define aesni_ccm_cipher aes_ccm_cipher
3371f13597dSJung-uk Kim static int aesni_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
3381f13597dSJung-uk Kim                             const unsigned char *in, size_t len);
3391f13597dSJung-uk Kim 
340e71b7053SJung-uk Kim # ifndef OPENSSL_NO_OCB
aesni_ocb_init_key(EVP_CIPHER_CTX * ctx,const unsigned char * key,const unsigned char * iv,int enc)341e71b7053SJung-uk Kim static int aesni_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
342e71b7053SJung-uk Kim                               const unsigned char *iv, int enc)
343e71b7053SJung-uk Kim {
344e71b7053SJung-uk Kim     EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,ctx);
345e71b7053SJung-uk Kim     if (!iv && !key)
346e71b7053SJung-uk Kim         return 1;
347e71b7053SJung-uk Kim     if (key) {
348e71b7053SJung-uk Kim         do {
349e71b7053SJung-uk Kim             /*
350e71b7053SJung-uk Kim              * We set both the encrypt and decrypt key here because decrypt
351e71b7053SJung-uk Kim              * needs both. We could possibly optimise to remove setting the
352e71b7053SJung-uk Kim              * decrypt for an encryption operation.
353e71b7053SJung-uk Kim              */
354b077aed3SPierre Pronchery             aesni_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
355e71b7053SJung-uk Kim                                   &octx->ksenc.ks);
356b077aed3SPierre Pronchery             aesni_set_decrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
357e71b7053SJung-uk Kim                                   &octx->ksdec.ks);
358e71b7053SJung-uk Kim             if (!CRYPTO_ocb128_init(&octx->ocb,
359e71b7053SJung-uk Kim                                     &octx->ksenc.ks, &octx->ksdec.ks,
360e71b7053SJung-uk Kim                                     (block128_f) aesni_encrypt,
361e71b7053SJung-uk Kim                                     (block128_f) aesni_decrypt,
362e71b7053SJung-uk Kim                                     enc ? aesni_ocb_encrypt
363e71b7053SJung-uk Kim                                         : aesni_ocb_decrypt))
364e71b7053SJung-uk Kim                 return 0;
365e71b7053SJung-uk Kim         }
366e71b7053SJung-uk Kim         while (0);
367e71b7053SJung-uk Kim 
368e71b7053SJung-uk Kim         /*
369e71b7053SJung-uk Kim          * If we have an iv we can set it directly, otherwise use saved IV.
370e71b7053SJung-uk Kim          */
371e71b7053SJung-uk Kim         if (iv == NULL && octx->iv_set)
372e71b7053SJung-uk Kim             iv = octx->iv;
373e71b7053SJung-uk Kim         if (iv) {
374e71b7053SJung-uk Kim             if (CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen)
375e71b7053SJung-uk Kim                 != 1)
376e71b7053SJung-uk Kim                 return 0;
377e71b7053SJung-uk Kim             octx->iv_set = 1;
378e71b7053SJung-uk Kim         }
379e71b7053SJung-uk Kim         octx->key_set = 1;
380e71b7053SJung-uk Kim     } else {
381e71b7053SJung-uk Kim         /* If key set use IV, otherwise copy */
382e71b7053SJung-uk Kim         if (octx->key_set)
383e71b7053SJung-uk Kim             CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen);
384e71b7053SJung-uk Kim         else
385e71b7053SJung-uk Kim             memcpy(octx->iv, iv, octx->ivlen);
386e71b7053SJung-uk Kim         octx->iv_set = 1;
387e71b7053SJung-uk Kim     }
388e71b7053SJung-uk Kim     return 1;
389e71b7053SJung-uk Kim }
390e71b7053SJung-uk Kim 
391e71b7053SJung-uk Kim #  define aesni_ocb_cipher aes_ocb_cipher
392e71b7053SJung-uk Kim static int aesni_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
393e71b7053SJung-uk Kim                             const unsigned char *in, size_t len);
394e71b7053SJung-uk Kim # endif                        /* OPENSSL_NO_OCB */
395e71b7053SJung-uk Kim 
3961f13597dSJung-uk Kim # define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \
3971f13597dSJung-uk Kim static const EVP_CIPHER aesni_##keylen##_##mode = { \
3981f13597dSJung-uk Kim         nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \
3991f13597dSJung-uk Kim         flags|EVP_CIPH_##MODE##_MODE,   \
400b077aed3SPierre Pronchery         EVP_ORIG_GLOBAL,                \
4011f13597dSJung-uk Kim         aesni_init_key,                 \
4021f13597dSJung-uk Kim         aesni_##mode##_cipher,          \
4031f13597dSJung-uk Kim         NULL,                           \
4041f13597dSJung-uk Kim         sizeof(EVP_AES_KEY),            \
4051f13597dSJung-uk Kim         NULL,NULL,NULL,NULL }; \
4061f13597dSJung-uk Kim static const EVP_CIPHER aes_##keylen##_##mode = { \
4071f13597dSJung-uk Kim         nid##_##keylen##_##nmode,blocksize,     \
4081f13597dSJung-uk Kim         keylen/8,ivlen,                 \
4091f13597dSJung-uk Kim         flags|EVP_CIPH_##MODE##_MODE,   \
410b077aed3SPierre Pronchery         EVP_ORIG_GLOBAL,                 \
4111f13597dSJung-uk Kim         aes_init_key,                   \
4121f13597dSJung-uk Kim         aes_##mode##_cipher,            \
4131f13597dSJung-uk Kim         NULL,                           \
4141f13597dSJung-uk Kim         sizeof(EVP_AES_KEY),            \
4151f13597dSJung-uk Kim         NULL,NULL,NULL,NULL }; \
4161f13597dSJung-uk Kim const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
4171f13597dSJung-uk Kim { return AESNI_CAPABLE?&aesni_##keylen##_##mode:&aes_##keylen##_##mode; }
4181f13597dSJung-uk Kim 
4191f13597dSJung-uk Kim # define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags) \
4201f13597dSJung-uk Kim static const EVP_CIPHER aesni_##keylen##_##mode = { \
4211f13597dSJung-uk Kim         nid##_##keylen##_##mode,blocksize, \
422b077aed3SPierre Pronchery         (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE||EVP_CIPH_##MODE##_MODE==EVP_CIPH_SIV_MODE?2:1)*keylen/8, \
423b077aed3SPierre Pronchery         ivlen,                          \
4241f13597dSJung-uk Kim         flags|EVP_CIPH_##MODE##_MODE,   \
425b077aed3SPierre Pronchery         EVP_ORIG_GLOBAL,                \
4261f13597dSJung-uk Kim         aesni_##mode##_init_key,        \
4271f13597dSJung-uk Kim         aesni_##mode##_cipher,          \
4281f13597dSJung-uk Kim         aes_##mode##_cleanup,           \
4291f13597dSJung-uk Kim         sizeof(EVP_AES_##MODE##_CTX),   \
4301f13597dSJung-uk Kim         NULL,NULL,aes_##mode##_ctrl,NULL }; \
4311f13597dSJung-uk Kim static const EVP_CIPHER aes_##keylen##_##mode = { \
4321f13597dSJung-uk Kim         nid##_##keylen##_##mode,blocksize, \
433b077aed3SPierre Pronchery         (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE||EVP_CIPH_##MODE##_MODE==EVP_CIPH_SIV_MODE?2:1)*keylen/8, \
434b077aed3SPierre Pronchery         ivlen,                          \
4351f13597dSJung-uk Kim         flags|EVP_CIPH_##MODE##_MODE,   \
436b077aed3SPierre Pronchery         EVP_ORIG_GLOBAL,                \
4371f13597dSJung-uk Kim         aes_##mode##_init_key,          \
4381f13597dSJung-uk Kim         aes_##mode##_cipher,            \
4391f13597dSJung-uk Kim         aes_##mode##_cleanup,           \
4401f13597dSJung-uk Kim         sizeof(EVP_AES_##MODE##_CTX),   \
4411f13597dSJung-uk Kim         NULL,NULL,aes_##mode##_ctrl,NULL }; \
4421f13597dSJung-uk Kim const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
4431f13597dSJung-uk Kim { return AESNI_CAPABLE?&aesni_##keylen##_##mode:&aes_##keylen##_##mode; }
4441f13597dSJung-uk Kim 
445b077aed3SPierre Pronchery #elif defined(SPARC_AES_CAPABLE)
4467bded2dbSJung-uk Kim 
aes_t4_init_key(EVP_CIPHER_CTX * ctx,const unsigned char * key,const unsigned char * iv,int enc)4477bded2dbSJung-uk Kim static int aes_t4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
4487bded2dbSJung-uk Kim                            const unsigned char *iv, int enc)
4497bded2dbSJung-uk Kim {
4507bded2dbSJung-uk Kim     int ret, mode, bits;
451e71b7053SJung-uk Kim     EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
4527bded2dbSJung-uk Kim 
453b077aed3SPierre Pronchery     mode = EVP_CIPHER_CTX_get_mode(ctx);
454b077aed3SPierre Pronchery     bits = EVP_CIPHER_CTX_get_key_length(ctx) * 8;
4557bded2dbSJung-uk Kim     if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE)
4567bded2dbSJung-uk Kim         && !enc) {
4577bded2dbSJung-uk Kim         ret = 0;
458e71b7053SJung-uk Kim         aes_t4_set_decrypt_key(key, bits, &dat->ks.ks);
4597bded2dbSJung-uk Kim         dat->block = (block128_f) aes_t4_decrypt;
4607bded2dbSJung-uk Kim         switch (bits) {
4617bded2dbSJung-uk Kim         case 128:
4627bded2dbSJung-uk Kim             dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
4637bded2dbSJung-uk Kim                 (cbc128_f) aes128_t4_cbc_decrypt : NULL;
4647bded2dbSJung-uk Kim             break;
4657bded2dbSJung-uk Kim         case 192:
4667bded2dbSJung-uk Kim             dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
4677bded2dbSJung-uk Kim                 (cbc128_f) aes192_t4_cbc_decrypt : NULL;
4687bded2dbSJung-uk Kim             break;
4697bded2dbSJung-uk Kim         case 256:
4707bded2dbSJung-uk Kim             dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
4717bded2dbSJung-uk Kim                 (cbc128_f) aes256_t4_cbc_decrypt : NULL;
4727bded2dbSJung-uk Kim             break;
4737bded2dbSJung-uk Kim         default:
4747bded2dbSJung-uk Kim             ret = -1;
4757bded2dbSJung-uk Kim         }
4767bded2dbSJung-uk Kim     } else {
4777bded2dbSJung-uk Kim         ret = 0;
478e71b7053SJung-uk Kim         aes_t4_set_encrypt_key(key, bits, &dat->ks.ks);
4797bded2dbSJung-uk Kim         dat->block = (block128_f) aes_t4_encrypt;
4807bded2dbSJung-uk Kim         switch (bits) {
4817bded2dbSJung-uk Kim         case 128:
4827bded2dbSJung-uk Kim             if (mode == EVP_CIPH_CBC_MODE)
4837bded2dbSJung-uk Kim                 dat->stream.cbc = (cbc128_f) aes128_t4_cbc_encrypt;
4847bded2dbSJung-uk Kim             else if (mode == EVP_CIPH_CTR_MODE)
4857bded2dbSJung-uk Kim                 dat->stream.ctr = (ctr128_f) aes128_t4_ctr32_encrypt;
4867bded2dbSJung-uk Kim             else
4877bded2dbSJung-uk Kim                 dat->stream.cbc = NULL;
4887bded2dbSJung-uk Kim             break;
4897bded2dbSJung-uk Kim         case 192:
4907bded2dbSJung-uk Kim             if (mode == EVP_CIPH_CBC_MODE)
4917bded2dbSJung-uk Kim                 dat->stream.cbc = (cbc128_f) aes192_t4_cbc_encrypt;
4927bded2dbSJung-uk Kim             else if (mode == EVP_CIPH_CTR_MODE)
4937bded2dbSJung-uk Kim                 dat->stream.ctr = (ctr128_f) aes192_t4_ctr32_encrypt;
4947bded2dbSJung-uk Kim             else
4957bded2dbSJung-uk Kim                 dat->stream.cbc = NULL;
4967bded2dbSJung-uk Kim             break;
4977bded2dbSJung-uk Kim         case 256:
4987bded2dbSJung-uk Kim             if (mode == EVP_CIPH_CBC_MODE)
4997bded2dbSJung-uk Kim                 dat->stream.cbc = (cbc128_f) aes256_t4_cbc_encrypt;
5007bded2dbSJung-uk Kim             else if (mode == EVP_CIPH_CTR_MODE)
5017bded2dbSJung-uk Kim                 dat->stream.ctr = (ctr128_f) aes256_t4_ctr32_encrypt;
5027bded2dbSJung-uk Kim             else
5037bded2dbSJung-uk Kim                 dat->stream.cbc = NULL;
5047bded2dbSJung-uk Kim             break;
5057bded2dbSJung-uk Kim         default:
5067bded2dbSJung-uk Kim             ret = -1;
5077bded2dbSJung-uk Kim         }
5087bded2dbSJung-uk Kim     }
5097bded2dbSJung-uk Kim 
5107bded2dbSJung-uk Kim     if (ret < 0) {
511b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, EVP_R_AES_KEY_SETUP_FAILED);
5127bded2dbSJung-uk Kim         return 0;
5137bded2dbSJung-uk Kim     }
5147bded2dbSJung-uk Kim 
5157bded2dbSJung-uk Kim     return 1;
5167bded2dbSJung-uk Kim }
5177bded2dbSJung-uk Kim 
5187bded2dbSJung-uk Kim # define aes_t4_cbc_cipher aes_cbc_cipher
5197bded2dbSJung-uk Kim static int aes_t4_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
5207bded2dbSJung-uk Kim                              const unsigned char *in, size_t len);
5217bded2dbSJung-uk Kim 
5227bded2dbSJung-uk Kim # define aes_t4_ecb_cipher aes_ecb_cipher
5237bded2dbSJung-uk Kim static int aes_t4_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
5247bded2dbSJung-uk Kim                              const unsigned char *in, size_t len);
5257bded2dbSJung-uk Kim 
5267bded2dbSJung-uk Kim # define aes_t4_ofb_cipher aes_ofb_cipher
5277bded2dbSJung-uk Kim static int aes_t4_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
5287bded2dbSJung-uk Kim                              const unsigned char *in, size_t len);
5297bded2dbSJung-uk Kim 
5307bded2dbSJung-uk Kim # define aes_t4_cfb_cipher aes_cfb_cipher
5317bded2dbSJung-uk Kim static int aes_t4_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
5327bded2dbSJung-uk Kim                              const unsigned char *in, size_t len);
5337bded2dbSJung-uk Kim 
5347bded2dbSJung-uk Kim # define aes_t4_cfb8_cipher aes_cfb8_cipher
5357bded2dbSJung-uk Kim static int aes_t4_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
5367bded2dbSJung-uk Kim                               const unsigned char *in, size_t len);
5377bded2dbSJung-uk Kim 
5387bded2dbSJung-uk Kim # define aes_t4_cfb1_cipher aes_cfb1_cipher
5397bded2dbSJung-uk Kim static int aes_t4_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
5407bded2dbSJung-uk Kim                               const unsigned char *in, size_t len);
5417bded2dbSJung-uk Kim 
5427bded2dbSJung-uk Kim # define aes_t4_ctr_cipher aes_ctr_cipher
5437bded2dbSJung-uk Kim static int aes_t4_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
5447bded2dbSJung-uk Kim                              const unsigned char *in, size_t len);
5457bded2dbSJung-uk Kim 
aes_t4_gcm_init_key(EVP_CIPHER_CTX * ctx,const unsigned char * key,const unsigned char * iv,int enc)5467bded2dbSJung-uk Kim static int aes_t4_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
5477bded2dbSJung-uk Kim                                const unsigned char *iv, int enc)
5487bded2dbSJung-uk Kim {
549e71b7053SJung-uk Kim     EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx);
5507bded2dbSJung-uk Kim     if (!iv && !key)
5517bded2dbSJung-uk Kim         return 1;
5527bded2dbSJung-uk Kim     if (key) {
553b077aed3SPierre Pronchery         int bits = EVP_CIPHER_CTX_get_key_length(ctx) * 8;
5547bded2dbSJung-uk Kim         aes_t4_set_encrypt_key(key, bits, &gctx->ks.ks);
5557bded2dbSJung-uk Kim         CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks,
5567bded2dbSJung-uk Kim                            (block128_f) aes_t4_encrypt);
5577bded2dbSJung-uk Kim         switch (bits) {
5587bded2dbSJung-uk Kim         case 128:
5597bded2dbSJung-uk Kim             gctx->ctr = (ctr128_f) aes128_t4_ctr32_encrypt;
5607bded2dbSJung-uk Kim             break;
5617bded2dbSJung-uk Kim         case 192:
5627bded2dbSJung-uk Kim             gctx->ctr = (ctr128_f) aes192_t4_ctr32_encrypt;
5637bded2dbSJung-uk Kim             break;
5647bded2dbSJung-uk Kim         case 256:
5657bded2dbSJung-uk Kim             gctx->ctr = (ctr128_f) aes256_t4_ctr32_encrypt;
5667bded2dbSJung-uk Kim             break;
5677bded2dbSJung-uk Kim         default:
5687bded2dbSJung-uk Kim             return 0;
5697bded2dbSJung-uk Kim         }
5707bded2dbSJung-uk Kim         /*
5717bded2dbSJung-uk Kim          * If we have an iv can set it directly, otherwise use saved IV.
5727bded2dbSJung-uk Kim          */
5737bded2dbSJung-uk Kim         if (iv == NULL && gctx->iv_set)
5747bded2dbSJung-uk Kim             iv = gctx->iv;
5757bded2dbSJung-uk Kim         if (iv) {
5767bded2dbSJung-uk Kim             CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen);
5777bded2dbSJung-uk Kim             gctx->iv_set = 1;
5787bded2dbSJung-uk Kim         }
5797bded2dbSJung-uk Kim         gctx->key_set = 1;
5807bded2dbSJung-uk Kim     } else {
5817bded2dbSJung-uk Kim         /* If key set use IV, otherwise copy */
5827bded2dbSJung-uk Kim         if (gctx->key_set)
5837bded2dbSJung-uk Kim             CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen);
5847bded2dbSJung-uk Kim         else
5857bded2dbSJung-uk Kim             memcpy(gctx->iv, iv, gctx->ivlen);
5867bded2dbSJung-uk Kim         gctx->iv_set = 1;
5877bded2dbSJung-uk Kim         gctx->iv_gen = 0;
5887bded2dbSJung-uk Kim     }
5897bded2dbSJung-uk Kim     return 1;
5907bded2dbSJung-uk Kim }
5917bded2dbSJung-uk Kim 
5927bded2dbSJung-uk Kim # define aes_t4_gcm_cipher aes_gcm_cipher
5937bded2dbSJung-uk Kim static int aes_t4_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
5947bded2dbSJung-uk Kim                              const unsigned char *in, size_t len);
5957bded2dbSJung-uk Kim 
aes_t4_xts_init_key(EVP_CIPHER_CTX * ctx,const unsigned char * key,const unsigned char * iv,int enc)5967bded2dbSJung-uk Kim static int aes_t4_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
5977bded2dbSJung-uk Kim                                const unsigned char *iv, int enc)
5987bded2dbSJung-uk Kim {
599e71b7053SJung-uk Kim     EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,ctx);
600da327cd2SJung-uk Kim 
6017bded2dbSJung-uk Kim     if (!iv && !key)
6027bded2dbSJung-uk Kim         return 1;
6037bded2dbSJung-uk Kim 
6047bded2dbSJung-uk Kim     if (key) {
605da327cd2SJung-uk Kim         /* The key is two half length keys in reality */
606b077aed3SPierre Pronchery         const int bytes = EVP_CIPHER_CTX_get_key_length(ctx) / 2;
607da327cd2SJung-uk Kim         const int bits = bytes * 8;
608da327cd2SJung-uk Kim 
609da327cd2SJung-uk Kim         /*
610da327cd2SJung-uk Kim          * Verify that the two keys are different.
611da327cd2SJung-uk Kim          *
612da327cd2SJung-uk Kim          * This addresses Rogaway's vulnerability.
613da327cd2SJung-uk Kim          * See comment in aes_xts_init_key() below.
614da327cd2SJung-uk Kim          */
615b077aed3SPierre Pronchery         if ((!allow_insecure_decrypt || enc)
616b077aed3SPierre Pronchery                 && CRYPTO_memcmp(key, key + bytes, bytes) == 0) {
617b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_EVP, EVP_R_XTS_DUPLICATED_KEYS);
618da327cd2SJung-uk Kim             return 0;
619da327cd2SJung-uk Kim         }
620da327cd2SJung-uk Kim 
6217bded2dbSJung-uk Kim         xctx->stream = NULL;
6227bded2dbSJung-uk Kim         /* key_len is two AES keys */
6237bded2dbSJung-uk Kim         if (enc) {
6247bded2dbSJung-uk Kim             aes_t4_set_encrypt_key(key, bits, &xctx->ks1.ks);
6257bded2dbSJung-uk Kim             xctx->xts.block1 = (block128_f) aes_t4_encrypt;
6267bded2dbSJung-uk Kim             switch (bits) {
6277bded2dbSJung-uk Kim             case 128:
6287bded2dbSJung-uk Kim                 xctx->stream = aes128_t4_xts_encrypt;
6297bded2dbSJung-uk Kim                 break;
6307bded2dbSJung-uk Kim             case 256:
6317bded2dbSJung-uk Kim                 xctx->stream = aes256_t4_xts_encrypt;
6327bded2dbSJung-uk Kim                 break;
6337bded2dbSJung-uk Kim             default:
6347bded2dbSJung-uk Kim                 return 0;
6357bded2dbSJung-uk Kim             }
6367bded2dbSJung-uk Kim         } else {
637b077aed3SPierre Pronchery             aes_t4_set_decrypt_key(key, bits, &xctx->ks1.ks);
6387bded2dbSJung-uk Kim             xctx->xts.block1 = (block128_f) aes_t4_decrypt;
6397bded2dbSJung-uk Kim             switch (bits) {
6407bded2dbSJung-uk Kim             case 128:
6417bded2dbSJung-uk Kim                 xctx->stream = aes128_t4_xts_decrypt;
6427bded2dbSJung-uk Kim                 break;
6437bded2dbSJung-uk Kim             case 256:
6447bded2dbSJung-uk Kim                 xctx->stream = aes256_t4_xts_decrypt;
6457bded2dbSJung-uk Kim                 break;
6467bded2dbSJung-uk Kim             default:
6477bded2dbSJung-uk Kim                 return 0;
6487bded2dbSJung-uk Kim             }
6497bded2dbSJung-uk Kim         }
6507bded2dbSJung-uk Kim 
651b077aed3SPierre Pronchery         aes_t4_set_encrypt_key(key + bytes, bits, &xctx->ks2.ks);
6527bded2dbSJung-uk Kim         xctx->xts.block2 = (block128_f) aes_t4_encrypt;
6537bded2dbSJung-uk Kim 
6547bded2dbSJung-uk Kim         xctx->xts.key1 = &xctx->ks1;
6557bded2dbSJung-uk Kim     }
6567bded2dbSJung-uk Kim 
6577bded2dbSJung-uk Kim     if (iv) {
6587bded2dbSJung-uk Kim         xctx->xts.key2 = &xctx->ks2;
659b077aed3SPierre Pronchery         memcpy(ctx->iv, iv, 16);
6607bded2dbSJung-uk Kim     }
6617bded2dbSJung-uk Kim 
6627bded2dbSJung-uk Kim     return 1;
6637bded2dbSJung-uk Kim }
6647bded2dbSJung-uk Kim 
6657bded2dbSJung-uk Kim # define aes_t4_xts_cipher aes_xts_cipher
6667bded2dbSJung-uk Kim static int aes_t4_xts_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
6677bded2dbSJung-uk Kim                              const unsigned char *in, size_t len);
6687bded2dbSJung-uk Kim 
aes_t4_ccm_init_key(EVP_CIPHER_CTX * ctx,const unsigned char * key,const unsigned char * iv,int enc)6697bded2dbSJung-uk Kim static int aes_t4_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
6707bded2dbSJung-uk Kim                                const unsigned char *iv, int enc)
6717bded2dbSJung-uk Kim {
672e71b7053SJung-uk Kim     EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx);
6737bded2dbSJung-uk Kim     if (!iv && !key)
6747bded2dbSJung-uk Kim         return 1;
6757bded2dbSJung-uk Kim     if (key) {
676b077aed3SPierre Pronchery         int bits = EVP_CIPHER_CTX_get_key_length(ctx) * 8;
6777bded2dbSJung-uk Kim         aes_t4_set_encrypt_key(key, bits, &cctx->ks.ks);
6787bded2dbSJung-uk Kim         CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L,
6797bded2dbSJung-uk Kim                            &cctx->ks, (block128_f) aes_t4_encrypt);
6807bded2dbSJung-uk Kim         cctx->str = NULL;
6817bded2dbSJung-uk Kim         cctx->key_set = 1;
6827bded2dbSJung-uk Kim     }
6837bded2dbSJung-uk Kim     if (iv) {
684b077aed3SPierre Pronchery         memcpy(ctx->iv, iv, 15 - cctx->L);
6857bded2dbSJung-uk Kim         cctx->iv_set = 1;
6867bded2dbSJung-uk Kim     }
6877bded2dbSJung-uk Kim     return 1;
6887bded2dbSJung-uk Kim }
6897bded2dbSJung-uk Kim 
6907bded2dbSJung-uk Kim # define aes_t4_ccm_cipher aes_ccm_cipher
6917bded2dbSJung-uk Kim static int aes_t4_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
6927bded2dbSJung-uk Kim                              const unsigned char *in, size_t len);
6937bded2dbSJung-uk Kim 
694e71b7053SJung-uk Kim # ifndef OPENSSL_NO_OCB
aes_t4_ocb_init_key(EVP_CIPHER_CTX * ctx,const unsigned char * key,const unsigned char * iv,int enc)695e71b7053SJung-uk Kim static int aes_t4_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
696e71b7053SJung-uk Kim                                const unsigned char *iv, int enc)
697e71b7053SJung-uk Kim {
698e71b7053SJung-uk Kim     EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,ctx);
699e71b7053SJung-uk Kim     if (!iv && !key)
700e71b7053SJung-uk Kim         return 1;
701e71b7053SJung-uk Kim     if (key) {
702e71b7053SJung-uk Kim         do {
703e71b7053SJung-uk Kim             /*
704e71b7053SJung-uk Kim              * We set both the encrypt and decrypt key here because decrypt
705e71b7053SJung-uk Kim              * needs both. We could possibly optimise to remove setting the
706e71b7053SJung-uk Kim              * decrypt for an encryption operation.
707e71b7053SJung-uk Kim              */
708b077aed3SPierre Pronchery             aes_t4_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
709e71b7053SJung-uk Kim                                    &octx->ksenc.ks);
710b077aed3SPierre Pronchery             aes_t4_set_decrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
711e71b7053SJung-uk Kim                                    &octx->ksdec.ks);
712e71b7053SJung-uk Kim             if (!CRYPTO_ocb128_init(&octx->ocb,
713e71b7053SJung-uk Kim                                     &octx->ksenc.ks, &octx->ksdec.ks,
714e71b7053SJung-uk Kim                                     (block128_f) aes_t4_encrypt,
715e71b7053SJung-uk Kim                                     (block128_f) aes_t4_decrypt,
716e71b7053SJung-uk Kim                                     NULL))
717e71b7053SJung-uk Kim                 return 0;
718e71b7053SJung-uk Kim         }
719e71b7053SJung-uk Kim         while (0);
720e71b7053SJung-uk Kim 
721e71b7053SJung-uk Kim         /*
722e71b7053SJung-uk Kim          * If we have an iv we can set it directly, otherwise use saved IV.
723e71b7053SJung-uk Kim          */
724e71b7053SJung-uk Kim         if (iv == NULL && octx->iv_set)
725e71b7053SJung-uk Kim             iv = octx->iv;
726e71b7053SJung-uk Kim         if (iv) {
727e71b7053SJung-uk Kim             if (CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen)
728e71b7053SJung-uk Kim                 != 1)
729e71b7053SJung-uk Kim                 return 0;
730e71b7053SJung-uk Kim             octx->iv_set = 1;
731e71b7053SJung-uk Kim         }
732e71b7053SJung-uk Kim         octx->key_set = 1;
733e71b7053SJung-uk Kim     } else {
734e71b7053SJung-uk Kim         /* If key set use IV, otherwise copy */
735e71b7053SJung-uk Kim         if (octx->key_set)
736e71b7053SJung-uk Kim             CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen);
737e71b7053SJung-uk Kim         else
738e71b7053SJung-uk Kim             memcpy(octx->iv, iv, octx->ivlen);
739e71b7053SJung-uk Kim         octx->iv_set = 1;
740e71b7053SJung-uk Kim     }
741e71b7053SJung-uk Kim     return 1;
742e71b7053SJung-uk Kim }
743e71b7053SJung-uk Kim 
744e71b7053SJung-uk Kim #  define aes_t4_ocb_cipher aes_ocb_cipher
745e71b7053SJung-uk Kim static int aes_t4_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
746e71b7053SJung-uk Kim                              const unsigned char *in, size_t len);
747e71b7053SJung-uk Kim # endif                        /* OPENSSL_NO_OCB */
748e71b7053SJung-uk Kim 
749b077aed3SPierre Pronchery # ifndef OPENSSL_NO_SIV
750b077aed3SPierre Pronchery #  define aes_t4_siv_init_key aes_siv_init_key
751b077aed3SPierre Pronchery #  define aes_t4_siv_cipher aes_siv_cipher
752b077aed3SPierre Pronchery # endif /* OPENSSL_NO_SIV */
753b077aed3SPierre Pronchery 
7547bded2dbSJung-uk Kim # define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \
7557bded2dbSJung-uk Kim static const EVP_CIPHER aes_t4_##keylen##_##mode = { \
7567bded2dbSJung-uk Kim         nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \
7577bded2dbSJung-uk Kim         flags|EVP_CIPH_##MODE##_MODE,   \
758b077aed3SPierre Pronchery         EVP_ORIG_GLOBAL,                \
7597bded2dbSJung-uk Kim         aes_t4_init_key,                \
7607bded2dbSJung-uk Kim         aes_t4_##mode##_cipher,         \
7617bded2dbSJung-uk Kim         NULL,                           \
7627bded2dbSJung-uk Kim         sizeof(EVP_AES_KEY),            \
7637bded2dbSJung-uk Kim         NULL,NULL,NULL,NULL }; \
7647bded2dbSJung-uk Kim static const EVP_CIPHER aes_##keylen##_##mode = { \
7657bded2dbSJung-uk Kim         nid##_##keylen##_##nmode,blocksize,     \
7667bded2dbSJung-uk Kim         keylen/8,ivlen, \
7677bded2dbSJung-uk Kim         flags|EVP_CIPH_##MODE##_MODE,   \
768b077aed3SPierre Pronchery         EVP_ORIG_GLOBAL,                \
7697bded2dbSJung-uk Kim         aes_init_key,                   \
7707bded2dbSJung-uk Kim         aes_##mode##_cipher,            \
7717bded2dbSJung-uk Kim         NULL,                           \
7727bded2dbSJung-uk Kim         sizeof(EVP_AES_KEY),            \
7737bded2dbSJung-uk Kim         NULL,NULL,NULL,NULL }; \
7747bded2dbSJung-uk Kim const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
7757bded2dbSJung-uk Kim { return SPARC_AES_CAPABLE?&aes_t4_##keylen##_##mode:&aes_##keylen##_##mode; }
7767bded2dbSJung-uk Kim 
7777bded2dbSJung-uk Kim # define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags) \
7787bded2dbSJung-uk Kim static const EVP_CIPHER aes_t4_##keylen##_##mode = { \
7797bded2dbSJung-uk Kim         nid##_##keylen##_##mode,blocksize, \
780b077aed3SPierre Pronchery         (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE||EVP_CIPH_##MODE##_MODE==EVP_CIPH_SIV_MODE?2:1)*keylen/8, \
781b077aed3SPierre Pronchery         ivlen,                          \
7827bded2dbSJung-uk Kim         flags|EVP_CIPH_##MODE##_MODE,   \
783b077aed3SPierre Pronchery         EVP_ORIG_GLOBAL,                \
7847bded2dbSJung-uk Kim         aes_t4_##mode##_init_key,       \
7857bded2dbSJung-uk Kim         aes_t4_##mode##_cipher,         \
7867bded2dbSJung-uk Kim         aes_##mode##_cleanup,           \
7877bded2dbSJung-uk Kim         sizeof(EVP_AES_##MODE##_CTX),   \
7887bded2dbSJung-uk Kim         NULL,NULL,aes_##mode##_ctrl,NULL }; \
7897bded2dbSJung-uk Kim static const EVP_CIPHER aes_##keylen##_##mode = { \
7907bded2dbSJung-uk Kim         nid##_##keylen##_##mode,blocksize, \
791b077aed3SPierre Pronchery         (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE||EVP_CIPH_##MODE##_MODE==EVP_CIPH_SIV_MODE?2:1)*keylen/8, \
792b077aed3SPierre Pronchery         ivlen,                          \
7937bded2dbSJung-uk Kim         flags|EVP_CIPH_##MODE##_MODE,   \
794b077aed3SPierre Pronchery         EVP_ORIG_GLOBAL,                \
7957bded2dbSJung-uk Kim         aes_##mode##_init_key,          \
7967bded2dbSJung-uk Kim         aes_##mode##_cipher,            \
7977bded2dbSJung-uk Kim         aes_##mode##_cleanup,           \
7987bded2dbSJung-uk Kim         sizeof(EVP_AES_##MODE##_CTX),   \
7997bded2dbSJung-uk Kim         NULL,NULL,aes_##mode##_ctrl,NULL }; \
8007bded2dbSJung-uk Kim const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
8017bded2dbSJung-uk Kim { return SPARC_AES_CAPABLE?&aes_t4_##keylen##_##mode:&aes_##keylen##_##mode; }
8027bded2dbSJung-uk Kim 
803b077aed3SPierre Pronchery #elif defined(S390X_aes_128_CAPABLE)
804b077aed3SPierre Pronchery /* IBM S390X support */
805e71b7053SJung-uk Kim typedef struct {
806e71b7053SJung-uk Kim     union {
807b077aed3SPierre Pronchery         OSSL_UNION_ALIGN;
808e71b7053SJung-uk Kim         /*-
809e71b7053SJung-uk Kim          * KM-AES parameter block - begin
810e71b7053SJung-uk Kim          * (see z/Architecture Principles of Operation >= SA22-7832-06)
811e71b7053SJung-uk Kim          */
812e71b7053SJung-uk Kim         struct {
813e71b7053SJung-uk Kim             unsigned char k[32];
814e71b7053SJung-uk Kim         } param;
815e71b7053SJung-uk Kim         /* KM-AES parameter block - end */
816e71b7053SJung-uk Kim     } km;
817e71b7053SJung-uk Kim     unsigned int fc;
818e71b7053SJung-uk Kim } S390X_AES_ECB_CTX;
819e71b7053SJung-uk Kim 
820e71b7053SJung-uk Kim typedef struct {
821e71b7053SJung-uk Kim     union {
822b077aed3SPierre Pronchery         OSSL_UNION_ALIGN;
823e71b7053SJung-uk Kim         /*-
824e71b7053SJung-uk Kim          * KMO-AES parameter block - begin
825e71b7053SJung-uk Kim          * (see z/Architecture Principles of Operation >= SA22-7832-08)
826e71b7053SJung-uk Kim          */
827e71b7053SJung-uk Kim         struct {
828e71b7053SJung-uk Kim             unsigned char cv[16];
829e71b7053SJung-uk Kim             unsigned char k[32];
830e71b7053SJung-uk Kim         } param;
831e71b7053SJung-uk Kim         /* KMO-AES parameter block - end */
832e71b7053SJung-uk Kim     } kmo;
833e71b7053SJung-uk Kim     unsigned int fc;
834e71b7053SJung-uk Kim } S390X_AES_OFB_CTX;
835e71b7053SJung-uk Kim 
836e71b7053SJung-uk Kim typedef struct {
837e71b7053SJung-uk Kim     union {
838b077aed3SPierre Pronchery         OSSL_UNION_ALIGN;
839e71b7053SJung-uk Kim         /*-
840e71b7053SJung-uk Kim          * KMF-AES parameter block - begin
841e71b7053SJung-uk Kim          * (see z/Architecture Principles of Operation >= SA22-7832-08)
842e71b7053SJung-uk Kim          */
843e71b7053SJung-uk Kim         struct {
844e71b7053SJung-uk Kim             unsigned char cv[16];
845e71b7053SJung-uk Kim             unsigned char k[32];
846e71b7053SJung-uk Kim         } param;
847e71b7053SJung-uk Kim         /* KMF-AES parameter block - end */
848e71b7053SJung-uk Kim     } kmf;
849e71b7053SJung-uk Kim     unsigned int fc;
850e71b7053SJung-uk Kim } S390X_AES_CFB_CTX;
851e71b7053SJung-uk Kim 
852e71b7053SJung-uk Kim typedef struct {
853e71b7053SJung-uk Kim     union {
854b077aed3SPierre Pronchery         OSSL_UNION_ALIGN;
855e71b7053SJung-uk Kim         /*-
856e71b7053SJung-uk Kim          * KMA-GCM-AES parameter block - begin
857e71b7053SJung-uk Kim          * (see z/Architecture Principles of Operation >= SA22-7832-11)
858e71b7053SJung-uk Kim          */
859e71b7053SJung-uk Kim         struct {
860e71b7053SJung-uk Kim             unsigned char reserved[12];
861e71b7053SJung-uk Kim             union {
862e71b7053SJung-uk Kim                 unsigned int w;
863e71b7053SJung-uk Kim                 unsigned char b[4];
864e71b7053SJung-uk Kim             } cv;
865e71b7053SJung-uk Kim             union {
866e71b7053SJung-uk Kim                 unsigned long long g[2];
867e71b7053SJung-uk Kim                 unsigned char b[16];
868e71b7053SJung-uk Kim             } t;
869e71b7053SJung-uk Kim             unsigned char h[16];
870e71b7053SJung-uk Kim             unsigned long long taadl;
871e71b7053SJung-uk Kim             unsigned long long tpcl;
872e71b7053SJung-uk Kim             union {
873e71b7053SJung-uk Kim                 unsigned long long g[2];
874e71b7053SJung-uk Kim                 unsigned int w[4];
875e71b7053SJung-uk Kim             } j0;
876e71b7053SJung-uk Kim             unsigned char k[32];
877e71b7053SJung-uk Kim         } param;
878e71b7053SJung-uk Kim         /* KMA-GCM-AES parameter block - end */
879e71b7053SJung-uk Kim     } kma;
880e71b7053SJung-uk Kim     unsigned int fc;
881e71b7053SJung-uk Kim     int key_set;
882e71b7053SJung-uk Kim 
883e71b7053SJung-uk Kim     unsigned char *iv;
884e71b7053SJung-uk Kim     int ivlen;
885e71b7053SJung-uk Kim     int iv_set;
886e71b7053SJung-uk Kim     int iv_gen;
887e71b7053SJung-uk Kim 
888e71b7053SJung-uk Kim     int taglen;
889e71b7053SJung-uk Kim 
890e71b7053SJung-uk Kim     unsigned char ares[16];
891e71b7053SJung-uk Kim     unsigned char mres[16];
892e71b7053SJung-uk Kim     unsigned char kres[16];
893e71b7053SJung-uk Kim     int areslen;
894e71b7053SJung-uk Kim     int mreslen;
895e71b7053SJung-uk Kim     int kreslen;
896e71b7053SJung-uk Kim 
897e71b7053SJung-uk Kim     int tls_aad_len;
898b077aed3SPierre Pronchery     uint64_t tls_enc_records;   /* Number of TLS records encrypted */
899e71b7053SJung-uk Kim } S390X_AES_GCM_CTX;
900e71b7053SJung-uk Kim 
901e71b7053SJung-uk Kim typedef struct {
902e71b7053SJung-uk Kim     union {
903b077aed3SPierre Pronchery         OSSL_UNION_ALIGN;
904e71b7053SJung-uk Kim         /*-
905e71b7053SJung-uk Kim          * Padding is chosen so that ccm.kmac_param.k overlaps with key.k and
906e71b7053SJung-uk Kim          * ccm.fc with key.k.rounds. Remember that on s390x, an AES_KEY's
907e71b7053SJung-uk Kim          * rounds field is used to store the function code and that the key
908e71b7053SJung-uk Kim          * schedule is not stored (if aes hardware support is detected).
909e71b7053SJung-uk Kim          */
910e71b7053SJung-uk Kim         struct {
911e71b7053SJung-uk Kim             unsigned char pad[16];
912e71b7053SJung-uk Kim             AES_KEY k;
913e71b7053SJung-uk Kim         } key;
914e71b7053SJung-uk Kim 
915e71b7053SJung-uk Kim         struct {
916e71b7053SJung-uk Kim             /*-
917e71b7053SJung-uk Kim              * KMAC-AES parameter block - begin
918e71b7053SJung-uk Kim              * (see z/Architecture Principles of Operation >= SA22-7832-08)
919e71b7053SJung-uk Kim              */
920e71b7053SJung-uk Kim             struct {
921e71b7053SJung-uk Kim                 union {
922e71b7053SJung-uk Kim                     unsigned long long g[2];
923e71b7053SJung-uk Kim                     unsigned char b[16];
924e71b7053SJung-uk Kim                 } icv;
925e71b7053SJung-uk Kim                 unsigned char k[32];
926e71b7053SJung-uk Kim             } kmac_param;
92717f01e99SJung-uk Kim             /* KMAC-AES parameter block - end */
928e71b7053SJung-uk Kim 
929e71b7053SJung-uk Kim             union {
930e71b7053SJung-uk Kim                 unsigned long long g[2];
931e71b7053SJung-uk Kim                 unsigned char b[16];
932e71b7053SJung-uk Kim             } nonce;
933e71b7053SJung-uk Kim             union {
934e71b7053SJung-uk Kim                 unsigned long long g[2];
935e71b7053SJung-uk Kim                 unsigned char b[16];
936e71b7053SJung-uk Kim             } buf;
937e71b7053SJung-uk Kim 
938e71b7053SJung-uk Kim             unsigned long long blocks;
939e71b7053SJung-uk Kim             int l;
940e71b7053SJung-uk Kim             int m;
941e71b7053SJung-uk Kim             int tls_aad_len;
942e71b7053SJung-uk Kim             int iv_set;
943e71b7053SJung-uk Kim             int tag_set;
944e71b7053SJung-uk Kim             int len_set;
945e71b7053SJung-uk Kim             int key_set;
946e71b7053SJung-uk Kim 
947e71b7053SJung-uk Kim             unsigned char pad[140];
948e71b7053SJung-uk Kim             unsigned int fc;
949e71b7053SJung-uk Kim         } ccm;
950e71b7053SJung-uk Kim     } aes;
951e71b7053SJung-uk Kim } S390X_AES_CCM_CTX;
952e71b7053SJung-uk Kim 
953e71b7053SJung-uk Kim # define s390x_aes_init_key aes_init_key
954e71b7053SJung-uk Kim static int s390x_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
955e71b7053SJung-uk Kim                               const unsigned char *iv, int enc);
956e71b7053SJung-uk Kim 
957e71b7053SJung-uk Kim # define S390X_AES_CBC_CTX              EVP_AES_KEY
958e71b7053SJung-uk Kim 
959e71b7053SJung-uk Kim # define s390x_aes_cbc_init_key aes_init_key
960e71b7053SJung-uk Kim 
961e71b7053SJung-uk Kim # define s390x_aes_cbc_cipher aes_cbc_cipher
962e71b7053SJung-uk Kim static int s390x_aes_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
963e71b7053SJung-uk Kim                                 const unsigned char *in, size_t len);
964e71b7053SJung-uk Kim 
s390x_aes_ecb_init_key(EVP_CIPHER_CTX * ctx,const unsigned char * key,const unsigned char * iv,int enc)965e71b7053SJung-uk Kim static int s390x_aes_ecb_init_key(EVP_CIPHER_CTX *ctx,
966e71b7053SJung-uk Kim                                   const unsigned char *key,
967e71b7053SJung-uk Kim                                   const unsigned char *iv, int enc)
968e71b7053SJung-uk Kim {
969e71b7053SJung-uk Kim     S390X_AES_ECB_CTX *cctx = EVP_C_DATA(S390X_AES_ECB_CTX, ctx);
970b077aed3SPierre Pronchery     const int keylen = EVP_CIPHER_CTX_get_key_length(ctx);
971e71b7053SJung-uk Kim 
972b077aed3SPierre Pronchery     cctx->fc = S390X_AES_FC(keylen);
973b077aed3SPierre Pronchery     if (!enc)
974b077aed3SPierre Pronchery         cctx->fc |= S390X_DECRYPT;
975e71b7053SJung-uk Kim 
976e71b7053SJung-uk Kim     memcpy(cctx->km.param.k, key, keylen);
977e71b7053SJung-uk Kim     return 1;
978e71b7053SJung-uk Kim }
979e71b7053SJung-uk Kim 
s390x_aes_ecb_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t len)980e71b7053SJung-uk Kim static int s390x_aes_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
981e71b7053SJung-uk Kim                                 const unsigned char *in, size_t len)
982e71b7053SJung-uk Kim {
983e71b7053SJung-uk Kim     S390X_AES_ECB_CTX *cctx = EVP_C_DATA(S390X_AES_ECB_CTX, ctx);
984e71b7053SJung-uk Kim 
985e71b7053SJung-uk Kim     s390x_km(in, len, out, cctx->fc, &cctx->km.param);
986e71b7053SJung-uk Kim     return 1;
987e71b7053SJung-uk Kim }
988e71b7053SJung-uk Kim 
s390x_aes_ofb_init_key(EVP_CIPHER_CTX * ctx,const unsigned char * key,const unsigned char * ivec,int enc)989e71b7053SJung-uk Kim static int s390x_aes_ofb_init_key(EVP_CIPHER_CTX *ctx,
990e71b7053SJung-uk Kim                                   const unsigned char *key,
991e71b7053SJung-uk Kim                                   const unsigned char *ivec, int enc)
992e71b7053SJung-uk Kim {
993e71b7053SJung-uk Kim     S390X_AES_OFB_CTX *cctx = EVP_C_DATA(S390X_AES_OFB_CTX, ctx);
994b077aed3SPierre Pronchery     const unsigned char *iv = ctx->oiv;
995b077aed3SPierre Pronchery     const int keylen = EVP_CIPHER_CTX_get_key_length(ctx);
996b077aed3SPierre Pronchery     const int ivlen = EVP_CIPHER_CTX_get_iv_length(ctx);
997e71b7053SJung-uk Kim 
998b077aed3SPierre Pronchery     memcpy(cctx->kmo.param.cv, iv, ivlen);
9999a3ae0cdSJung-uk Kim     memcpy(cctx->kmo.param.k, key, keylen);
1000b077aed3SPierre Pronchery     cctx->fc = S390X_AES_FC(keylen);
1001e71b7053SJung-uk Kim     return 1;
1002e71b7053SJung-uk Kim }
1003e71b7053SJung-uk Kim 
s390x_aes_ofb_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t len)1004e71b7053SJung-uk Kim static int s390x_aes_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
1005e71b7053SJung-uk Kim                                 const unsigned char *in, size_t len)
1006e71b7053SJung-uk Kim {
1007e71b7053SJung-uk Kim     S390X_AES_OFB_CTX *cctx = EVP_C_DATA(S390X_AES_OFB_CTX, ctx);
1008b077aed3SPierre Pronchery     const int ivlen = EVP_CIPHER_CTX_get_iv_length(ctx);
10099a3ae0cdSJung-uk Kim     unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
1010*e0c4386eSCy Schubert     int n = ctx->num;
1011e71b7053SJung-uk Kim     int rem;
1012e71b7053SJung-uk Kim 
10139a3ae0cdSJung-uk Kim     memcpy(cctx->kmo.param.cv, iv, ivlen);
1014e71b7053SJung-uk Kim     while (n && len) {
1015e71b7053SJung-uk Kim         *out = *in ^ cctx->kmo.param.cv[n];
1016e71b7053SJung-uk Kim         n = (n + 1) & 0xf;
1017e71b7053SJung-uk Kim         --len;
1018e71b7053SJung-uk Kim         ++in;
1019e71b7053SJung-uk Kim         ++out;
1020e71b7053SJung-uk Kim     }
1021e71b7053SJung-uk Kim 
1022e71b7053SJung-uk Kim     rem = len & 0xf;
1023e71b7053SJung-uk Kim 
1024e71b7053SJung-uk Kim     len &= ~(size_t)0xf;
1025e71b7053SJung-uk Kim     if (len) {
1026e71b7053SJung-uk Kim         s390x_kmo(in, len, out, cctx->fc, &cctx->kmo.param);
1027e71b7053SJung-uk Kim 
1028e71b7053SJung-uk Kim         out += len;
1029e71b7053SJung-uk Kim         in += len;
1030e71b7053SJung-uk Kim     }
1031e71b7053SJung-uk Kim 
1032e71b7053SJung-uk Kim     if (rem) {
1033e71b7053SJung-uk Kim         s390x_km(cctx->kmo.param.cv, 16, cctx->kmo.param.cv, cctx->fc,
1034e71b7053SJung-uk Kim                  cctx->kmo.param.k);
1035e71b7053SJung-uk Kim 
1036e71b7053SJung-uk Kim         while (rem--) {
1037e71b7053SJung-uk Kim             out[n] = in[n] ^ cctx->kmo.param.cv[n];
1038e71b7053SJung-uk Kim             ++n;
1039e71b7053SJung-uk Kim         }
1040e71b7053SJung-uk Kim     }
1041e71b7053SJung-uk Kim 
10429a3ae0cdSJung-uk Kim     memcpy(iv, cctx->kmo.param.cv, ivlen);
1043*e0c4386eSCy Schubert     ctx->num = n;
1044e71b7053SJung-uk Kim     return 1;
1045e71b7053SJung-uk Kim }
1046e71b7053SJung-uk Kim 
s390x_aes_cfb_init_key(EVP_CIPHER_CTX * ctx,const unsigned char * key,const unsigned char * ivec,int enc)1047e71b7053SJung-uk Kim static int s390x_aes_cfb_init_key(EVP_CIPHER_CTX *ctx,
1048e71b7053SJung-uk Kim                                   const unsigned char *key,
1049e71b7053SJung-uk Kim                                   const unsigned char *ivec, int enc)
1050e71b7053SJung-uk Kim {
1051e71b7053SJung-uk Kim     S390X_AES_CFB_CTX *cctx = EVP_C_DATA(S390X_AES_CFB_CTX, ctx);
1052b077aed3SPierre Pronchery     const unsigned char *iv = ctx->oiv;
1053b077aed3SPierre Pronchery     const int keylen = EVP_CIPHER_CTX_get_key_length(ctx);
1054b077aed3SPierre Pronchery     const int ivlen = EVP_CIPHER_CTX_get_iv_length(ctx);
1055e71b7053SJung-uk Kim 
1056b077aed3SPierre Pronchery     cctx->fc = S390X_AES_FC(keylen);
1057b077aed3SPierre Pronchery     cctx->fc |= 16 << 24;   /* 16 bytes cipher feedback */
1058b077aed3SPierre Pronchery     if (!enc)
1059b077aed3SPierre Pronchery         cctx->fc |= S390X_DECRYPT;
1060e71b7053SJung-uk Kim 
1061b077aed3SPierre Pronchery     memcpy(cctx->kmf.param.cv, iv, ivlen);
1062b077aed3SPierre Pronchery     memcpy(cctx->kmf.param.k, key, keylen);
1063e71b7053SJung-uk Kim     return 1;
1064e71b7053SJung-uk Kim }
1065e71b7053SJung-uk Kim 
s390x_aes_cfb_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t len)1066e71b7053SJung-uk Kim static int s390x_aes_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
1067e71b7053SJung-uk Kim                                 const unsigned char *in, size_t len)
1068e71b7053SJung-uk Kim {
1069e71b7053SJung-uk Kim     S390X_AES_CFB_CTX *cctx = EVP_C_DATA(S390X_AES_CFB_CTX, ctx);
1070b077aed3SPierre Pronchery     const int keylen = EVP_CIPHER_CTX_get_key_length(ctx);
1071b077aed3SPierre Pronchery     const int enc = EVP_CIPHER_CTX_is_encrypting(ctx);
1072b077aed3SPierre Pronchery     const int ivlen = EVP_CIPHER_CTX_get_iv_length(ctx);
10739a3ae0cdSJung-uk Kim     unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
1074*e0c4386eSCy Schubert     int n = ctx->num;
1075e71b7053SJung-uk Kim     int rem;
1076e71b7053SJung-uk Kim     unsigned char tmp;
1077e71b7053SJung-uk Kim 
10789a3ae0cdSJung-uk Kim     memcpy(cctx->kmf.param.cv, iv, ivlen);
1079e71b7053SJung-uk Kim     while (n && len) {
1080e71b7053SJung-uk Kim         tmp = *in;
1081e71b7053SJung-uk Kim         *out = cctx->kmf.param.cv[n] ^ tmp;
1082e71b7053SJung-uk Kim         cctx->kmf.param.cv[n] = enc ? *out : tmp;
1083e71b7053SJung-uk Kim         n = (n + 1) & 0xf;
1084e71b7053SJung-uk Kim         --len;
1085e71b7053SJung-uk Kim         ++in;
1086e71b7053SJung-uk Kim         ++out;
1087e71b7053SJung-uk Kim     }
1088e71b7053SJung-uk Kim 
1089e71b7053SJung-uk Kim     rem = len & 0xf;
1090e71b7053SJung-uk Kim 
1091e71b7053SJung-uk Kim     len &= ~(size_t)0xf;
1092e71b7053SJung-uk Kim     if (len) {
1093e71b7053SJung-uk Kim         s390x_kmf(in, len, out, cctx->fc, &cctx->kmf.param);
1094e71b7053SJung-uk Kim 
1095e71b7053SJung-uk Kim         out += len;
1096e71b7053SJung-uk Kim         in += len;
1097e71b7053SJung-uk Kim     }
1098e71b7053SJung-uk Kim 
1099e71b7053SJung-uk Kim     if (rem) {
1100e71b7053SJung-uk Kim         s390x_km(cctx->kmf.param.cv, 16, cctx->kmf.param.cv,
1101e71b7053SJung-uk Kim                  S390X_AES_FC(keylen), cctx->kmf.param.k);
1102e71b7053SJung-uk Kim 
1103e71b7053SJung-uk Kim         while (rem--) {
1104e71b7053SJung-uk Kim             tmp = in[n];
1105e71b7053SJung-uk Kim             out[n] = cctx->kmf.param.cv[n] ^ tmp;
1106e71b7053SJung-uk Kim             cctx->kmf.param.cv[n] = enc ? out[n] : tmp;
1107e71b7053SJung-uk Kim             ++n;
1108e71b7053SJung-uk Kim         }
1109e71b7053SJung-uk Kim     }
1110e71b7053SJung-uk Kim 
11119a3ae0cdSJung-uk Kim     memcpy(iv, cctx->kmf.param.cv, ivlen);
1112*e0c4386eSCy Schubert     ctx->num = n;
1113e71b7053SJung-uk Kim     return 1;
1114e71b7053SJung-uk Kim }
1115e71b7053SJung-uk Kim 
s390x_aes_cfb8_init_key(EVP_CIPHER_CTX * ctx,const unsigned char * key,const unsigned char * ivec,int enc)1116e71b7053SJung-uk Kim static int s390x_aes_cfb8_init_key(EVP_CIPHER_CTX *ctx,
1117e71b7053SJung-uk Kim                                    const unsigned char *key,
1118e71b7053SJung-uk Kim                                    const unsigned char *ivec, int enc)
1119e71b7053SJung-uk Kim {
1120e71b7053SJung-uk Kim     S390X_AES_CFB_CTX *cctx = EVP_C_DATA(S390X_AES_CFB_CTX, ctx);
1121b077aed3SPierre Pronchery     const unsigned char *iv = ctx->oiv;
1122b077aed3SPierre Pronchery     const int keylen = EVP_CIPHER_CTX_get_key_length(ctx);
1123b077aed3SPierre Pronchery     const int ivlen = EVP_CIPHER_CTX_get_iv_length(ctx);
1124e71b7053SJung-uk Kim 
1125b077aed3SPierre Pronchery     cctx->fc = S390X_AES_FC(keylen);
1126b077aed3SPierre Pronchery     cctx->fc |= 1 << 24;   /* 1 byte cipher feedback */
1127b077aed3SPierre Pronchery     if (!enc)
1128b077aed3SPierre Pronchery         cctx->fc |= S390X_DECRYPT;
1129e71b7053SJung-uk Kim 
1130b077aed3SPierre Pronchery     memcpy(cctx->kmf.param.cv, iv, ivlen);
1131e71b7053SJung-uk Kim     memcpy(cctx->kmf.param.k, key, keylen);
1132e71b7053SJung-uk Kim     return 1;
1133e71b7053SJung-uk Kim }
1134e71b7053SJung-uk Kim 
s390x_aes_cfb8_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t len)1135e71b7053SJung-uk Kim static int s390x_aes_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
1136e71b7053SJung-uk Kim                                  const unsigned char *in, size_t len)
1137e71b7053SJung-uk Kim {
1138e71b7053SJung-uk Kim     S390X_AES_CFB_CTX *cctx = EVP_C_DATA(S390X_AES_CFB_CTX, ctx);
1139b077aed3SPierre Pronchery     const int ivlen = EVP_CIPHER_CTX_get_iv_length(ctx);
11409a3ae0cdSJung-uk Kim     unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
1141e71b7053SJung-uk Kim 
11429a3ae0cdSJung-uk Kim     memcpy(cctx->kmf.param.cv, iv, ivlen);
1143e71b7053SJung-uk Kim     s390x_kmf(in, len, out, cctx->fc, &cctx->kmf.param);
11449a3ae0cdSJung-uk Kim     memcpy(iv, cctx->kmf.param.cv, ivlen);
1145e71b7053SJung-uk Kim     return 1;
1146e71b7053SJung-uk Kim }
1147e71b7053SJung-uk Kim 
1148e71b7053SJung-uk Kim # define s390x_aes_cfb1_init_key aes_init_key
1149e71b7053SJung-uk Kim 
1150e71b7053SJung-uk Kim # define s390x_aes_cfb1_cipher aes_cfb1_cipher
1151e71b7053SJung-uk Kim static int s390x_aes_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
1152e71b7053SJung-uk Kim                                  const unsigned char *in, size_t len);
1153e71b7053SJung-uk Kim 
1154e71b7053SJung-uk Kim # define S390X_AES_CTR_CTX              EVP_AES_KEY
1155e71b7053SJung-uk Kim 
1156e71b7053SJung-uk Kim # define s390x_aes_ctr_init_key aes_init_key
1157e71b7053SJung-uk Kim 
1158e71b7053SJung-uk Kim # define s390x_aes_ctr_cipher aes_ctr_cipher
1159e71b7053SJung-uk Kim static int s390x_aes_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
1160e71b7053SJung-uk Kim                                 const unsigned char *in, size_t len);
1161e71b7053SJung-uk Kim 
116217f01e99SJung-uk Kim /* iv + padding length for iv lengths != 12 */
1163e71b7053SJung-uk Kim # define S390X_gcm_ivpadlen(i)  ((((i) + 15) >> 4 << 4) + 16)
1164e71b7053SJung-uk Kim 
1165e71b7053SJung-uk Kim /*-
1166e71b7053SJung-uk Kim  * Process additional authenticated data. Returns 0 on success. Code is
1167e71b7053SJung-uk Kim  * big-endian.
1168e71b7053SJung-uk Kim  */
s390x_aes_gcm_aad(S390X_AES_GCM_CTX * ctx,const unsigned char * aad,size_t len)1169e71b7053SJung-uk Kim static int s390x_aes_gcm_aad(S390X_AES_GCM_CTX *ctx, const unsigned char *aad,
1170e71b7053SJung-uk Kim                              size_t len)
1171e71b7053SJung-uk Kim {
1172e71b7053SJung-uk Kim     unsigned long long alen;
1173e71b7053SJung-uk Kim     int n, rem;
1174e71b7053SJung-uk Kim 
1175e71b7053SJung-uk Kim     if (ctx->kma.param.tpcl)
1176e71b7053SJung-uk Kim         return -2;
1177e71b7053SJung-uk Kim 
1178e71b7053SJung-uk Kim     alen = ctx->kma.param.taadl + len;
1179e71b7053SJung-uk Kim     if (alen > (U64(1) << 61) || (sizeof(len) == 8 && alen < len))
1180e71b7053SJung-uk Kim         return -1;
1181e71b7053SJung-uk Kim     ctx->kma.param.taadl = alen;
1182e71b7053SJung-uk Kim 
1183e71b7053SJung-uk Kim     n = ctx->areslen;
1184e71b7053SJung-uk Kim     if (n) {
1185e71b7053SJung-uk Kim         while (n && len) {
1186e71b7053SJung-uk Kim             ctx->ares[n] = *aad;
1187e71b7053SJung-uk Kim             n = (n + 1) & 0xf;
1188e71b7053SJung-uk Kim             ++aad;
1189e71b7053SJung-uk Kim             --len;
1190e71b7053SJung-uk Kim         }
1191e71b7053SJung-uk Kim         /* ctx->ares contains a complete block if offset has wrapped around */
1192e71b7053SJung-uk Kim         if (!n) {
1193e71b7053SJung-uk Kim             s390x_kma(ctx->ares, 16, NULL, 0, NULL, ctx->fc, &ctx->kma.param);
1194e71b7053SJung-uk Kim             ctx->fc |= S390X_KMA_HS;
1195e71b7053SJung-uk Kim         }
1196e71b7053SJung-uk Kim         ctx->areslen = n;
1197e71b7053SJung-uk Kim     }
1198e71b7053SJung-uk Kim 
1199e71b7053SJung-uk Kim     rem = len & 0xf;
1200e71b7053SJung-uk Kim 
1201e71b7053SJung-uk Kim     len &= ~(size_t)0xf;
1202e71b7053SJung-uk Kim     if (len) {
1203e71b7053SJung-uk Kim         s390x_kma(aad, len, NULL, 0, NULL, ctx->fc, &ctx->kma.param);
1204e71b7053SJung-uk Kim         aad += len;
1205e71b7053SJung-uk Kim         ctx->fc |= S390X_KMA_HS;
1206e71b7053SJung-uk Kim     }
1207e71b7053SJung-uk Kim 
1208e71b7053SJung-uk Kim     if (rem) {
1209e71b7053SJung-uk Kim         ctx->areslen = rem;
1210e71b7053SJung-uk Kim 
1211e71b7053SJung-uk Kim         do {
1212e71b7053SJung-uk Kim             --rem;
1213e71b7053SJung-uk Kim             ctx->ares[rem] = aad[rem];
1214e71b7053SJung-uk Kim         } while (rem);
1215e71b7053SJung-uk Kim     }
1216e71b7053SJung-uk Kim     return 0;
1217e71b7053SJung-uk Kim }
1218e71b7053SJung-uk Kim 
1219e71b7053SJung-uk Kim /*-
1220e71b7053SJung-uk Kim  * En/de-crypt plain/cipher-text and authenticate ciphertext. Returns 0 for
1221e71b7053SJung-uk Kim  * success. Code is big-endian.
1222e71b7053SJung-uk Kim  */
s390x_aes_gcm(S390X_AES_GCM_CTX * ctx,const unsigned char * in,unsigned char * out,size_t len)1223e71b7053SJung-uk Kim static int s390x_aes_gcm(S390X_AES_GCM_CTX *ctx, const unsigned char *in,
1224e71b7053SJung-uk Kim                          unsigned char *out, size_t len)
1225e71b7053SJung-uk Kim {
1226e71b7053SJung-uk Kim     const unsigned char *inptr;
1227e71b7053SJung-uk Kim     unsigned long long mlen;
1228e71b7053SJung-uk Kim     union {
1229e71b7053SJung-uk Kim         unsigned int w[4];
1230e71b7053SJung-uk Kim         unsigned char b[16];
1231e71b7053SJung-uk Kim     } buf;
1232e71b7053SJung-uk Kim     size_t inlen;
1233e71b7053SJung-uk Kim     int n, rem, i;
1234e71b7053SJung-uk Kim 
1235e71b7053SJung-uk Kim     mlen = ctx->kma.param.tpcl + len;
1236e71b7053SJung-uk Kim     if (mlen > ((U64(1) << 36) - 32) || (sizeof(len) == 8 && mlen < len))
1237e71b7053SJung-uk Kim         return -1;
1238e71b7053SJung-uk Kim     ctx->kma.param.tpcl = mlen;
1239e71b7053SJung-uk Kim 
1240e71b7053SJung-uk Kim     n = ctx->mreslen;
1241e71b7053SJung-uk Kim     if (n) {
1242e71b7053SJung-uk Kim         inptr = in;
1243e71b7053SJung-uk Kim         inlen = len;
1244e71b7053SJung-uk Kim         while (n && inlen) {
1245e71b7053SJung-uk Kim             ctx->mres[n] = *inptr;
1246e71b7053SJung-uk Kim             n = (n + 1) & 0xf;
1247e71b7053SJung-uk Kim             ++inptr;
1248e71b7053SJung-uk Kim             --inlen;
1249e71b7053SJung-uk Kim         }
1250e71b7053SJung-uk Kim         /* ctx->mres contains a complete block if offset has wrapped around */
1251e71b7053SJung-uk Kim         if (!n) {
1252e71b7053SJung-uk Kim             s390x_kma(ctx->ares, ctx->areslen, ctx->mres, 16, buf.b,
1253e71b7053SJung-uk Kim                       ctx->fc | S390X_KMA_LAAD, &ctx->kma.param);
1254e71b7053SJung-uk Kim             ctx->fc |= S390X_KMA_HS;
1255e71b7053SJung-uk Kim             ctx->areslen = 0;
1256e71b7053SJung-uk Kim 
1257e71b7053SJung-uk Kim             /* previous call already encrypted/decrypted its remainder,
1258e71b7053SJung-uk Kim              * see comment below */
1259e71b7053SJung-uk Kim             n = ctx->mreslen;
1260e71b7053SJung-uk Kim             while (n) {
1261e71b7053SJung-uk Kim                 *out = buf.b[n];
1262e71b7053SJung-uk Kim                 n = (n + 1) & 0xf;
1263e71b7053SJung-uk Kim                 ++out;
1264e71b7053SJung-uk Kim                 ++in;
1265e71b7053SJung-uk Kim                 --len;
1266e71b7053SJung-uk Kim             }
1267e71b7053SJung-uk Kim             ctx->mreslen = 0;
1268e71b7053SJung-uk Kim         }
1269e71b7053SJung-uk Kim     }
1270e71b7053SJung-uk Kim 
1271e71b7053SJung-uk Kim     rem = len & 0xf;
1272e71b7053SJung-uk Kim 
1273e71b7053SJung-uk Kim     len &= ~(size_t)0xf;
1274e71b7053SJung-uk Kim     if (len) {
1275e71b7053SJung-uk Kim         s390x_kma(ctx->ares, ctx->areslen, in, len, out,
1276e71b7053SJung-uk Kim                   ctx->fc | S390X_KMA_LAAD, &ctx->kma.param);
1277e71b7053SJung-uk Kim         in += len;
1278e71b7053SJung-uk Kim         out += len;
1279e71b7053SJung-uk Kim         ctx->fc |= S390X_KMA_HS;
1280e71b7053SJung-uk Kim         ctx->areslen = 0;
1281e71b7053SJung-uk Kim     }
1282e71b7053SJung-uk Kim 
1283e71b7053SJung-uk Kim     /*-
1284e71b7053SJung-uk Kim      * If there is a remainder, it has to be saved such that it can be
1285e71b7053SJung-uk Kim      * processed by kma later. However, we also have to do the for-now
1286e71b7053SJung-uk Kim      * unauthenticated encryption/decryption part here and now...
1287e71b7053SJung-uk Kim      */
1288e71b7053SJung-uk Kim     if (rem) {
1289e71b7053SJung-uk Kim         if (!ctx->mreslen) {
1290e71b7053SJung-uk Kim             buf.w[0] = ctx->kma.param.j0.w[0];
1291e71b7053SJung-uk Kim             buf.w[1] = ctx->kma.param.j0.w[1];
1292e71b7053SJung-uk Kim             buf.w[2] = ctx->kma.param.j0.w[2];
1293e71b7053SJung-uk Kim             buf.w[3] = ctx->kma.param.cv.w + 1;
1294e71b7053SJung-uk Kim             s390x_km(buf.b, 16, ctx->kres, ctx->fc & 0x1f, &ctx->kma.param.k);
1295e71b7053SJung-uk Kim         }
1296e71b7053SJung-uk Kim 
1297e71b7053SJung-uk Kim         n = ctx->mreslen;
1298e71b7053SJung-uk Kim         for (i = 0; i < rem; i++) {
1299e71b7053SJung-uk Kim             ctx->mres[n + i] = in[i];
1300e71b7053SJung-uk Kim             out[i] = in[i] ^ ctx->kres[n + i];
1301e71b7053SJung-uk Kim         }
1302e71b7053SJung-uk Kim 
1303e71b7053SJung-uk Kim         ctx->mreslen += rem;
1304e71b7053SJung-uk Kim     }
1305e71b7053SJung-uk Kim     return 0;
1306e71b7053SJung-uk Kim }
1307e71b7053SJung-uk Kim 
1308e71b7053SJung-uk Kim /*-
1309e71b7053SJung-uk Kim  * Initialize context structure. Code is big-endian.
1310e71b7053SJung-uk Kim  */
s390x_aes_gcm_setiv(S390X_AES_GCM_CTX * ctx,const unsigned char * iv)1311b077aed3SPierre Pronchery static void s390x_aes_gcm_setiv(S390X_AES_GCM_CTX *ctx,
1312b077aed3SPierre Pronchery                                 const unsigned char *iv)
1313e71b7053SJung-uk Kim {
1314e71b7053SJung-uk Kim     ctx->kma.param.t.g[0] = 0;
1315e71b7053SJung-uk Kim     ctx->kma.param.t.g[1] = 0;
1316e71b7053SJung-uk Kim     ctx->kma.param.tpcl = 0;
1317e71b7053SJung-uk Kim     ctx->kma.param.taadl = 0;
1318e71b7053SJung-uk Kim     ctx->mreslen = 0;
1319e71b7053SJung-uk Kim     ctx->areslen = 0;
1320e71b7053SJung-uk Kim     ctx->kreslen = 0;
1321e71b7053SJung-uk Kim 
1322e71b7053SJung-uk Kim     if (ctx->ivlen == 12) {
1323b077aed3SPierre Pronchery         memcpy(&ctx->kma.param.j0, iv, ctx->ivlen);
1324e71b7053SJung-uk Kim         ctx->kma.param.j0.w[3] = 1;
1325e71b7053SJung-uk Kim         ctx->kma.param.cv.w = 1;
1326e71b7053SJung-uk Kim     } else {
1327e71b7053SJung-uk Kim         /* ctx->iv has the right size and is already padded. */
1328b077aed3SPierre Pronchery         memcpy(ctx->iv, iv, ctx->ivlen);
1329e71b7053SJung-uk Kim         s390x_kma(ctx->iv, S390X_gcm_ivpadlen(ctx->ivlen), NULL, 0, NULL,
1330e71b7053SJung-uk Kim                   ctx->fc, &ctx->kma.param);
1331e71b7053SJung-uk Kim         ctx->fc |= S390X_KMA_HS;
1332e71b7053SJung-uk Kim 
1333e71b7053SJung-uk Kim         ctx->kma.param.j0.g[0] = ctx->kma.param.t.g[0];
1334e71b7053SJung-uk Kim         ctx->kma.param.j0.g[1] = ctx->kma.param.t.g[1];
1335e71b7053SJung-uk Kim         ctx->kma.param.cv.w = ctx->kma.param.j0.w[3];
1336e71b7053SJung-uk Kim         ctx->kma.param.t.g[0] = 0;
1337e71b7053SJung-uk Kim         ctx->kma.param.t.g[1] = 0;
1338e71b7053SJung-uk Kim     }
1339e71b7053SJung-uk Kim }
1340e71b7053SJung-uk Kim 
1341e71b7053SJung-uk Kim /*-
1342e71b7053SJung-uk Kim  * Performs various operations on the context structure depending on control
1343e71b7053SJung-uk Kim  * type. Returns 1 for success, 0 for failure and -1 for unknown control type.
1344e71b7053SJung-uk Kim  * Code is big-endian.
1345e71b7053SJung-uk Kim  */
s390x_aes_gcm_ctrl(EVP_CIPHER_CTX * c,int type,int arg,void * ptr)1346e71b7053SJung-uk Kim static int s390x_aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
1347e71b7053SJung-uk Kim {
1348e71b7053SJung-uk Kim     S390X_AES_GCM_CTX *gctx = EVP_C_DATA(S390X_AES_GCM_CTX, c);
1349e71b7053SJung-uk Kim     S390X_AES_GCM_CTX *gctx_out;
1350e71b7053SJung-uk Kim     EVP_CIPHER_CTX *out;
1351b077aed3SPierre Pronchery     unsigned char *buf;
1352e71b7053SJung-uk Kim     int ivlen, enc, len;
1353e71b7053SJung-uk Kim 
1354e71b7053SJung-uk Kim     switch (type) {
1355e71b7053SJung-uk Kim     case EVP_CTRL_INIT:
1356b077aed3SPierre Pronchery         ivlen = EVP_CIPHER_get_iv_length(c->cipher);
1357e71b7053SJung-uk Kim         gctx->key_set = 0;
1358e71b7053SJung-uk Kim         gctx->iv_set = 0;
1359e71b7053SJung-uk Kim         gctx->ivlen = ivlen;
1360b077aed3SPierre Pronchery         gctx->iv = c->iv;
1361e71b7053SJung-uk Kim         gctx->taglen = -1;
1362e71b7053SJung-uk Kim         gctx->iv_gen = 0;
1363e71b7053SJung-uk Kim         gctx->tls_aad_len = -1;
1364e71b7053SJung-uk Kim         return 1;
1365e71b7053SJung-uk Kim 
1366da327cd2SJung-uk Kim     case EVP_CTRL_GET_IVLEN:
1367da327cd2SJung-uk Kim         *(int *)ptr = gctx->ivlen;
1368da327cd2SJung-uk Kim         return 1;
1369da327cd2SJung-uk Kim 
1370e71b7053SJung-uk Kim     case EVP_CTRL_AEAD_SET_IVLEN:
1371e71b7053SJung-uk Kim         if (arg <= 0)
1372e71b7053SJung-uk Kim             return 0;
1373e71b7053SJung-uk Kim 
1374e71b7053SJung-uk Kim         if (arg != 12) {
1375e71b7053SJung-uk Kim             len = S390X_gcm_ivpadlen(arg);
1376e71b7053SJung-uk Kim 
1377e71b7053SJung-uk Kim             /* Allocate memory for iv if needed. */
1378e71b7053SJung-uk Kim             if (gctx->ivlen == 12 || len > S390X_gcm_ivpadlen(gctx->ivlen)) {
1379b077aed3SPierre Pronchery                 if (gctx->iv != c->iv)
1380e71b7053SJung-uk Kim                     OPENSSL_free(gctx->iv);
1381e71b7053SJung-uk Kim 
1382e71b7053SJung-uk Kim                 if ((gctx->iv = OPENSSL_malloc(len)) == NULL) {
1383b077aed3SPierre Pronchery                     ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
1384e71b7053SJung-uk Kim                     return 0;
1385e71b7053SJung-uk Kim                 }
1386e71b7053SJung-uk Kim             }
1387e71b7053SJung-uk Kim             /* Add padding. */
1388e71b7053SJung-uk Kim             memset(gctx->iv + arg, 0, len - arg - 8);
1389e71b7053SJung-uk Kim             *((unsigned long long *)(gctx->iv + len - 8)) = arg << 3;
1390e71b7053SJung-uk Kim         }
1391e71b7053SJung-uk Kim         gctx->ivlen = arg;
1392e71b7053SJung-uk Kim         return 1;
1393e71b7053SJung-uk Kim 
1394e71b7053SJung-uk Kim     case EVP_CTRL_AEAD_SET_TAG:
1395e71b7053SJung-uk Kim         buf = EVP_CIPHER_CTX_buf_noconst(c);
1396b077aed3SPierre Pronchery         enc = EVP_CIPHER_CTX_is_encrypting(c);
1397e71b7053SJung-uk Kim         if (arg <= 0 || arg > 16 || enc)
1398e71b7053SJung-uk Kim             return 0;
1399e71b7053SJung-uk Kim 
1400e71b7053SJung-uk Kim         memcpy(buf, ptr, arg);
1401e71b7053SJung-uk Kim         gctx->taglen = arg;
1402e71b7053SJung-uk Kim         return 1;
1403e71b7053SJung-uk Kim 
1404e71b7053SJung-uk Kim     case EVP_CTRL_AEAD_GET_TAG:
1405b077aed3SPierre Pronchery         enc = EVP_CIPHER_CTX_is_encrypting(c);
1406e71b7053SJung-uk Kim         if (arg <= 0 || arg > 16 || !enc || gctx->taglen < 0)
1407e71b7053SJung-uk Kim             return 0;
1408e71b7053SJung-uk Kim 
1409e71b7053SJung-uk Kim         memcpy(ptr, gctx->kma.param.t.b, arg);
1410e71b7053SJung-uk Kim         return 1;
1411e71b7053SJung-uk Kim 
1412e71b7053SJung-uk Kim     case EVP_CTRL_GCM_SET_IV_FIXED:
1413e71b7053SJung-uk Kim         /* Special case: -1 length restores whole iv */
1414e71b7053SJung-uk Kim         if (arg == -1) {
1415e71b7053SJung-uk Kim             memcpy(gctx->iv, ptr, gctx->ivlen);
1416e71b7053SJung-uk Kim             gctx->iv_gen = 1;
1417e71b7053SJung-uk Kim             return 1;
1418e71b7053SJung-uk Kim         }
1419e71b7053SJung-uk Kim         /*
1420e71b7053SJung-uk Kim          * Fixed field must be at least 4 bytes and invocation field at least
1421e71b7053SJung-uk Kim          * 8.
1422e71b7053SJung-uk Kim          */
1423e71b7053SJung-uk Kim         if ((arg < 4) || (gctx->ivlen - arg) < 8)
1424e71b7053SJung-uk Kim             return 0;
1425e71b7053SJung-uk Kim 
1426e71b7053SJung-uk Kim         if (arg)
1427e71b7053SJung-uk Kim             memcpy(gctx->iv, ptr, arg);
1428e71b7053SJung-uk Kim 
1429b077aed3SPierre Pronchery         enc = EVP_CIPHER_CTX_is_encrypting(c);
1430e71b7053SJung-uk Kim         if (enc && RAND_bytes(gctx->iv + arg, gctx->ivlen - arg) <= 0)
1431e71b7053SJung-uk Kim             return 0;
1432e71b7053SJung-uk Kim 
1433e71b7053SJung-uk Kim         gctx->iv_gen = 1;
1434e71b7053SJung-uk Kim         return 1;
1435e71b7053SJung-uk Kim 
1436e71b7053SJung-uk Kim     case EVP_CTRL_GCM_IV_GEN:
1437e71b7053SJung-uk Kim         if (gctx->iv_gen == 0 || gctx->key_set == 0)
1438e71b7053SJung-uk Kim             return 0;
1439e71b7053SJung-uk Kim 
1440b077aed3SPierre Pronchery         s390x_aes_gcm_setiv(gctx, gctx->iv);
1441e71b7053SJung-uk Kim 
1442e71b7053SJung-uk Kim         if (arg <= 0 || arg > gctx->ivlen)
1443e71b7053SJung-uk Kim             arg = gctx->ivlen;
1444e71b7053SJung-uk Kim 
1445e71b7053SJung-uk Kim         memcpy(ptr, gctx->iv + gctx->ivlen - arg, arg);
1446e71b7053SJung-uk Kim         /*
1447e71b7053SJung-uk Kim          * Invocation field will be at least 8 bytes in size and so no need
1448e71b7053SJung-uk Kim          * to check wrap around or increment more than last 8 bytes.
1449e71b7053SJung-uk Kim          */
1450e71b7053SJung-uk Kim         ctr64_inc(gctx->iv + gctx->ivlen - 8);
1451e71b7053SJung-uk Kim         gctx->iv_set = 1;
1452e71b7053SJung-uk Kim         return 1;
1453e71b7053SJung-uk Kim 
1454e71b7053SJung-uk Kim     case EVP_CTRL_GCM_SET_IV_INV:
1455b077aed3SPierre Pronchery         enc = EVP_CIPHER_CTX_is_encrypting(c);
1456e71b7053SJung-uk Kim         if (gctx->iv_gen == 0 || gctx->key_set == 0 || enc)
1457e71b7053SJung-uk Kim             return 0;
1458e71b7053SJung-uk Kim 
1459e71b7053SJung-uk Kim         memcpy(gctx->iv + gctx->ivlen - arg, ptr, arg);
1460b077aed3SPierre Pronchery         s390x_aes_gcm_setiv(gctx, gctx->iv);
1461e71b7053SJung-uk Kim         gctx->iv_set = 1;
1462e71b7053SJung-uk Kim         return 1;
1463e71b7053SJung-uk Kim 
1464e71b7053SJung-uk Kim     case EVP_CTRL_AEAD_TLS1_AAD:
1465e71b7053SJung-uk Kim         /* Save the aad for later use. */
1466e71b7053SJung-uk Kim         if (arg != EVP_AEAD_TLS1_AAD_LEN)
1467e71b7053SJung-uk Kim             return 0;
1468e71b7053SJung-uk Kim 
1469e71b7053SJung-uk Kim         buf = EVP_CIPHER_CTX_buf_noconst(c);
1470e71b7053SJung-uk Kim         memcpy(buf, ptr, arg);
1471e71b7053SJung-uk Kim         gctx->tls_aad_len = arg;
1472b077aed3SPierre Pronchery         gctx->tls_enc_records = 0;
1473e71b7053SJung-uk Kim 
1474e71b7053SJung-uk Kim         len = buf[arg - 2] << 8 | buf[arg - 1];
1475e71b7053SJung-uk Kim         /* Correct length for explicit iv. */
1476e71b7053SJung-uk Kim         if (len < EVP_GCM_TLS_EXPLICIT_IV_LEN)
1477e71b7053SJung-uk Kim             return 0;
1478e71b7053SJung-uk Kim         len -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
1479e71b7053SJung-uk Kim 
1480e71b7053SJung-uk Kim         /* If decrypting correct for tag too. */
1481b077aed3SPierre Pronchery         enc = EVP_CIPHER_CTX_is_encrypting(c);
1482e71b7053SJung-uk Kim         if (!enc) {
1483e71b7053SJung-uk Kim             if (len < EVP_GCM_TLS_TAG_LEN)
1484e71b7053SJung-uk Kim                 return 0;
1485e71b7053SJung-uk Kim             len -= EVP_GCM_TLS_TAG_LEN;
1486e71b7053SJung-uk Kim         }
1487e71b7053SJung-uk Kim         buf[arg - 2] = len >> 8;
1488e71b7053SJung-uk Kim         buf[arg - 1] = len & 0xff;
1489e71b7053SJung-uk Kim         /* Extra padding: tag appended to record. */
1490e71b7053SJung-uk Kim         return EVP_GCM_TLS_TAG_LEN;
1491e71b7053SJung-uk Kim 
1492e71b7053SJung-uk Kim     case EVP_CTRL_COPY:
1493e71b7053SJung-uk Kim         out = ptr;
1494e71b7053SJung-uk Kim         gctx_out = EVP_C_DATA(S390X_AES_GCM_CTX, out);
1495e71b7053SJung-uk Kim 
1496b077aed3SPierre Pronchery         if (gctx->iv == c->iv) {
1497b077aed3SPierre Pronchery             gctx_out->iv = out->iv;
1498e71b7053SJung-uk Kim         } else {
1499e71b7053SJung-uk Kim             len = S390X_gcm_ivpadlen(gctx->ivlen);
1500e71b7053SJung-uk Kim 
1501e71b7053SJung-uk Kim             if ((gctx_out->iv = OPENSSL_malloc(len)) == NULL) {
1502b077aed3SPierre Pronchery                 ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
1503e71b7053SJung-uk Kim                 return 0;
1504e71b7053SJung-uk Kim             }
1505e71b7053SJung-uk Kim 
1506e71b7053SJung-uk Kim             memcpy(gctx_out->iv, gctx->iv, len);
1507e71b7053SJung-uk Kim         }
1508e71b7053SJung-uk Kim         return 1;
1509e71b7053SJung-uk Kim 
1510e71b7053SJung-uk Kim     default:
1511e71b7053SJung-uk Kim         return -1;
1512e71b7053SJung-uk Kim     }
1513e71b7053SJung-uk Kim }
1514e71b7053SJung-uk Kim 
1515e71b7053SJung-uk Kim /*-
1516b077aed3SPierre Pronchery  * Set key and/or iv. Returns 1 on success. Otherwise 0 is returned.
1517e71b7053SJung-uk Kim  */
s390x_aes_gcm_init_key(EVP_CIPHER_CTX * ctx,const unsigned char * key,const unsigned char * iv,int enc)1518e71b7053SJung-uk Kim static int s390x_aes_gcm_init_key(EVP_CIPHER_CTX *ctx,
1519e71b7053SJung-uk Kim                                   const unsigned char *key,
1520e71b7053SJung-uk Kim                                   const unsigned char *iv, int enc)
1521e71b7053SJung-uk Kim {
1522e71b7053SJung-uk Kim     S390X_AES_GCM_CTX *gctx = EVP_C_DATA(S390X_AES_GCM_CTX, ctx);
1523b077aed3SPierre Pronchery     int keylen;
1524e71b7053SJung-uk Kim 
1525b077aed3SPierre Pronchery     if (iv == NULL && key == NULL)
1526b077aed3SPierre Pronchery         return 1;
1527e71b7053SJung-uk Kim 
1528e71b7053SJung-uk Kim     if (key != NULL) {
1529b077aed3SPierre Pronchery         keylen = EVP_CIPHER_CTX_get_key_length(ctx);
1530e71b7053SJung-uk Kim         memcpy(&gctx->kma.param.k, key, keylen);
1531b077aed3SPierre Pronchery 
1532b077aed3SPierre Pronchery         gctx->fc = S390X_AES_FC(keylen);
1533b077aed3SPierre Pronchery         if (!enc)
1534b077aed3SPierre Pronchery             gctx->fc |= S390X_DECRYPT;
1535b077aed3SPierre Pronchery 
1536b077aed3SPierre Pronchery         if (iv == NULL && gctx->iv_set)
1537b077aed3SPierre Pronchery             iv = gctx->iv;
1538e71b7053SJung-uk Kim 
1539e71b7053SJung-uk Kim         if (iv != NULL) {
1540b077aed3SPierre Pronchery             s390x_aes_gcm_setiv(gctx, iv);
15419a3ae0cdSJung-uk Kim             gctx->iv_set = 1;
1542e71b7053SJung-uk Kim         }
1543b077aed3SPierre Pronchery         gctx->key_set = 1;
1544b077aed3SPierre Pronchery     } else {
1545b077aed3SPierre Pronchery         if (gctx->key_set)
1546b077aed3SPierre Pronchery             s390x_aes_gcm_setiv(gctx, iv);
1547b077aed3SPierre Pronchery         else
1548b077aed3SPierre Pronchery             memcpy(gctx->iv, iv, gctx->ivlen);
15499a3ae0cdSJung-uk Kim 
1550b077aed3SPierre Pronchery         gctx->iv_set = 1;
1551b077aed3SPierre Pronchery         gctx->iv_gen = 0;
1552b077aed3SPierre Pronchery     }
1553e71b7053SJung-uk Kim     return 1;
1554e71b7053SJung-uk Kim }
1555e71b7053SJung-uk Kim 
1556e71b7053SJung-uk Kim /*-
1557e71b7053SJung-uk Kim  * En/de-crypt and authenticate TLS packet. Returns the number of bytes written
1558e71b7053SJung-uk Kim  * if successful. Otherwise -1 is returned. Code is big-endian.
1559e71b7053SJung-uk Kim  */
s390x_aes_gcm_tls_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t len)1560e71b7053SJung-uk Kim static int s390x_aes_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
1561e71b7053SJung-uk Kim                                     const unsigned char *in, size_t len)
1562e71b7053SJung-uk Kim {
1563e71b7053SJung-uk Kim     S390X_AES_GCM_CTX *gctx = EVP_C_DATA(S390X_AES_GCM_CTX, ctx);
1564e71b7053SJung-uk Kim     const unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx);
1565b077aed3SPierre Pronchery     const int enc = EVP_CIPHER_CTX_is_encrypting(ctx);
1566e71b7053SJung-uk Kim     int rv = -1;
1567e71b7053SJung-uk Kim 
1568e71b7053SJung-uk Kim     if (out != in || len < (EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN))
1569e71b7053SJung-uk Kim         return -1;
1570e71b7053SJung-uk Kim 
1571b077aed3SPierre Pronchery     /*
1572b077aed3SPierre Pronchery      * Check for too many keys as per FIPS 140-2 IG A.5 "Key/IV Pair Uniqueness
1573b077aed3SPierre Pronchery      * Requirements from SP 800-38D".  The requirements is for one party to the
1574b077aed3SPierre Pronchery      * communication to fail after 2^64 - 1 keys.  We do this on the encrypting
1575b077aed3SPierre Pronchery      * side only.
1576b077aed3SPierre Pronchery      */
1577b077aed3SPierre Pronchery     if (ctx->encrypt && ++gctx->tls_enc_records == 0) {
1578b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, EVP_R_TOO_MANY_RECORDS);
1579b077aed3SPierre Pronchery         goto err;
1580b077aed3SPierre Pronchery     }
1581b077aed3SPierre Pronchery 
1582e71b7053SJung-uk Kim     if (EVP_CIPHER_CTX_ctrl(ctx, enc ? EVP_CTRL_GCM_IV_GEN
1583e71b7053SJung-uk Kim                                      : EVP_CTRL_GCM_SET_IV_INV,
1584e71b7053SJung-uk Kim                             EVP_GCM_TLS_EXPLICIT_IV_LEN, out) <= 0)
1585e71b7053SJung-uk Kim         goto err;
1586e71b7053SJung-uk Kim 
1587e71b7053SJung-uk Kim     in += EVP_GCM_TLS_EXPLICIT_IV_LEN;
1588e71b7053SJung-uk Kim     out += EVP_GCM_TLS_EXPLICIT_IV_LEN;
1589e71b7053SJung-uk Kim     len -= EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
1590e71b7053SJung-uk Kim 
1591e71b7053SJung-uk Kim     gctx->kma.param.taadl = gctx->tls_aad_len << 3;
1592e71b7053SJung-uk Kim     gctx->kma.param.tpcl = len << 3;
1593e71b7053SJung-uk Kim     s390x_kma(buf, gctx->tls_aad_len, in, len, out,
1594e71b7053SJung-uk Kim               gctx->fc | S390X_KMA_LAAD | S390X_KMA_LPC, &gctx->kma.param);
1595e71b7053SJung-uk Kim 
1596e71b7053SJung-uk Kim     if (enc) {
1597e71b7053SJung-uk Kim         memcpy(out + len, gctx->kma.param.t.b, EVP_GCM_TLS_TAG_LEN);
1598e71b7053SJung-uk Kim         rv = len + EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
1599e71b7053SJung-uk Kim     } else {
1600e71b7053SJung-uk Kim         if (CRYPTO_memcmp(gctx->kma.param.t.b, in + len,
1601e71b7053SJung-uk Kim                           EVP_GCM_TLS_TAG_LEN)) {
1602e71b7053SJung-uk Kim             OPENSSL_cleanse(out, len);
1603e71b7053SJung-uk Kim             goto err;
1604e71b7053SJung-uk Kim         }
1605e71b7053SJung-uk Kim         rv = len;
1606e71b7053SJung-uk Kim     }
1607e71b7053SJung-uk Kim err:
1608e71b7053SJung-uk Kim     gctx->iv_set = 0;
1609e71b7053SJung-uk Kim     gctx->tls_aad_len = -1;
1610e71b7053SJung-uk Kim     return rv;
1611e71b7053SJung-uk Kim }
1612e71b7053SJung-uk Kim 
1613e71b7053SJung-uk Kim /*-
1614e71b7053SJung-uk Kim  * Called from EVP layer to initialize context, process additional
1615e71b7053SJung-uk Kim  * authenticated data, en/de-crypt plain/cipher-text and authenticate
1616e71b7053SJung-uk Kim  * ciphertext or process a TLS packet, depending on context. Returns bytes
1617e71b7053SJung-uk Kim  * written on success. Otherwise -1 is returned. Code is big-endian.
1618e71b7053SJung-uk Kim  */
s390x_aes_gcm_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t len)1619e71b7053SJung-uk Kim static int s390x_aes_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
1620e71b7053SJung-uk Kim                                 const unsigned char *in, size_t len)
1621e71b7053SJung-uk Kim {
1622e71b7053SJung-uk Kim     S390X_AES_GCM_CTX *gctx = EVP_C_DATA(S390X_AES_GCM_CTX, ctx);
1623e71b7053SJung-uk Kim     unsigned char *buf, tmp[16];
1624e71b7053SJung-uk Kim     int enc;
1625e71b7053SJung-uk Kim 
1626e71b7053SJung-uk Kim     if (!gctx->key_set)
1627e71b7053SJung-uk Kim         return -1;
1628e71b7053SJung-uk Kim 
1629e71b7053SJung-uk Kim     if (gctx->tls_aad_len >= 0)
1630e71b7053SJung-uk Kim         return s390x_aes_gcm_tls_cipher(ctx, out, in, len);
1631e71b7053SJung-uk Kim 
1632e71b7053SJung-uk Kim     if (!gctx->iv_set)
1633e71b7053SJung-uk Kim         return -1;
1634e71b7053SJung-uk Kim 
1635e71b7053SJung-uk Kim     if (in != NULL) {
1636e71b7053SJung-uk Kim         if (out == NULL) {
1637e71b7053SJung-uk Kim             if (s390x_aes_gcm_aad(gctx, in, len))
1638e71b7053SJung-uk Kim                 return -1;
1639e71b7053SJung-uk Kim         } else {
1640e71b7053SJung-uk Kim             if (s390x_aes_gcm(gctx, in, out, len))
1641e71b7053SJung-uk Kim                 return -1;
1642e71b7053SJung-uk Kim         }
1643e71b7053SJung-uk Kim         return len;
1644e71b7053SJung-uk Kim     } else {
1645e71b7053SJung-uk Kim         gctx->kma.param.taadl <<= 3;
1646e71b7053SJung-uk Kim         gctx->kma.param.tpcl <<= 3;
1647e71b7053SJung-uk Kim         s390x_kma(gctx->ares, gctx->areslen, gctx->mres, gctx->mreslen, tmp,
1648e71b7053SJung-uk Kim                   gctx->fc | S390X_KMA_LAAD | S390X_KMA_LPC, &gctx->kma.param);
1649e71b7053SJung-uk Kim         /* recall that we already did en-/decrypt gctx->mres
1650e71b7053SJung-uk Kim          * and returned it to caller... */
1651e71b7053SJung-uk Kim         OPENSSL_cleanse(tmp, gctx->mreslen);
1652b077aed3SPierre Pronchery         gctx->iv_set = 0;
1653e71b7053SJung-uk Kim 
1654b077aed3SPierre Pronchery         enc = EVP_CIPHER_CTX_is_encrypting(ctx);
1655e71b7053SJung-uk Kim         if (enc) {
1656e71b7053SJung-uk Kim             gctx->taglen = 16;
1657e71b7053SJung-uk Kim         } else {
1658e71b7053SJung-uk Kim             if (gctx->taglen < 0)
1659e71b7053SJung-uk Kim                 return -1;
1660e71b7053SJung-uk Kim 
1661e71b7053SJung-uk Kim             buf = EVP_CIPHER_CTX_buf_noconst(ctx);
1662e71b7053SJung-uk Kim             if (CRYPTO_memcmp(buf, gctx->kma.param.t.b, gctx->taglen))
1663e71b7053SJung-uk Kim                 return -1;
1664e71b7053SJung-uk Kim         }
1665e71b7053SJung-uk Kim         return 0;
1666e71b7053SJung-uk Kim     }
1667e71b7053SJung-uk Kim }
1668e71b7053SJung-uk Kim 
s390x_aes_gcm_cleanup(EVP_CIPHER_CTX * c)1669e71b7053SJung-uk Kim static int s390x_aes_gcm_cleanup(EVP_CIPHER_CTX *c)
1670e71b7053SJung-uk Kim {
1671e71b7053SJung-uk Kim     S390X_AES_GCM_CTX *gctx = EVP_C_DATA(S390X_AES_GCM_CTX, c);
1672e71b7053SJung-uk Kim 
1673e71b7053SJung-uk Kim     if (gctx == NULL)
1674e71b7053SJung-uk Kim         return 0;
1675e71b7053SJung-uk Kim 
1676b077aed3SPierre Pronchery     if (gctx->iv != c->iv)
1677e71b7053SJung-uk Kim         OPENSSL_free(gctx->iv);
1678e71b7053SJung-uk Kim 
1679e71b7053SJung-uk Kim     OPENSSL_cleanse(gctx, sizeof(*gctx));
1680e71b7053SJung-uk Kim     return 1;
1681e71b7053SJung-uk Kim }
1682e71b7053SJung-uk Kim 
1683e71b7053SJung-uk Kim # define S390X_AES_XTS_CTX              EVP_AES_XTS_CTX
1684e71b7053SJung-uk Kim 
1685e71b7053SJung-uk Kim # define s390x_aes_xts_init_key aes_xts_init_key
1686e71b7053SJung-uk Kim static int s390x_aes_xts_init_key(EVP_CIPHER_CTX *ctx,
1687e71b7053SJung-uk Kim                                   const unsigned char *key,
1688e71b7053SJung-uk Kim                                   const unsigned char *iv, int enc);
1689e71b7053SJung-uk Kim # define s390x_aes_xts_cipher aes_xts_cipher
1690e71b7053SJung-uk Kim static int s390x_aes_xts_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
1691e71b7053SJung-uk Kim                                 const unsigned char *in, size_t len);
1692e71b7053SJung-uk Kim # define s390x_aes_xts_ctrl aes_xts_ctrl
1693e71b7053SJung-uk Kim static int s390x_aes_xts_ctrl(EVP_CIPHER_CTX *, int type, int arg, void *ptr);
1694e71b7053SJung-uk Kim # define s390x_aes_xts_cleanup aes_xts_cleanup
1695e71b7053SJung-uk Kim 
1696e71b7053SJung-uk Kim /*-
1697e71b7053SJung-uk Kim  * Set nonce and length fields. Code is big-endian.
1698e71b7053SJung-uk Kim  */
s390x_aes_ccm_setiv(S390X_AES_CCM_CTX * ctx,const unsigned char * nonce,size_t mlen)1699e71b7053SJung-uk Kim static inline void s390x_aes_ccm_setiv(S390X_AES_CCM_CTX *ctx,
1700e71b7053SJung-uk Kim                                           const unsigned char *nonce,
1701e71b7053SJung-uk Kim                                           size_t mlen)
1702e71b7053SJung-uk Kim {
1703e71b7053SJung-uk Kim     ctx->aes.ccm.nonce.b[0] &= ~S390X_CCM_AAD_FLAG;
1704e71b7053SJung-uk Kim     ctx->aes.ccm.nonce.g[1] = mlen;
1705e71b7053SJung-uk Kim     memcpy(ctx->aes.ccm.nonce.b + 1, nonce, 15 - ctx->aes.ccm.l);
1706e71b7053SJung-uk Kim }
1707e71b7053SJung-uk Kim 
1708e71b7053SJung-uk Kim /*-
1709e71b7053SJung-uk Kim  * Process additional authenticated data. Code is big-endian.
1710e71b7053SJung-uk Kim  */
s390x_aes_ccm_aad(S390X_AES_CCM_CTX * ctx,const unsigned char * aad,size_t alen)1711e71b7053SJung-uk Kim static void s390x_aes_ccm_aad(S390X_AES_CCM_CTX *ctx, const unsigned char *aad,
1712e71b7053SJung-uk Kim                               size_t alen)
1713e71b7053SJung-uk Kim {
1714e71b7053SJung-uk Kim     unsigned char *ptr;
1715e71b7053SJung-uk Kim     int i, rem;
1716e71b7053SJung-uk Kim 
1717e71b7053SJung-uk Kim     if (!alen)
1718e71b7053SJung-uk Kim         return;
1719e71b7053SJung-uk Kim 
1720e71b7053SJung-uk Kim     ctx->aes.ccm.nonce.b[0] |= S390X_CCM_AAD_FLAG;
1721e71b7053SJung-uk Kim 
1722e71b7053SJung-uk Kim     /* Suppress 'type-punned pointer dereference' warning. */
1723e71b7053SJung-uk Kim     ptr = ctx->aes.ccm.buf.b;
1724e71b7053SJung-uk Kim 
1725e71b7053SJung-uk Kim     if (alen < ((1 << 16) - (1 << 8))) {
1726e71b7053SJung-uk Kim         *(uint16_t *)ptr = alen;
1727e71b7053SJung-uk Kim         i = 2;
1728e71b7053SJung-uk Kim     } else if (sizeof(alen) == 8
1729e71b7053SJung-uk Kim                && alen >= (size_t)1 << (32 % (sizeof(alen) * 8))) {
1730e71b7053SJung-uk Kim         *(uint16_t *)ptr = 0xffff;
1731e71b7053SJung-uk Kim         *(uint64_t *)(ptr + 2) = alen;
1732e71b7053SJung-uk Kim         i = 10;
1733e71b7053SJung-uk Kim     } else {
1734e71b7053SJung-uk Kim         *(uint16_t *)ptr = 0xfffe;
1735e71b7053SJung-uk Kim         *(uint32_t *)(ptr + 2) = alen;
1736e71b7053SJung-uk Kim         i = 6;
1737e71b7053SJung-uk Kim     }
1738e71b7053SJung-uk Kim 
1739e71b7053SJung-uk Kim     while (i < 16 && alen) {
1740e71b7053SJung-uk Kim         ctx->aes.ccm.buf.b[i] = *aad;
1741e71b7053SJung-uk Kim         ++aad;
1742e71b7053SJung-uk Kim         --alen;
1743e71b7053SJung-uk Kim         ++i;
1744e71b7053SJung-uk Kim     }
1745e71b7053SJung-uk Kim     while (i < 16) {
1746e71b7053SJung-uk Kim         ctx->aes.ccm.buf.b[i] = 0;
1747e71b7053SJung-uk Kim         ++i;
1748e71b7053SJung-uk Kim     }
1749e71b7053SJung-uk Kim 
1750e71b7053SJung-uk Kim     ctx->aes.ccm.kmac_param.icv.g[0] = 0;
1751e71b7053SJung-uk Kim     ctx->aes.ccm.kmac_param.icv.g[1] = 0;
1752e71b7053SJung-uk Kim     s390x_kmac(ctx->aes.ccm.nonce.b, 32, ctx->aes.ccm.fc,
1753e71b7053SJung-uk Kim                &ctx->aes.ccm.kmac_param);
1754e71b7053SJung-uk Kim     ctx->aes.ccm.blocks += 2;
1755e71b7053SJung-uk Kim 
1756e71b7053SJung-uk Kim     rem = alen & 0xf;
1757e71b7053SJung-uk Kim     alen &= ~(size_t)0xf;
1758e71b7053SJung-uk Kim     if (alen) {
1759e71b7053SJung-uk Kim         s390x_kmac(aad, alen, ctx->aes.ccm.fc, &ctx->aes.ccm.kmac_param);
1760e71b7053SJung-uk Kim         ctx->aes.ccm.blocks += alen >> 4;
1761e71b7053SJung-uk Kim         aad += alen;
1762e71b7053SJung-uk Kim     }
1763e71b7053SJung-uk Kim     if (rem) {
1764e71b7053SJung-uk Kim         for (i = 0; i < rem; i++)
1765e71b7053SJung-uk Kim             ctx->aes.ccm.kmac_param.icv.b[i] ^= aad[i];
1766e71b7053SJung-uk Kim 
1767e71b7053SJung-uk Kim         s390x_km(ctx->aes.ccm.kmac_param.icv.b, 16,
1768e71b7053SJung-uk Kim                  ctx->aes.ccm.kmac_param.icv.b, ctx->aes.ccm.fc,
1769e71b7053SJung-uk Kim                  ctx->aes.ccm.kmac_param.k);
1770e71b7053SJung-uk Kim         ctx->aes.ccm.blocks++;
1771e71b7053SJung-uk Kim     }
1772e71b7053SJung-uk Kim }
1773e71b7053SJung-uk Kim 
1774e71b7053SJung-uk Kim /*-
1775e71b7053SJung-uk Kim  * En/de-crypt plain/cipher-text. Compute tag from plaintext. Returns 0 for
1776e71b7053SJung-uk Kim  * success.
1777e71b7053SJung-uk Kim  */
s390x_aes_ccm(S390X_AES_CCM_CTX * ctx,const unsigned char * in,unsigned char * out,size_t len,int enc)1778e71b7053SJung-uk Kim static int s390x_aes_ccm(S390X_AES_CCM_CTX *ctx, const unsigned char *in,
1779e71b7053SJung-uk Kim                          unsigned char *out, size_t len, int enc)
1780e71b7053SJung-uk Kim {
1781e71b7053SJung-uk Kim     size_t n, rem;
1782e71b7053SJung-uk Kim     unsigned int i, l, num;
1783e71b7053SJung-uk Kim     unsigned char flags;
1784e71b7053SJung-uk Kim 
1785e71b7053SJung-uk Kim     flags = ctx->aes.ccm.nonce.b[0];
1786e71b7053SJung-uk Kim     if (!(flags & S390X_CCM_AAD_FLAG)) {
1787e71b7053SJung-uk Kim         s390x_km(ctx->aes.ccm.nonce.b, 16, ctx->aes.ccm.kmac_param.icv.b,
1788e71b7053SJung-uk Kim                  ctx->aes.ccm.fc, ctx->aes.ccm.kmac_param.k);
1789e71b7053SJung-uk Kim         ctx->aes.ccm.blocks++;
1790e71b7053SJung-uk Kim     }
1791e71b7053SJung-uk Kim     l = flags & 0x7;
1792e71b7053SJung-uk Kim     ctx->aes.ccm.nonce.b[0] = l;
1793e71b7053SJung-uk Kim 
1794e71b7053SJung-uk Kim     /*-
1795e71b7053SJung-uk Kim      * Reconstruct length from encoded length field
1796e71b7053SJung-uk Kim      * and initialize it with counter value.
1797e71b7053SJung-uk Kim      */
1798e71b7053SJung-uk Kim     n = 0;
1799e71b7053SJung-uk Kim     for (i = 15 - l; i < 15; i++) {
1800e71b7053SJung-uk Kim         n |= ctx->aes.ccm.nonce.b[i];
1801e71b7053SJung-uk Kim         ctx->aes.ccm.nonce.b[i] = 0;
1802e71b7053SJung-uk Kim         n <<= 8;
1803e71b7053SJung-uk Kim     }
1804e71b7053SJung-uk Kim     n |= ctx->aes.ccm.nonce.b[15];
1805e71b7053SJung-uk Kim     ctx->aes.ccm.nonce.b[15] = 1;
1806e71b7053SJung-uk Kim 
1807e71b7053SJung-uk Kim     if (n != len)
1808e71b7053SJung-uk Kim         return -1;              /* length mismatch */
1809e71b7053SJung-uk Kim 
1810e71b7053SJung-uk Kim     if (enc) {
1811e71b7053SJung-uk Kim         /* Two operations per block plus one for tag encryption */
1812e71b7053SJung-uk Kim         ctx->aes.ccm.blocks += (((len + 15) >> 4) << 1) + 1;
1813e71b7053SJung-uk Kim         if (ctx->aes.ccm.blocks > (1ULL << 61))
1814e71b7053SJung-uk Kim             return -2;          /* too much data */
1815e71b7053SJung-uk Kim     }
1816e71b7053SJung-uk Kim 
1817e71b7053SJung-uk Kim     num = 0;
1818e71b7053SJung-uk Kim     rem = len & 0xf;
1819e71b7053SJung-uk Kim     len &= ~(size_t)0xf;
1820e71b7053SJung-uk Kim 
1821e71b7053SJung-uk Kim     if (enc) {
1822e71b7053SJung-uk Kim         /* mac-then-encrypt */
1823e71b7053SJung-uk Kim         if (len)
1824e71b7053SJung-uk Kim             s390x_kmac(in, len, ctx->aes.ccm.fc, &ctx->aes.ccm.kmac_param);
1825e71b7053SJung-uk Kim         if (rem) {
1826e71b7053SJung-uk Kim             for (i = 0; i < rem; i++)
1827e71b7053SJung-uk Kim                 ctx->aes.ccm.kmac_param.icv.b[i] ^= in[len + i];
1828e71b7053SJung-uk Kim 
1829e71b7053SJung-uk Kim             s390x_km(ctx->aes.ccm.kmac_param.icv.b, 16,
1830e71b7053SJung-uk Kim                      ctx->aes.ccm.kmac_param.icv.b, ctx->aes.ccm.fc,
1831e71b7053SJung-uk Kim                      ctx->aes.ccm.kmac_param.k);
1832e71b7053SJung-uk Kim         }
1833e71b7053SJung-uk Kim 
1834e71b7053SJung-uk Kim         CRYPTO_ctr128_encrypt_ctr32(in, out, len + rem, &ctx->aes.key.k,
1835e71b7053SJung-uk Kim                                     ctx->aes.ccm.nonce.b, ctx->aes.ccm.buf.b,
1836e71b7053SJung-uk Kim                                     &num, (ctr128_f)AES_ctr32_encrypt);
1837e71b7053SJung-uk Kim     } else {
1838e71b7053SJung-uk Kim         /* decrypt-then-mac */
1839e71b7053SJung-uk Kim         CRYPTO_ctr128_encrypt_ctr32(in, out, len + rem, &ctx->aes.key.k,
1840e71b7053SJung-uk Kim                                     ctx->aes.ccm.nonce.b, ctx->aes.ccm.buf.b,
1841e71b7053SJung-uk Kim                                     &num, (ctr128_f)AES_ctr32_encrypt);
1842e71b7053SJung-uk Kim 
1843e71b7053SJung-uk Kim         if (len)
1844e71b7053SJung-uk Kim             s390x_kmac(out, len, ctx->aes.ccm.fc, &ctx->aes.ccm.kmac_param);
1845e71b7053SJung-uk Kim         if (rem) {
1846e71b7053SJung-uk Kim             for (i = 0; i < rem; i++)
1847e71b7053SJung-uk Kim                 ctx->aes.ccm.kmac_param.icv.b[i] ^= out[len + i];
1848e71b7053SJung-uk Kim 
1849e71b7053SJung-uk Kim             s390x_km(ctx->aes.ccm.kmac_param.icv.b, 16,
1850e71b7053SJung-uk Kim                      ctx->aes.ccm.kmac_param.icv.b, ctx->aes.ccm.fc,
1851e71b7053SJung-uk Kim                      ctx->aes.ccm.kmac_param.k);
1852e71b7053SJung-uk Kim         }
1853e71b7053SJung-uk Kim     }
1854e71b7053SJung-uk Kim     /* encrypt tag */
1855e71b7053SJung-uk Kim     for (i = 15 - l; i < 16; i++)
1856e71b7053SJung-uk Kim         ctx->aes.ccm.nonce.b[i] = 0;
1857e71b7053SJung-uk Kim 
1858e71b7053SJung-uk Kim     s390x_km(ctx->aes.ccm.nonce.b, 16, ctx->aes.ccm.buf.b, ctx->aes.ccm.fc,
1859e71b7053SJung-uk Kim              ctx->aes.ccm.kmac_param.k);
1860e71b7053SJung-uk Kim     ctx->aes.ccm.kmac_param.icv.g[0] ^= ctx->aes.ccm.buf.g[0];
1861e71b7053SJung-uk Kim     ctx->aes.ccm.kmac_param.icv.g[1] ^= ctx->aes.ccm.buf.g[1];
1862e71b7053SJung-uk Kim 
1863e71b7053SJung-uk Kim     ctx->aes.ccm.nonce.b[0] = flags;    /* restore flags field */
1864e71b7053SJung-uk Kim     return 0;
1865e71b7053SJung-uk Kim }
1866e71b7053SJung-uk Kim 
1867e71b7053SJung-uk Kim /*-
1868e71b7053SJung-uk Kim  * En/de-crypt and authenticate TLS packet. Returns the number of bytes written
1869e71b7053SJung-uk Kim  * if successful. Otherwise -1 is returned.
1870e71b7053SJung-uk Kim  */
s390x_aes_ccm_tls_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t len)1871e71b7053SJung-uk Kim static int s390x_aes_ccm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
1872e71b7053SJung-uk Kim                                     const unsigned char *in, size_t len)
1873e71b7053SJung-uk Kim {
1874e71b7053SJung-uk Kim     S390X_AES_CCM_CTX *cctx = EVP_C_DATA(S390X_AES_CCM_CTX, ctx);
1875b077aed3SPierre Pronchery     unsigned char *ivec = ctx->iv;
1876e71b7053SJung-uk Kim     unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx);
1877b077aed3SPierre Pronchery     const int enc = EVP_CIPHER_CTX_is_encrypting(ctx);
1878e71b7053SJung-uk Kim 
1879e71b7053SJung-uk Kim     if (out != in
1880e71b7053SJung-uk Kim             || len < (EVP_CCM_TLS_EXPLICIT_IV_LEN + (size_t)cctx->aes.ccm.m))
1881e71b7053SJung-uk Kim         return -1;
1882e71b7053SJung-uk Kim 
1883e71b7053SJung-uk Kim     if (enc) {
1884e71b7053SJung-uk Kim         /* Set explicit iv (sequence number). */
1885e71b7053SJung-uk Kim         memcpy(out, buf, EVP_CCM_TLS_EXPLICIT_IV_LEN);
1886e71b7053SJung-uk Kim     }
1887e71b7053SJung-uk Kim 
1888e71b7053SJung-uk Kim     len -= EVP_CCM_TLS_EXPLICIT_IV_LEN + cctx->aes.ccm.m;
1889e71b7053SJung-uk Kim     /*-
1890e71b7053SJung-uk Kim      * Get explicit iv (sequence number). We already have fixed iv
1891e71b7053SJung-uk Kim      * (server/client_write_iv) here.
1892e71b7053SJung-uk Kim      */
1893b077aed3SPierre Pronchery     memcpy(ivec + EVP_CCM_TLS_FIXED_IV_LEN, in, EVP_CCM_TLS_EXPLICIT_IV_LEN);
1894b077aed3SPierre Pronchery     s390x_aes_ccm_setiv(cctx, ivec, len);
1895e71b7053SJung-uk Kim 
1896e71b7053SJung-uk Kim     /* Process aad (sequence number|type|version|length) */
1897e71b7053SJung-uk Kim     s390x_aes_ccm_aad(cctx, buf, cctx->aes.ccm.tls_aad_len);
1898e71b7053SJung-uk Kim 
1899e71b7053SJung-uk Kim     in += EVP_CCM_TLS_EXPLICIT_IV_LEN;
1900e71b7053SJung-uk Kim     out += EVP_CCM_TLS_EXPLICIT_IV_LEN;
1901e71b7053SJung-uk Kim 
1902e71b7053SJung-uk Kim     if (enc) {
1903e71b7053SJung-uk Kim         if (s390x_aes_ccm(cctx, in, out, len, enc))
1904e71b7053SJung-uk Kim             return -1;
1905e71b7053SJung-uk Kim 
1906e71b7053SJung-uk Kim         memcpy(out + len, cctx->aes.ccm.kmac_param.icv.b, cctx->aes.ccm.m);
1907e71b7053SJung-uk Kim         return len + EVP_CCM_TLS_EXPLICIT_IV_LEN + cctx->aes.ccm.m;
1908e71b7053SJung-uk Kim     } else {
1909e71b7053SJung-uk Kim         if (!s390x_aes_ccm(cctx, in, out, len, enc)) {
1910e71b7053SJung-uk Kim             if (!CRYPTO_memcmp(cctx->aes.ccm.kmac_param.icv.b, in + len,
1911e71b7053SJung-uk Kim                                cctx->aes.ccm.m))
1912e71b7053SJung-uk Kim                 return len;
1913e71b7053SJung-uk Kim         }
1914e71b7053SJung-uk Kim 
1915e71b7053SJung-uk Kim         OPENSSL_cleanse(out, len);
1916e71b7053SJung-uk Kim         return -1;
1917e71b7053SJung-uk Kim     }
1918e71b7053SJung-uk Kim }
1919e71b7053SJung-uk Kim 
1920e71b7053SJung-uk Kim /*-
1921b077aed3SPierre Pronchery  * Set key and flag field and/or iv. Returns 1 if successful. Otherwise 0 is
1922b077aed3SPierre Pronchery  * returned.
1923e71b7053SJung-uk Kim  */
s390x_aes_ccm_init_key(EVP_CIPHER_CTX * ctx,const unsigned char * key,const unsigned char * iv,int enc)1924e71b7053SJung-uk Kim static int s390x_aes_ccm_init_key(EVP_CIPHER_CTX *ctx,
1925e71b7053SJung-uk Kim                                   const unsigned char *key,
1926e71b7053SJung-uk Kim                                   const unsigned char *iv, int enc)
1927e71b7053SJung-uk Kim {
1928e71b7053SJung-uk Kim     S390X_AES_CCM_CTX *cctx = EVP_C_DATA(S390X_AES_CCM_CTX, ctx);
1929b077aed3SPierre Pronchery     int keylen;
1930e71b7053SJung-uk Kim 
1931b077aed3SPierre Pronchery     if (iv == NULL && key == NULL)
1932b077aed3SPierre Pronchery         return 1;
1933e71b7053SJung-uk Kim 
1934e71b7053SJung-uk Kim     if (key != NULL) {
1935b077aed3SPierre Pronchery         keylen = EVP_CIPHER_CTX_get_key_length(ctx);
1936b077aed3SPierre Pronchery         cctx->aes.ccm.fc = S390X_AES_FC(keylen);
1937e71b7053SJung-uk Kim         memcpy(cctx->aes.ccm.kmac_param.k, key, keylen);
1938e71b7053SJung-uk Kim 
1939e71b7053SJung-uk Kim         /* Store encoded m and l. */
1940e71b7053SJung-uk Kim         cctx->aes.ccm.nonce.b[0] = ((cctx->aes.ccm.l - 1) & 0x7)
1941e71b7053SJung-uk Kim                                  | (((cctx->aes.ccm.m - 2) >> 1) & 0x7) << 3;
1942b077aed3SPierre Pronchery         memset(cctx->aes.ccm.nonce.b + 1, 0,
1943b077aed3SPierre Pronchery                sizeof(cctx->aes.ccm.nonce.b));
1944e71b7053SJung-uk Kim         cctx->aes.ccm.blocks = 0;
1945b077aed3SPierre Pronchery 
1946b077aed3SPierre Pronchery         cctx->aes.ccm.key_set = 1;
1947b077aed3SPierre Pronchery     }
1948b077aed3SPierre Pronchery 
1949b077aed3SPierre Pronchery     if (iv != NULL) {
1950b077aed3SPierre Pronchery         memcpy(ctx->iv, iv, 15 - cctx->aes.ccm.l);
1951b077aed3SPierre Pronchery 
1952b077aed3SPierre Pronchery         cctx->aes.ccm.iv_set = 1;
1953b077aed3SPierre Pronchery     }
1954b077aed3SPierre Pronchery 
1955e71b7053SJung-uk Kim     return 1;
1956e71b7053SJung-uk Kim }
1957e71b7053SJung-uk Kim 
1958e71b7053SJung-uk Kim /*-
1959e71b7053SJung-uk Kim  * Called from EVP layer to initialize context, process additional
1960e71b7053SJung-uk Kim  * authenticated data, en/de-crypt plain/cipher-text and authenticate
1961e71b7053SJung-uk Kim  * plaintext or process a TLS packet, depending on context. Returns bytes
1962e71b7053SJung-uk Kim  * written on success. Otherwise -1 is returned.
1963e71b7053SJung-uk Kim  */
s390x_aes_ccm_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t len)1964e71b7053SJung-uk Kim static int s390x_aes_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
1965e71b7053SJung-uk Kim                                 const unsigned char *in, size_t len)
1966e71b7053SJung-uk Kim {
1967e71b7053SJung-uk Kim     S390X_AES_CCM_CTX *cctx = EVP_C_DATA(S390X_AES_CCM_CTX, ctx);
1968b077aed3SPierre Pronchery     const int enc = EVP_CIPHER_CTX_is_encrypting(ctx);
1969e71b7053SJung-uk Kim     int rv;
1970b077aed3SPierre Pronchery     unsigned char *buf;
1971e71b7053SJung-uk Kim 
1972e71b7053SJung-uk Kim     if (!cctx->aes.ccm.key_set)
1973e71b7053SJung-uk Kim         return -1;
1974e71b7053SJung-uk Kim 
1975e71b7053SJung-uk Kim     if (cctx->aes.ccm.tls_aad_len >= 0)
1976e71b7053SJung-uk Kim         return s390x_aes_ccm_tls_cipher(ctx, out, in, len);
1977e71b7053SJung-uk Kim 
1978e71b7053SJung-uk Kim     /*-
1979e71b7053SJung-uk Kim      * Final(): Does not return any data. Recall that ccm is mac-then-encrypt
1980e71b7053SJung-uk Kim      * so integrity must be checked already at Update() i.e., before
1981e71b7053SJung-uk Kim      * potentially corrupted data is output.
1982e71b7053SJung-uk Kim      */
1983e71b7053SJung-uk Kim     if (in == NULL && out != NULL)
1984e71b7053SJung-uk Kim         return 0;
1985e71b7053SJung-uk Kim 
1986e71b7053SJung-uk Kim     if (!cctx->aes.ccm.iv_set)
1987e71b7053SJung-uk Kim         return -1;
1988e71b7053SJung-uk Kim 
1989e71b7053SJung-uk Kim     if (out == NULL) {
1990e71b7053SJung-uk Kim         /* Update(): Pass message length. */
1991e71b7053SJung-uk Kim         if (in == NULL) {
1992b077aed3SPierre Pronchery             s390x_aes_ccm_setiv(cctx, ctx->iv, len);
1993e71b7053SJung-uk Kim 
1994e71b7053SJung-uk Kim             cctx->aes.ccm.len_set = 1;
1995e71b7053SJung-uk Kim             return len;
1996e71b7053SJung-uk Kim         }
1997e71b7053SJung-uk Kim 
1998e71b7053SJung-uk Kim         /* Update(): Process aad. */
1999e71b7053SJung-uk Kim         if (!cctx->aes.ccm.len_set && len)
2000e71b7053SJung-uk Kim             return -1;
2001e71b7053SJung-uk Kim 
2002e71b7053SJung-uk Kim         s390x_aes_ccm_aad(cctx, in, len);
2003e71b7053SJung-uk Kim         return len;
2004e71b7053SJung-uk Kim     }
2005e71b7053SJung-uk Kim 
2006610a21fdSJung-uk Kim     /* The tag must be set before actually decrypting data */
2007610a21fdSJung-uk Kim     if (!enc && !cctx->aes.ccm.tag_set)
2008610a21fdSJung-uk Kim         return -1;
2009610a21fdSJung-uk Kim 
2010e71b7053SJung-uk Kim     /* Update(): Process message. */
2011e71b7053SJung-uk Kim 
2012e71b7053SJung-uk Kim     if (!cctx->aes.ccm.len_set) {
2013e71b7053SJung-uk Kim         /*-
2014c9cf7b5cSJung-uk Kim          * In case message length was not previously set explicitly via
2015e71b7053SJung-uk Kim          * Update(), set it now.
2016e71b7053SJung-uk Kim          */
2017b077aed3SPierre Pronchery         s390x_aes_ccm_setiv(cctx, ctx->iv, len);
2018e71b7053SJung-uk Kim 
2019e71b7053SJung-uk Kim         cctx->aes.ccm.len_set = 1;
2020e71b7053SJung-uk Kim     }
2021e71b7053SJung-uk Kim 
2022e71b7053SJung-uk Kim     if (enc) {
2023e71b7053SJung-uk Kim         if (s390x_aes_ccm(cctx, in, out, len, enc))
2024e71b7053SJung-uk Kim             return -1;
2025e71b7053SJung-uk Kim 
2026e71b7053SJung-uk Kim         cctx->aes.ccm.tag_set = 1;
2027e71b7053SJung-uk Kim         return len;
2028e71b7053SJung-uk Kim     } else {
2029e71b7053SJung-uk Kim         rv = -1;
2030e71b7053SJung-uk Kim 
2031e71b7053SJung-uk Kim         if (!s390x_aes_ccm(cctx, in, out, len, enc)) {
2032e71b7053SJung-uk Kim             buf = EVP_CIPHER_CTX_buf_noconst(ctx);
2033e71b7053SJung-uk Kim             if (!CRYPTO_memcmp(cctx->aes.ccm.kmac_param.icv.b, buf,
2034e71b7053SJung-uk Kim                                cctx->aes.ccm.m))
2035e71b7053SJung-uk Kim                 rv = len;
2036e71b7053SJung-uk Kim         }
2037e71b7053SJung-uk Kim 
2038e71b7053SJung-uk Kim         if (rv == -1)
2039e71b7053SJung-uk Kim             OPENSSL_cleanse(out, len);
2040e71b7053SJung-uk Kim 
2041b077aed3SPierre Pronchery         cctx->aes.ccm.iv_set = 0;
2042b077aed3SPierre Pronchery         cctx->aes.ccm.tag_set = 0;
2043b077aed3SPierre Pronchery         cctx->aes.ccm.len_set = 0;
2044e71b7053SJung-uk Kim         return rv;
2045e71b7053SJung-uk Kim     }
2046e71b7053SJung-uk Kim }
2047e71b7053SJung-uk Kim 
2048e71b7053SJung-uk Kim /*-
2049e71b7053SJung-uk Kim  * Performs various operations on the context structure depending on control
2050e71b7053SJung-uk Kim  * type. Returns 1 for success, 0 for failure and -1 for unknown control type.
2051e71b7053SJung-uk Kim  * Code is big-endian.
2052e71b7053SJung-uk Kim  */
s390x_aes_ccm_ctrl(EVP_CIPHER_CTX * c,int type,int arg,void * ptr)2053e71b7053SJung-uk Kim static int s390x_aes_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
2054e71b7053SJung-uk Kim {
2055e71b7053SJung-uk Kim     S390X_AES_CCM_CTX *cctx = EVP_C_DATA(S390X_AES_CCM_CTX, c);
2056b077aed3SPierre Pronchery     unsigned char *buf;
2057e71b7053SJung-uk Kim     int enc, len;
2058e71b7053SJung-uk Kim 
2059e71b7053SJung-uk Kim     switch (type) {
2060e71b7053SJung-uk Kim     case EVP_CTRL_INIT:
2061e71b7053SJung-uk Kim         cctx->aes.ccm.key_set = 0;
2062e71b7053SJung-uk Kim         cctx->aes.ccm.iv_set = 0;
2063e71b7053SJung-uk Kim         cctx->aes.ccm.l = 8;
2064e71b7053SJung-uk Kim         cctx->aes.ccm.m = 12;
2065e71b7053SJung-uk Kim         cctx->aes.ccm.tag_set = 0;
2066e71b7053SJung-uk Kim         cctx->aes.ccm.len_set = 0;
2067e71b7053SJung-uk Kim         cctx->aes.ccm.tls_aad_len = -1;
2068e71b7053SJung-uk Kim         return 1;
2069e71b7053SJung-uk Kim 
2070da327cd2SJung-uk Kim     case EVP_CTRL_GET_IVLEN:
2071da327cd2SJung-uk Kim         *(int *)ptr = 15 - cctx->aes.ccm.l;
2072da327cd2SJung-uk Kim         return 1;
2073da327cd2SJung-uk Kim 
2074e71b7053SJung-uk Kim     case EVP_CTRL_AEAD_TLS1_AAD:
2075e71b7053SJung-uk Kim         if (arg != EVP_AEAD_TLS1_AAD_LEN)
2076e71b7053SJung-uk Kim             return 0;
2077e71b7053SJung-uk Kim 
2078e71b7053SJung-uk Kim         /* Save the aad for later use. */
2079e71b7053SJung-uk Kim         buf = EVP_CIPHER_CTX_buf_noconst(c);
2080e71b7053SJung-uk Kim         memcpy(buf, ptr, arg);
2081e71b7053SJung-uk Kim         cctx->aes.ccm.tls_aad_len = arg;
2082e71b7053SJung-uk Kim 
2083e71b7053SJung-uk Kim         len = buf[arg - 2] << 8 | buf[arg - 1];
2084e71b7053SJung-uk Kim         if (len < EVP_CCM_TLS_EXPLICIT_IV_LEN)
2085e71b7053SJung-uk Kim             return 0;
2086e71b7053SJung-uk Kim 
2087e71b7053SJung-uk Kim         /* Correct length for explicit iv. */
2088e71b7053SJung-uk Kim         len -= EVP_CCM_TLS_EXPLICIT_IV_LEN;
2089e71b7053SJung-uk Kim 
2090b077aed3SPierre Pronchery         enc = EVP_CIPHER_CTX_is_encrypting(c);
2091e71b7053SJung-uk Kim         if (!enc) {
2092e71b7053SJung-uk Kim             if (len < cctx->aes.ccm.m)
2093e71b7053SJung-uk Kim                 return 0;
2094e71b7053SJung-uk Kim 
2095e71b7053SJung-uk Kim             /* Correct length for tag. */
2096e71b7053SJung-uk Kim             len -= cctx->aes.ccm.m;
2097e71b7053SJung-uk Kim         }
2098e71b7053SJung-uk Kim 
2099e71b7053SJung-uk Kim         buf[arg - 2] = len >> 8;
2100e71b7053SJung-uk Kim         buf[arg - 1] = len & 0xff;
2101e71b7053SJung-uk Kim 
2102e71b7053SJung-uk Kim         /* Extra padding: tag appended to record. */
2103e71b7053SJung-uk Kim         return cctx->aes.ccm.m;
2104e71b7053SJung-uk Kim 
2105e71b7053SJung-uk Kim     case EVP_CTRL_CCM_SET_IV_FIXED:
2106e71b7053SJung-uk Kim         if (arg != EVP_CCM_TLS_FIXED_IV_LEN)
2107e71b7053SJung-uk Kim             return 0;
2108e71b7053SJung-uk Kim 
2109e71b7053SJung-uk Kim         /* Copy to first part of the iv. */
2110b077aed3SPierre Pronchery         memcpy(c->iv, ptr, arg);
2111e71b7053SJung-uk Kim         return 1;
2112e71b7053SJung-uk Kim 
2113e71b7053SJung-uk Kim     case EVP_CTRL_AEAD_SET_IVLEN:
2114e71b7053SJung-uk Kim         arg = 15 - arg;
2115e71b7053SJung-uk Kim         /* fall-through */
2116e71b7053SJung-uk Kim 
2117e71b7053SJung-uk Kim     case EVP_CTRL_CCM_SET_L:
2118e71b7053SJung-uk Kim         if (arg < 2 || arg > 8)
2119e71b7053SJung-uk Kim             return 0;
2120e71b7053SJung-uk Kim 
2121e71b7053SJung-uk Kim         cctx->aes.ccm.l = arg;
2122e71b7053SJung-uk Kim         return 1;
2123e71b7053SJung-uk Kim 
2124e71b7053SJung-uk Kim     case EVP_CTRL_AEAD_SET_TAG:
2125e71b7053SJung-uk Kim         if ((arg & 1) || arg < 4 || arg > 16)
2126e71b7053SJung-uk Kim             return 0;
2127e71b7053SJung-uk Kim 
2128b077aed3SPierre Pronchery         enc = EVP_CIPHER_CTX_is_encrypting(c);
2129e71b7053SJung-uk Kim         if (enc && ptr)
2130e71b7053SJung-uk Kim             return 0;
2131e71b7053SJung-uk Kim 
2132e71b7053SJung-uk Kim         if (ptr) {
2133e71b7053SJung-uk Kim             cctx->aes.ccm.tag_set = 1;
2134e71b7053SJung-uk Kim             buf = EVP_CIPHER_CTX_buf_noconst(c);
2135e71b7053SJung-uk Kim             memcpy(buf, ptr, arg);
2136e71b7053SJung-uk Kim         }
2137e71b7053SJung-uk Kim 
2138e71b7053SJung-uk Kim         cctx->aes.ccm.m = arg;
2139e71b7053SJung-uk Kim         return 1;
2140e71b7053SJung-uk Kim 
2141e71b7053SJung-uk Kim     case EVP_CTRL_AEAD_GET_TAG:
2142b077aed3SPierre Pronchery         enc = EVP_CIPHER_CTX_is_encrypting(c);
2143e71b7053SJung-uk Kim         if (!enc || !cctx->aes.ccm.tag_set)
2144e71b7053SJung-uk Kim             return 0;
2145e71b7053SJung-uk Kim 
2146e71b7053SJung-uk Kim         if(arg < cctx->aes.ccm.m)
2147e71b7053SJung-uk Kim             return 0;
2148e71b7053SJung-uk Kim 
2149e71b7053SJung-uk Kim         memcpy(ptr, cctx->aes.ccm.kmac_param.icv.b, cctx->aes.ccm.m);
2150b077aed3SPierre Pronchery         cctx->aes.ccm.tag_set = 0;
2151b077aed3SPierre Pronchery         cctx->aes.ccm.iv_set = 0;
2152b077aed3SPierre Pronchery         cctx->aes.ccm.len_set = 0;
2153e71b7053SJung-uk Kim         return 1;
2154e71b7053SJung-uk Kim 
2155e71b7053SJung-uk Kim     case EVP_CTRL_COPY:
2156e71b7053SJung-uk Kim         return 1;
2157e71b7053SJung-uk Kim 
2158e71b7053SJung-uk Kim     default:
2159e71b7053SJung-uk Kim         return -1;
2160e71b7053SJung-uk Kim     }
2161e71b7053SJung-uk Kim }
2162e71b7053SJung-uk Kim 
2163e71b7053SJung-uk Kim # define s390x_aes_ccm_cleanup aes_ccm_cleanup
2164e71b7053SJung-uk Kim 
2165e71b7053SJung-uk Kim # ifndef OPENSSL_NO_OCB
2166e71b7053SJung-uk Kim #  define S390X_AES_OCB_CTX             EVP_AES_OCB_CTX
2167e71b7053SJung-uk Kim 
2168e71b7053SJung-uk Kim #  define s390x_aes_ocb_init_key aes_ocb_init_key
2169e71b7053SJung-uk Kim static int s390x_aes_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
2170e71b7053SJung-uk Kim                                   const unsigned char *iv, int enc);
2171e71b7053SJung-uk Kim #  define s390x_aes_ocb_cipher aes_ocb_cipher
2172e71b7053SJung-uk Kim static int s390x_aes_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
2173e71b7053SJung-uk Kim                                 const unsigned char *in, size_t len);
2174e71b7053SJung-uk Kim #  define s390x_aes_ocb_cleanup aes_ocb_cleanup
2175e71b7053SJung-uk Kim static int s390x_aes_ocb_cleanup(EVP_CIPHER_CTX *);
2176e71b7053SJung-uk Kim #  define s390x_aes_ocb_ctrl aes_ocb_ctrl
2177e71b7053SJung-uk Kim static int s390x_aes_ocb_ctrl(EVP_CIPHER_CTX *, int type, int arg, void *ptr);
2178e71b7053SJung-uk Kim # endif
2179e71b7053SJung-uk Kim 
2180b077aed3SPierre Pronchery # ifndef OPENSSL_NO_SIV
2181b077aed3SPierre Pronchery #  define S390X_AES_SIV_CTX             EVP_AES_SIV_CTX
2182b077aed3SPierre Pronchery 
2183b077aed3SPierre Pronchery #  define s390x_aes_siv_init_key aes_siv_init_key
2184b077aed3SPierre Pronchery #  define s390x_aes_siv_cipher aes_siv_cipher
2185b077aed3SPierre Pronchery #  define s390x_aes_siv_cleanup aes_siv_cleanup
2186b077aed3SPierre Pronchery #  define s390x_aes_siv_ctrl aes_siv_ctrl
2187b077aed3SPierre Pronchery # endif
2188b077aed3SPierre Pronchery 
2189e71b7053SJung-uk Kim # define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,    \
2190e71b7053SJung-uk Kim                               MODE,flags)                               \
2191e71b7053SJung-uk Kim static const EVP_CIPHER s390x_aes_##keylen##_##mode = {                 \
2192e71b7053SJung-uk Kim     nid##_##keylen##_##nmode,blocksize,                                 \
2193e71b7053SJung-uk Kim     keylen / 8,                                                         \
2194e71b7053SJung-uk Kim     ivlen,                                                              \
2195b077aed3SPierre Pronchery     flags | EVP_CIPH_##MODE##_MODE,                                     \
2196b077aed3SPierre Pronchery     EVP_ORIG_GLOBAL,                                                    \
2197e71b7053SJung-uk Kim     s390x_aes_##mode##_init_key,                                        \
2198e71b7053SJung-uk Kim     s390x_aes_##mode##_cipher,                                          \
2199e71b7053SJung-uk Kim     NULL,                                                               \
2200e71b7053SJung-uk Kim     sizeof(S390X_AES_##MODE##_CTX),                                     \
2201e71b7053SJung-uk Kim     NULL,                                                               \
2202e71b7053SJung-uk Kim     NULL,                                                               \
2203e71b7053SJung-uk Kim     NULL,                                                               \
2204e71b7053SJung-uk Kim     NULL                                                                \
2205e71b7053SJung-uk Kim };                                                                      \
2206e71b7053SJung-uk Kim static const EVP_CIPHER aes_##keylen##_##mode = {                       \
2207e71b7053SJung-uk Kim     nid##_##keylen##_##nmode,                                           \
2208e71b7053SJung-uk Kim     blocksize,                                                          \
2209e71b7053SJung-uk Kim     keylen / 8,                                                         \
2210e71b7053SJung-uk Kim     ivlen,                                                              \
2211e71b7053SJung-uk Kim     flags | EVP_CIPH_##MODE##_MODE,                                     \
2212b077aed3SPierre Pronchery     EVP_ORIG_GLOBAL,                                                    \
2213e71b7053SJung-uk Kim     aes_init_key,                                                       \
2214e71b7053SJung-uk Kim     aes_##mode##_cipher,                                                \
2215e71b7053SJung-uk Kim     NULL,                                                               \
2216e71b7053SJung-uk Kim     sizeof(EVP_AES_KEY),                                                \
2217e71b7053SJung-uk Kim     NULL,                                                               \
2218e71b7053SJung-uk Kim     NULL,                                                               \
2219e71b7053SJung-uk Kim     NULL,                                                               \
2220e71b7053SJung-uk Kim     NULL                                                                \
2221e71b7053SJung-uk Kim };                                                                      \
2222e71b7053SJung-uk Kim const EVP_CIPHER *EVP_aes_##keylen##_##mode(void)                       \
2223e71b7053SJung-uk Kim {                                                                       \
2224e71b7053SJung-uk Kim     return S390X_aes_##keylen##_##mode##_CAPABLE ?                      \
2225e71b7053SJung-uk Kim            &s390x_aes_##keylen##_##mode : &aes_##keylen##_##mode;       \
2226e71b7053SJung-uk Kim }
2227e71b7053SJung-uk Kim 
2228e71b7053SJung-uk Kim # define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags)\
2229e71b7053SJung-uk Kim static const EVP_CIPHER s390x_aes_##keylen##_##mode = {                 \
2230e71b7053SJung-uk Kim     nid##_##keylen##_##mode,                                            \
2231e71b7053SJung-uk Kim     blocksize,                                                          \
2232b077aed3SPierre Pronchery     (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE||EVP_CIPH_##MODE##_MODE==EVP_CIPH_SIV_MODE ? 2 : 1) * keylen / 8,        \
2233e71b7053SJung-uk Kim     ivlen,                                                              \
2234b077aed3SPierre Pronchery     flags | EVP_CIPH_##MODE##_MODE,                                     \
2235b077aed3SPierre Pronchery     EVP_ORIG_GLOBAL,                                                    \
2236e71b7053SJung-uk Kim     s390x_aes_##mode##_init_key,                                        \
2237e71b7053SJung-uk Kim     s390x_aes_##mode##_cipher,                                          \
2238e71b7053SJung-uk Kim     s390x_aes_##mode##_cleanup,                                         \
2239e71b7053SJung-uk Kim     sizeof(S390X_AES_##MODE##_CTX),                                     \
2240e71b7053SJung-uk Kim     NULL,                                                               \
2241e71b7053SJung-uk Kim     NULL,                                                               \
2242e71b7053SJung-uk Kim     s390x_aes_##mode##_ctrl,                                            \
2243e71b7053SJung-uk Kim     NULL                                                                \
2244e71b7053SJung-uk Kim };                                                                      \
2245e71b7053SJung-uk Kim static const EVP_CIPHER aes_##keylen##_##mode = {                       \
2246e71b7053SJung-uk Kim     nid##_##keylen##_##mode,blocksize,                                  \
2247b077aed3SPierre Pronchery     (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE||EVP_CIPH_##MODE##_MODE==EVP_CIPH_SIV_MODE ? 2 : 1) * keylen / 8,        \
2248e71b7053SJung-uk Kim     ivlen,                                                              \
2249e71b7053SJung-uk Kim     flags | EVP_CIPH_##MODE##_MODE,                                     \
2250b077aed3SPierre Pronchery     EVP_ORIG_GLOBAL,                                                    \
2251e71b7053SJung-uk Kim     aes_##mode##_init_key,                                              \
2252e71b7053SJung-uk Kim     aes_##mode##_cipher,                                                \
2253e71b7053SJung-uk Kim     aes_##mode##_cleanup,                                               \
2254e71b7053SJung-uk Kim     sizeof(EVP_AES_##MODE##_CTX),                                       \
2255e71b7053SJung-uk Kim     NULL,                                                               \
2256e71b7053SJung-uk Kim     NULL,                                                               \
2257e71b7053SJung-uk Kim     aes_##mode##_ctrl,                                                  \
2258e71b7053SJung-uk Kim     NULL                                                                \
2259e71b7053SJung-uk Kim };                                                                      \
2260e71b7053SJung-uk Kim const EVP_CIPHER *EVP_aes_##keylen##_##mode(void)                       \
2261e71b7053SJung-uk Kim {                                                                       \
2262e71b7053SJung-uk Kim     return S390X_aes_##keylen##_##mode##_CAPABLE ?                      \
2263e71b7053SJung-uk Kim            &s390x_aes_##keylen##_##mode : &aes_##keylen##_##mode;       \
2264e71b7053SJung-uk Kim }
2265e71b7053SJung-uk Kim 
22661f13597dSJung-uk Kim #else
22671f13597dSJung-uk Kim 
22681f13597dSJung-uk Kim # define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \
22691f13597dSJung-uk Kim static const EVP_CIPHER aes_##keylen##_##mode = { \
22701f13597dSJung-uk Kim         nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \
22711f13597dSJung-uk Kim         flags|EVP_CIPH_##MODE##_MODE,   \
2272b077aed3SPierre Pronchery         EVP_ORIG_GLOBAL,                \
22731f13597dSJung-uk Kim         aes_init_key,                   \
22741f13597dSJung-uk Kim         aes_##mode##_cipher,            \
22751f13597dSJung-uk Kim         NULL,                           \
22761f13597dSJung-uk Kim         sizeof(EVP_AES_KEY),            \
22771f13597dSJung-uk Kim         NULL,NULL,NULL,NULL }; \
22781f13597dSJung-uk Kim const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
22791f13597dSJung-uk Kim { return &aes_##keylen##_##mode; }
22801f13597dSJung-uk Kim 
22811f13597dSJung-uk Kim # define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags) \
22821f13597dSJung-uk Kim static const EVP_CIPHER aes_##keylen##_##mode = { \
22831f13597dSJung-uk Kim         nid##_##keylen##_##mode,blocksize, \
2284b077aed3SPierre Pronchery         (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE||EVP_CIPH_##MODE##_MODE==EVP_CIPH_SIV_MODE?2:1)*keylen/8, \
2285b077aed3SPierre Pronchery         ivlen,                          \
22861f13597dSJung-uk Kim         flags|EVP_CIPH_##MODE##_MODE,   \
2287b077aed3SPierre Pronchery         EVP_ORIG_GLOBAL,                \
22881f13597dSJung-uk Kim         aes_##mode##_init_key,          \
22891f13597dSJung-uk Kim         aes_##mode##_cipher,            \
22901f13597dSJung-uk Kim         aes_##mode##_cleanup,           \
22911f13597dSJung-uk Kim         sizeof(EVP_AES_##MODE##_CTX),   \
22921f13597dSJung-uk Kim         NULL,NULL,aes_##mode##_ctrl,NULL }; \
22931f13597dSJung-uk Kim const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
22941f13597dSJung-uk Kim { return &aes_##keylen##_##mode; }
2295e71b7053SJung-uk Kim 
22961f13597dSJung-uk Kim #endif
22971f13597dSJung-uk Kim 
22981f13597dSJung-uk Kim #define BLOCK_CIPHER_generic_pack(nid,keylen,flags)             \
22991f13597dSJung-uk Kim         BLOCK_CIPHER_generic(nid,keylen,16,16,cbc,cbc,CBC,flags|EVP_CIPH_FLAG_DEFAULT_ASN1)     \
23001f13597dSJung-uk Kim         BLOCK_CIPHER_generic(nid,keylen,16,0,ecb,ecb,ECB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1)      \
23011f13597dSJung-uk Kim         BLOCK_CIPHER_generic(nid,keylen,1,16,ofb128,ofb,OFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1)   \
23021f13597dSJung-uk Kim         BLOCK_CIPHER_generic(nid,keylen,1,16,cfb128,cfb,CFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1)   \
23031f13597dSJung-uk Kim         BLOCK_CIPHER_generic(nid,keylen,1,16,cfb1,cfb1,CFB,flags)       \
23041f13597dSJung-uk Kim         BLOCK_CIPHER_generic(nid,keylen,1,16,cfb8,cfb8,CFB,flags)       \
23051f13597dSJung-uk Kim         BLOCK_CIPHER_generic(nid,keylen,1,16,ctr,ctr,CTR,flags)
23066be8ae07SJacques Vidrine 
aes_init_key(EVP_CIPHER_CTX * ctx,const unsigned char * key,const unsigned char * iv,int enc)23075c87c606SMark Murray static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
23086be8ae07SJacques Vidrine                         const unsigned char *iv, int enc)
23096be8ae07SJacques Vidrine {
23101f13597dSJung-uk Kim     int ret, mode;
2311e71b7053SJung-uk Kim     EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
23125c87c606SMark Murray 
2313b077aed3SPierre Pronchery     mode = EVP_CIPHER_CTX_get_mode(ctx);
23141f13597dSJung-uk Kim     if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE)
2315e71b7053SJung-uk Kim         && !enc) {
23167bded2dbSJung-uk Kim #ifdef HWAES_CAPABLE
23177bded2dbSJung-uk Kim         if (HWAES_CAPABLE) {
2318e71b7053SJung-uk Kim             ret = HWAES_set_decrypt_key(key,
2319b077aed3SPierre Pronchery                                         EVP_CIPHER_CTX_get_key_length(ctx) * 8,
2320e71b7053SJung-uk Kim                                         &dat->ks.ks);
23217bded2dbSJung-uk Kim             dat->block = (block128_f) HWAES_decrypt;
23227bded2dbSJung-uk Kim             dat->stream.cbc = NULL;
23237bded2dbSJung-uk Kim # ifdef HWAES_cbc_encrypt
23247bded2dbSJung-uk Kim             if (mode == EVP_CIPH_CBC_MODE)
23257bded2dbSJung-uk Kim                 dat->stream.cbc = (cbc128_f) HWAES_cbc_encrypt;
23267bded2dbSJung-uk Kim # endif
23277bded2dbSJung-uk Kim         } else
23287bded2dbSJung-uk Kim #endif
23291f13597dSJung-uk Kim #ifdef BSAES_CAPABLE
23306f9291ceSJung-uk Kim         if (BSAES_CAPABLE && mode == EVP_CIPH_CBC_MODE) {
2331b077aed3SPierre Pronchery             ret = AES_set_decrypt_key(key,
2332b077aed3SPierre Pronchery                                       EVP_CIPHER_CTX_get_key_length(ctx) * 8,
2333e71b7053SJung-uk Kim                                       &dat->ks.ks);
23341f13597dSJung-uk Kim             dat->block = (block128_f) AES_decrypt;
2335b077aed3SPierre Pronchery             dat->stream.cbc = (cbc128_f) ossl_bsaes_cbc_encrypt;
23366f9291ceSJung-uk Kim         } else
23371f13597dSJung-uk Kim #endif
23381f13597dSJung-uk Kim #ifdef VPAES_CAPABLE
23396f9291ceSJung-uk Kim         if (VPAES_CAPABLE) {
2340e71b7053SJung-uk Kim             ret = vpaes_set_decrypt_key(key,
2341b077aed3SPierre Pronchery                                         EVP_CIPHER_CTX_get_key_length(ctx) * 8,
2342e71b7053SJung-uk Kim                                         &dat->ks.ks);
23431f13597dSJung-uk Kim             dat->block = (block128_f) vpaes_decrypt;
23441f13597dSJung-uk Kim             dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
23456f9291ceSJung-uk Kim                 (cbc128_f) vpaes_cbc_encrypt : NULL;
23466f9291ceSJung-uk Kim         } else
23471f13597dSJung-uk Kim #endif
23481f13597dSJung-uk Kim         {
2349e71b7053SJung-uk Kim             ret = AES_set_decrypt_key(key,
2350b077aed3SPierre Pronchery                                       EVP_CIPHER_CTX_get_key_length(ctx) * 8,
2351e71b7053SJung-uk Kim                                       &dat->ks.ks);
23521f13597dSJung-uk Kim             dat->block = (block128_f) AES_decrypt;
23531f13597dSJung-uk Kim             dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
23546f9291ceSJung-uk Kim                 (cbc128_f) AES_cbc_encrypt : NULL;
2355e71b7053SJung-uk Kim         }
23566f9291ceSJung-uk Kim     } else
23577bded2dbSJung-uk Kim #ifdef HWAES_CAPABLE
23587bded2dbSJung-uk Kim     if (HWAES_CAPABLE) {
2359b077aed3SPierre Pronchery         ret = HWAES_set_encrypt_key(key,
2360b077aed3SPierre Pronchery                                     EVP_CIPHER_CTX_get_key_length(ctx) * 8,
2361e71b7053SJung-uk Kim                                     &dat->ks.ks);
23627bded2dbSJung-uk Kim         dat->block = (block128_f) HWAES_encrypt;
23637bded2dbSJung-uk Kim         dat->stream.cbc = NULL;
23647bded2dbSJung-uk Kim # ifdef HWAES_cbc_encrypt
23657bded2dbSJung-uk Kim         if (mode == EVP_CIPH_CBC_MODE)
23667bded2dbSJung-uk Kim             dat->stream.cbc = (cbc128_f) HWAES_cbc_encrypt;
23677bded2dbSJung-uk Kim         else
23687bded2dbSJung-uk Kim # endif
23697bded2dbSJung-uk Kim # ifdef HWAES_ctr32_encrypt_blocks
23707bded2dbSJung-uk Kim         if (mode == EVP_CIPH_CTR_MODE)
23717bded2dbSJung-uk Kim             dat->stream.ctr = (ctr128_f) HWAES_ctr32_encrypt_blocks;
23727bded2dbSJung-uk Kim         else
23737bded2dbSJung-uk Kim # endif
23747bded2dbSJung-uk Kim             (void)0;            /* terminate potentially open 'else' */
23757bded2dbSJung-uk Kim     } else
23767bded2dbSJung-uk Kim #endif
23771f13597dSJung-uk Kim #ifdef BSAES_CAPABLE
23786f9291ceSJung-uk Kim     if (BSAES_CAPABLE && mode == EVP_CIPH_CTR_MODE) {
2379b077aed3SPierre Pronchery         ret = AES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
2380e71b7053SJung-uk Kim                                   &dat->ks.ks);
23811f13597dSJung-uk Kim         dat->block = (block128_f) AES_encrypt;
2382b077aed3SPierre Pronchery         dat->stream.ctr = (ctr128_f) ossl_bsaes_ctr32_encrypt_blocks;
23836f9291ceSJung-uk Kim     } else
23841f13597dSJung-uk Kim #endif
23851f13597dSJung-uk Kim #ifdef VPAES_CAPABLE
23866f9291ceSJung-uk Kim     if (VPAES_CAPABLE) {
2387b077aed3SPierre Pronchery         ret = vpaes_set_encrypt_key(key,
2388b077aed3SPierre Pronchery                                     EVP_CIPHER_CTX_get_key_length(ctx) * 8,
2389e71b7053SJung-uk Kim                                     &dat->ks.ks);
23901f13597dSJung-uk Kim         dat->block = (block128_f) vpaes_encrypt;
23911f13597dSJung-uk Kim         dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
23926f9291ceSJung-uk Kim             (cbc128_f) vpaes_cbc_encrypt : NULL;
23936f9291ceSJung-uk Kim     } else
23941f13597dSJung-uk Kim #endif
23951f13597dSJung-uk Kim     {
2396b077aed3SPierre Pronchery         ret = AES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
2397e71b7053SJung-uk Kim                                   &dat->ks.ks);
23981f13597dSJung-uk Kim         dat->block = (block128_f) AES_encrypt;
23991f13597dSJung-uk Kim         dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
24006f9291ceSJung-uk Kim             (cbc128_f) AES_cbc_encrypt : NULL;
24011f13597dSJung-uk Kim #ifdef AES_CTR_ASM
24021f13597dSJung-uk Kim         if (mode == EVP_CIPH_CTR_MODE)
24031f13597dSJung-uk Kim             dat->stream.ctr = (ctr128_f) AES_ctr32_encrypt;
24041f13597dSJung-uk Kim #endif
24051f13597dSJung-uk Kim     }
24066be8ae07SJacques Vidrine 
24076f9291ceSJung-uk Kim     if (ret < 0) {
2408b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, EVP_R_AES_KEY_SETUP_FAILED);
24096be8ae07SJacques Vidrine         return 0;
24106be8ae07SJacques Vidrine     }
24115c87c606SMark Murray 
24125c87c606SMark Murray     return 1;
24135c87c606SMark Murray }
24145c87c606SMark Murray 
aes_cbc_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t len)24151f13597dSJung-uk Kim static int aes_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
24161f13597dSJung-uk Kim                           const unsigned char *in, size_t len)
24171f13597dSJung-uk Kim {
2418e71b7053SJung-uk Kim     EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
24191f13597dSJung-uk Kim 
24201f13597dSJung-uk Kim     if (dat->stream.cbc)
2421b077aed3SPierre Pronchery         (*dat->stream.cbc) (in, out, len, &dat->ks, ctx->iv,
2422b077aed3SPierre Pronchery                             EVP_CIPHER_CTX_is_encrypting(ctx));
2423b077aed3SPierre Pronchery     else if (EVP_CIPHER_CTX_is_encrypting(ctx))
2424b077aed3SPierre Pronchery         CRYPTO_cbc128_encrypt(in, out, len, &dat->ks, ctx->iv,
2425b077aed3SPierre Pronchery                               dat->block);
24261f13597dSJung-uk Kim     else
2427e71b7053SJung-uk Kim         CRYPTO_cbc128_decrypt(in, out, len, &dat->ks,
2428b077aed3SPierre Pronchery                               ctx->iv, dat->block);
24291f13597dSJung-uk Kim 
24301f13597dSJung-uk Kim     return 1;
24311f13597dSJung-uk Kim }
24321f13597dSJung-uk Kim 
aes_ecb_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t len)24331f13597dSJung-uk Kim static int aes_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
24341f13597dSJung-uk Kim                           const unsigned char *in, size_t len)
24351f13597dSJung-uk Kim {
2436b077aed3SPierre Pronchery     size_t bl = EVP_CIPHER_CTX_get_block_size(ctx);
24371f13597dSJung-uk Kim     size_t i;
2438e71b7053SJung-uk Kim     EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
24391f13597dSJung-uk Kim 
24406f9291ceSJung-uk Kim     if (len < bl)
24416f9291ceSJung-uk Kim         return 1;
24421f13597dSJung-uk Kim 
24431f13597dSJung-uk Kim     for (i = 0, len -= bl; i <= len; i += bl)
24441f13597dSJung-uk Kim         (*dat->block) (in + i, out + i, &dat->ks);
24451f13597dSJung-uk Kim 
24461f13597dSJung-uk Kim     return 1;
24471f13597dSJung-uk Kim }
24481f13597dSJung-uk Kim 
aes_ofb_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t len)24491f13597dSJung-uk Kim static int aes_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
24501f13597dSJung-uk Kim                           const unsigned char *in, size_t len)
24511f13597dSJung-uk Kim {
2452e71b7053SJung-uk Kim     EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
24531f13597dSJung-uk Kim 
2454b077aed3SPierre Pronchery     int num = EVP_CIPHER_CTX_get_num(ctx);
24551f13597dSJung-uk Kim     CRYPTO_ofb128_encrypt(in, out, len, &dat->ks,
2456b077aed3SPierre Pronchery                           ctx->iv, &num, dat->block);
2457e71b7053SJung-uk Kim     EVP_CIPHER_CTX_set_num(ctx, num);
24581f13597dSJung-uk Kim     return 1;
24591f13597dSJung-uk Kim }
24601f13597dSJung-uk Kim 
aes_cfb_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t len)24611f13597dSJung-uk Kim static int aes_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
24621f13597dSJung-uk Kim                           const unsigned char *in, size_t len)
24631f13597dSJung-uk Kim {
2464e71b7053SJung-uk Kim     EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
24651f13597dSJung-uk Kim 
2466b077aed3SPierre Pronchery     int num = EVP_CIPHER_CTX_get_num(ctx);
24671f13597dSJung-uk Kim     CRYPTO_cfb128_encrypt(in, out, len, &dat->ks,
2468b077aed3SPierre Pronchery                           ctx->iv, &num,
2469b077aed3SPierre Pronchery                           EVP_CIPHER_CTX_is_encrypting(ctx), dat->block);
2470e71b7053SJung-uk Kim     EVP_CIPHER_CTX_set_num(ctx, num);
24711f13597dSJung-uk Kim     return 1;
24721f13597dSJung-uk Kim }
24731f13597dSJung-uk Kim 
aes_cfb8_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t len)24741f13597dSJung-uk Kim static int aes_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
24751f13597dSJung-uk Kim                            const unsigned char *in, size_t len)
24761f13597dSJung-uk Kim {
2477e71b7053SJung-uk Kim     EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
24781f13597dSJung-uk Kim 
2479b077aed3SPierre Pronchery     int num = EVP_CIPHER_CTX_get_num(ctx);
24801f13597dSJung-uk Kim     CRYPTO_cfb128_8_encrypt(in, out, len, &dat->ks,
2481b077aed3SPierre Pronchery                             ctx->iv, &num,
2482b077aed3SPierre Pronchery                             EVP_CIPHER_CTX_is_encrypting(ctx), dat->block);
2483e71b7053SJung-uk Kim     EVP_CIPHER_CTX_set_num(ctx, num);
24841f13597dSJung-uk Kim     return 1;
24851f13597dSJung-uk Kim }
24861f13597dSJung-uk Kim 
aes_cfb1_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t len)24871f13597dSJung-uk Kim static int aes_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
24881f13597dSJung-uk Kim                            const unsigned char *in, size_t len)
24891f13597dSJung-uk Kim {
2490e71b7053SJung-uk Kim     EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
24911f13597dSJung-uk Kim 
2492e71b7053SJung-uk Kim     if (EVP_CIPHER_CTX_test_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS)) {
2493b077aed3SPierre Pronchery         int num = EVP_CIPHER_CTX_get_num(ctx);
24941f13597dSJung-uk Kim         CRYPTO_cfb128_1_encrypt(in, out, len, &dat->ks,
2495b077aed3SPierre Pronchery                                 ctx->iv, &num,
2496b077aed3SPierre Pronchery                                 EVP_CIPHER_CTX_is_encrypting(ctx), dat->block);
2497e71b7053SJung-uk Kim         EVP_CIPHER_CTX_set_num(ctx, num);
24981f13597dSJung-uk Kim         return 1;
24991f13597dSJung-uk Kim     }
25001f13597dSJung-uk Kim 
25011f13597dSJung-uk Kim     while (len >= MAXBITCHUNK) {
2502b077aed3SPierre Pronchery         int num = EVP_CIPHER_CTX_get_num(ctx);
25031f13597dSJung-uk Kim         CRYPTO_cfb128_1_encrypt(in, out, MAXBITCHUNK * 8, &dat->ks,
2504b077aed3SPierre Pronchery                                 ctx->iv, &num,
2505b077aed3SPierre Pronchery                                 EVP_CIPHER_CTX_is_encrypting(ctx), dat->block);
2506e71b7053SJung-uk Kim         EVP_CIPHER_CTX_set_num(ctx, num);
25071f13597dSJung-uk Kim         len -= MAXBITCHUNK;
2508dee36b4fSJung-uk Kim         out += MAXBITCHUNK;
2509dee36b4fSJung-uk Kim         in  += MAXBITCHUNK;
25101f13597dSJung-uk Kim     }
2511e71b7053SJung-uk Kim     if (len) {
2512b077aed3SPierre Pronchery         int num = EVP_CIPHER_CTX_get_num(ctx);
25131f13597dSJung-uk Kim         CRYPTO_cfb128_1_encrypt(in, out, len * 8, &dat->ks,
2514b077aed3SPierre Pronchery                                 ctx->iv, &num,
2515b077aed3SPierre Pronchery                                 EVP_CIPHER_CTX_is_encrypting(ctx), dat->block);
2516e71b7053SJung-uk Kim         EVP_CIPHER_CTX_set_num(ctx, num);
2517e71b7053SJung-uk Kim     }
25181f13597dSJung-uk Kim 
25191f13597dSJung-uk Kim     return 1;
25201f13597dSJung-uk Kim }
25211f13597dSJung-uk Kim 
aes_ctr_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t len)25221f13597dSJung-uk Kim static int aes_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
25231f13597dSJung-uk Kim                           const unsigned char *in, size_t len)
25241f13597dSJung-uk Kim {
2525b077aed3SPierre Pronchery     int n = EVP_CIPHER_CTX_get_num(ctx);
2526b077aed3SPierre Pronchery     unsigned int num;
2527e71b7053SJung-uk Kim     EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
25281f13597dSJung-uk Kim 
2529b077aed3SPierre Pronchery     if (n < 0)
2530b077aed3SPierre Pronchery         return 0;
2531b077aed3SPierre Pronchery     num = (unsigned int)n;
2532b077aed3SPierre Pronchery 
25331f13597dSJung-uk Kim     if (dat->stream.ctr)
25341f13597dSJung-uk Kim         CRYPTO_ctr128_encrypt_ctr32(in, out, len, &dat->ks,
2535b077aed3SPierre Pronchery                                     ctx->iv,
2536e71b7053SJung-uk Kim                                     EVP_CIPHER_CTX_buf_noconst(ctx),
2537e71b7053SJung-uk Kim                                     &num, dat->stream.ctr);
25381f13597dSJung-uk Kim     else
25391f13597dSJung-uk Kim         CRYPTO_ctr128_encrypt(in, out, len, &dat->ks,
2540b077aed3SPierre Pronchery                               ctx->iv,
2541e71b7053SJung-uk Kim                               EVP_CIPHER_CTX_buf_noconst(ctx), &num,
2542e71b7053SJung-uk Kim                               dat->block);
2543e71b7053SJung-uk Kim     EVP_CIPHER_CTX_set_num(ctx, num);
25441f13597dSJung-uk Kim     return 1;
25451f13597dSJung-uk Kim }
25461f13597dSJung-uk Kim 
2547e71b7053SJung-uk Kim BLOCK_CIPHER_generic_pack(NID_aes, 128, 0)
2548e71b7053SJung-uk Kim     BLOCK_CIPHER_generic_pack(NID_aes, 192, 0)
2549e71b7053SJung-uk Kim     BLOCK_CIPHER_generic_pack(NID_aes, 256, 0)
25501f13597dSJung-uk Kim 
aes_gcm_cleanup(EVP_CIPHER_CTX * c)25511f13597dSJung-uk Kim static int aes_gcm_cleanup(EVP_CIPHER_CTX *c)
25521f13597dSJung-uk Kim {
2553e71b7053SJung-uk Kim     EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,c);
2554ed7112f0SJung-uk Kim     if (gctx == NULL)
2555ed7112f0SJung-uk Kim         return 0;
25561f13597dSJung-uk Kim     OPENSSL_cleanse(&gctx->gcm, sizeof(gctx->gcm));
2557b077aed3SPierre Pronchery     if (gctx->iv != c->iv)
25581f13597dSJung-uk Kim         OPENSSL_free(gctx->iv);
25591f13597dSJung-uk Kim     return 1;
25601f13597dSJung-uk Kim }
25611f13597dSJung-uk Kim 
aes_gcm_ctrl(EVP_CIPHER_CTX * c,int type,int arg,void * ptr)25621f13597dSJung-uk Kim static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
25631f13597dSJung-uk Kim {
2564e71b7053SJung-uk Kim     EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,c);
25656f9291ceSJung-uk Kim     switch (type) {
25661f13597dSJung-uk Kim     case EVP_CTRL_INIT:
25671f13597dSJung-uk Kim         gctx->key_set = 0;
25681f13597dSJung-uk Kim         gctx->iv_set = 0;
2569b077aed3SPierre Pronchery         gctx->ivlen = EVP_CIPHER_get_iv_length(c->cipher);
25701f13597dSJung-uk Kim         gctx->iv = c->iv;
25711f13597dSJung-uk Kim         gctx->taglen = -1;
25721f13597dSJung-uk Kim         gctx->iv_gen = 0;
25731f13597dSJung-uk Kim         gctx->tls_aad_len = -1;
25741f13597dSJung-uk Kim         return 1;
25751f13597dSJung-uk Kim 
2576da327cd2SJung-uk Kim     case EVP_CTRL_GET_IVLEN:
2577da327cd2SJung-uk Kim         *(int *)ptr = gctx->ivlen;
2578da327cd2SJung-uk Kim         return 1;
2579da327cd2SJung-uk Kim 
2580e71b7053SJung-uk Kim     case EVP_CTRL_AEAD_SET_IVLEN:
25811f13597dSJung-uk Kim         if (arg <= 0)
25821f13597dSJung-uk Kim             return 0;
25831f13597dSJung-uk Kim         /* Allocate memory for IV if needed */
25846f9291ceSJung-uk Kim         if ((arg > EVP_MAX_IV_LENGTH) && (arg > gctx->ivlen)) {
25851f13597dSJung-uk Kim             if (gctx->iv != c->iv)
25861f13597dSJung-uk Kim                 OPENSSL_free(gctx->iv);
2587e71b7053SJung-uk Kim             if ((gctx->iv = OPENSSL_malloc(arg)) == NULL) {
2588b077aed3SPierre Pronchery                 ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
25891f13597dSJung-uk Kim                 return 0;
25901f13597dSJung-uk Kim             }
2591e71b7053SJung-uk Kim         }
25921f13597dSJung-uk Kim         gctx->ivlen = arg;
25931f13597dSJung-uk Kim         return 1;
25941f13597dSJung-uk Kim 
2595e71b7053SJung-uk Kim     case EVP_CTRL_AEAD_SET_TAG:
25961f13597dSJung-uk Kim         if (arg <= 0 || arg > 16 || c->encrypt)
25971f13597dSJung-uk Kim             return 0;
25981f13597dSJung-uk Kim         memcpy(c->buf, ptr, arg);
25991f13597dSJung-uk Kim         gctx->taglen = arg;
26001f13597dSJung-uk Kim         return 1;
26011f13597dSJung-uk Kim 
2602e71b7053SJung-uk Kim     case EVP_CTRL_AEAD_GET_TAG:
2603e71b7053SJung-uk Kim         if (arg <= 0 || arg > 16 || !c->encrypt
2604e71b7053SJung-uk Kim             || gctx->taglen < 0)
26051f13597dSJung-uk Kim             return 0;
26061f13597dSJung-uk Kim         memcpy(ptr, c->buf, arg);
26071f13597dSJung-uk Kim         return 1;
26081f13597dSJung-uk Kim 
26091f13597dSJung-uk Kim     case EVP_CTRL_GCM_SET_IV_FIXED:
26101f13597dSJung-uk Kim         /* Special case: -1 length restores whole IV */
26116f9291ceSJung-uk Kim         if (arg == -1) {
26121f13597dSJung-uk Kim             memcpy(gctx->iv, ptr, gctx->ivlen);
26131f13597dSJung-uk Kim             gctx->iv_gen = 1;
26141f13597dSJung-uk Kim             return 1;
26151f13597dSJung-uk Kim         }
26166f9291ceSJung-uk Kim         /*
26176f9291ceSJung-uk Kim          * Fixed field must be at least 4 bytes and invocation field at least
26186f9291ceSJung-uk Kim          * 8.
26191f13597dSJung-uk Kim          */
26201f13597dSJung-uk Kim         if ((arg < 4) || (gctx->ivlen - arg) < 8)
26211f13597dSJung-uk Kim             return 0;
26221f13597dSJung-uk Kim         if (arg)
26231f13597dSJung-uk Kim             memcpy(gctx->iv, ptr, arg);
26246f9291ceSJung-uk Kim         if (c->encrypt && RAND_bytes(gctx->iv + arg, gctx->ivlen - arg) <= 0)
26251f13597dSJung-uk Kim             return 0;
26261f13597dSJung-uk Kim         gctx->iv_gen = 1;
26271f13597dSJung-uk Kim         return 1;
26281f13597dSJung-uk Kim 
26291f13597dSJung-uk Kim     case EVP_CTRL_GCM_IV_GEN:
26301f13597dSJung-uk Kim         if (gctx->iv_gen == 0 || gctx->key_set == 0)
26311f13597dSJung-uk Kim             return 0;
26321f13597dSJung-uk Kim         CRYPTO_gcm128_setiv(&gctx->gcm, gctx->iv, gctx->ivlen);
26331f13597dSJung-uk Kim         if (arg <= 0 || arg > gctx->ivlen)
26341f13597dSJung-uk Kim             arg = gctx->ivlen;
26351f13597dSJung-uk Kim         memcpy(ptr, gctx->iv + gctx->ivlen - arg, arg);
26366f9291ceSJung-uk Kim         /*
26376f9291ceSJung-uk Kim          * Invocation field will be at least 8 bytes in size and so no need
26386f9291ceSJung-uk Kim          * to check wrap around or increment more than last 8 bytes.
26391f13597dSJung-uk Kim          */
26401f13597dSJung-uk Kim         ctr64_inc(gctx->iv + gctx->ivlen - 8);
26411f13597dSJung-uk Kim         gctx->iv_set = 1;
26421f13597dSJung-uk Kim         return 1;
26431f13597dSJung-uk Kim 
26441f13597dSJung-uk Kim     case EVP_CTRL_GCM_SET_IV_INV:
26451f13597dSJung-uk Kim         if (gctx->iv_gen == 0 || gctx->key_set == 0 || c->encrypt)
26461f13597dSJung-uk Kim             return 0;
26471f13597dSJung-uk Kim         memcpy(gctx->iv + gctx->ivlen - arg, ptr, arg);
26481f13597dSJung-uk Kim         CRYPTO_gcm128_setiv(&gctx->gcm, gctx->iv, gctx->ivlen);
26491f13597dSJung-uk Kim         gctx->iv_set = 1;
26501f13597dSJung-uk Kim         return 1;
26511f13597dSJung-uk Kim 
26521f13597dSJung-uk Kim     case EVP_CTRL_AEAD_TLS1_AAD:
26531f13597dSJung-uk Kim         /* Save the AAD for later use */
2654ed6b93beSJung-uk Kim         if (arg != EVP_AEAD_TLS1_AAD_LEN)
26551f13597dSJung-uk Kim             return 0;
26561f13597dSJung-uk Kim         memcpy(c->buf, ptr, arg);
26571f13597dSJung-uk Kim         gctx->tls_aad_len = arg;
2658b077aed3SPierre Pronchery         gctx->tls_enc_records = 0;
26591f13597dSJung-uk Kim         {
26601f13597dSJung-uk Kim             unsigned int len = c->buf[arg - 2] << 8 | c->buf[arg - 1];
26611f13597dSJung-uk Kim             /* Correct length for explicit IV */
2662ed7112f0SJung-uk Kim             if (len < EVP_GCM_TLS_EXPLICIT_IV_LEN)
2663ed7112f0SJung-uk Kim                 return 0;
26641f13597dSJung-uk Kim             len -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
26651f13597dSJung-uk Kim             /* If decrypting correct for tag too */
2666ed7112f0SJung-uk Kim             if (!c->encrypt) {
2667ed7112f0SJung-uk Kim                 if (len < EVP_GCM_TLS_TAG_LEN)
2668ed7112f0SJung-uk Kim                     return 0;
26691f13597dSJung-uk Kim                 len -= EVP_GCM_TLS_TAG_LEN;
2670ed7112f0SJung-uk Kim             }
26711f13597dSJung-uk Kim             c->buf[arg - 2] = len >> 8;
26721f13597dSJung-uk Kim             c->buf[arg - 1] = len & 0xff;
26731f13597dSJung-uk Kim         }
26741f13597dSJung-uk Kim         /* Extra padding: tag appended to record */
26751f13597dSJung-uk Kim         return EVP_GCM_TLS_TAG_LEN;
26761f13597dSJung-uk Kim 
2677a93cbc2bSJung-uk Kim     case EVP_CTRL_COPY:
2678a93cbc2bSJung-uk Kim         {
2679a93cbc2bSJung-uk Kim             EVP_CIPHER_CTX *out = ptr;
2680e71b7053SJung-uk Kim             EVP_AES_GCM_CTX *gctx_out = EVP_C_DATA(EVP_AES_GCM_CTX,out);
26816f9291ceSJung-uk Kim             if (gctx->gcm.key) {
2682a93cbc2bSJung-uk Kim                 if (gctx->gcm.key != &gctx->ks)
2683a93cbc2bSJung-uk Kim                     return 0;
2684a93cbc2bSJung-uk Kim                 gctx_out->gcm.key = &gctx_out->ks;
2685a93cbc2bSJung-uk Kim             }
2686a93cbc2bSJung-uk Kim             if (gctx->iv == c->iv)
2687a93cbc2bSJung-uk Kim                 gctx_out->iv = out->iv;
26886f9291ceSJung-uk Kim             else {
2689e71b7053SJung-uk Kim                 if ((gctx_out->iv = OPENSSL_malloc(gctx->ivlen)) == NULL) {
2690b077aed3SPierre Pronchery                     ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
2691a93cbc2bSJung-uk Kim                     return 0;
2692e71b7053SJung-uk Kim                 }
2693a93cbc2bSJung-uk Kim                 memcpy(gctx_out->iv, gctx->iv, gctx->ivlen);
2694a93cbc2bSJung-uk Kim             }
2695a93cbc2bSJung-uk Kim             return 1;
2696a93cbc2bSJung-uk Kim         }
2697a93cbc2bSJung-uk Kim 
26981f13597dSJung-uk Kim     default:
26991f13597dSJung-uk Kim         return -1;
27001f13597dSJung-uk Kim 
27011f13597dSJung-uk Kim     }
27021f13597dSJung-uk Kim }
27031f13597dSJung-uk Kim 
aes_gcm_init_key(EVP_CIPHER_CTX * ctx,const unsigned char * key,const unsigned char * iv,int enc)27041f13597dSJung-uk Kim static int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
27051f13597dSJung-uk Kim                             const unsigned char *iv, int enc)
27061f13597dSJung-uk Kim {
2707e71b7053SJung-uk Kim     EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx);
27081f13597dSJung-uk Kim     if (!iv && !key)
27091f13597dSJung-uk Kim         return 1;
27106f9291ceSJung-uk Kim     if (key) {
27116f9291ceSJung-uk Kim         do {
27127bded2dbSJung-uk Kim #ifdef HWAES_CAPABLE
27137bded2dbSJung-uk Kim             if (HWAES_CAPABLE) {
27147bded2dbSJung-uk Kim                 HWAES_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks);
27157bded2dbSJung-uk Kim                 CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks,
27167bded2dbSJung-uk Kim                                    (block128_f) HWAES_encrypt);
27177bded2dbSJung-uk Kim # ifdef HWAES_ctr32_encrypt_blocks
27187bded2dbSJung-uk Kim                 gctx->ctr = (ctr128_f) HWAES_ctr32_encrypt_blocks;
27197bded2dbSJung-uk Kim # else
27207bded2dbSJung-uk Kim                 gctx->ctr = NULL;
27217bded2dbSJung-uk Kim # endif
27227bded2dbSJung-uk Kim                 break;
27237bded2dbSJung-uk Kim             } else
27247bded2dbSJung-uk Kim #endif
27251f13597dSJung-uk Kim #ifdef BSAES_CAPABLE
27266f9291ceSJung-uk Kim             if (BSAES_CAPABLE) {
27277bded2dbSJung-uk Kim                 AES_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks);
27281f13597dSJung-uk Kim                 CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks,
27291f13597dSJung-uk Kim                                    (block128_f) AES_encrypt);
2730b077aed3SPierre Pronchery                 gctx->ctr = (ctr128_f) ossl_bsaes_ctr32_encrypt_blocks;
27311f13597dSJung-uk Kim                 break;
27326f9291ceSJung-uk Kim             } else
27331f13597dSJung-uk Kim #endif
27341f13597dSJung-uk Kim #ifdef VPAES_CAPABLE
27356f9291ceSJung-uk Kim             if (VPAES_CAPABLE) {
27367bded2dbSJung-uk Kim                 vpaes_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks);
27371f13597dSJung-uk Kim                 CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks,
27381f13597dSJung-uk Kim                                    (block128_f) vpaes_encrypt);
27391f13597dSJung-uk Kim                 gctx->ctr = NULL;
27401f13597dSJung-uk Kim                 break;
27416f9291ceSJung-uk Kim             } else
27421f13597dSJung-uk Kim #endif
2743de78d5d8SJung-uk Kim                 (void)0;        /* terminate potentially open 'else' */
2744de78d5d8SJung-uk Kim 
27457bded2dbSJung-uk Kim             AES_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks);
27466f9291ceSJung-uk Kim             CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks,
27476f9291ceSJung-uk Kim                                (block128_f) AES_encrypt);
27481f13597dSJung-uk Kim #ifdef AES_CTR_ASM
27491f13597dSJung-uk Kim             gctx->ctr = (ctr128_f) AES_ctr32_encrypt;
27501f13597dSJung-uk Kim #else
27511f13597dSJung-uk Kim             gctx->ctr = NULL;
27521f13597dSJung-uk Kim #endif
27531f13597dSJung-uk Kim         } while (0);
27541f13597dSJung-uk Kim 
27556f9291ceSJung-uk Kim         /*
27566f9291ceSJung-uk Kim          * If we have an iv can set it directly, otherwise use saved IV.
27571f13597dSJung-uk Kim          */
27581f13597dSJung-uk Kim         if (iv == NULL && gctx->iv_set)
27591f13597dSJung-uk Kim             iv = gctx->iv;
27606f9291ceSJung-uk Kim         if (iv) {
27611f13597dSJung-uk Kim             CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen);
27621f13597dSJung-uk Kim             gctx->iv_set = 1;
27631f13597dSJung-uk Kim         }
27641f13597dSJung-uk Kim         gctx->key_set = 1;
27656f9291ceSJung-uk Kim     } else {
27661f13597dSJung-uk Kim         /* If key set use IV, otherwise copy */
27671f13597dSJung-uk Kim         if (gctx->key_set)
27681f13597dSJung-uk Kim             CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen);
27691f13597dSJung-uk Kim         else
27701f13597dSJung-uk Kim             memcpy(gctx->iv, iv, gctx->ivlen);
27711f13597dSJung-uk Kim         gctx->iv_set = 1;
27721f13597dSJung-uk Kim         gctx->iv_gen = 0;
27731f13597dSJung-uk Kim     }
27741f13597dSJung-uk Kim     return 1;
27751f13597dSJung-uk Kim }
27761f13597dSJung-uk Kim 
27776f9291ceSJung-uk Kim /*
27786f9291ceSJung-uk Kim  * Handle TLS GCM packet format. This consists of the last portion of the IV
27791f13597dSJung-uk Kim  * followed by the payload and finally the tag. On encrypt generate IV,
27801f13597dSJung-uk Kim  * encrypt payload and write the tag. On verify retrieve IV, decrypt payload
27811f13597dSJung-uk Kim  * and verify tag.
27821f13597dSJung-uk Kim  */
27831f13597dSJung-uk Kim 
aes_gcm_tls_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t len)27841f13597dSJung-uk Kim static int aes_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
27851f13597dSJung-uk Kim                               const unsigned char *in, size_t len)
27861f13597dSJung-uk Kim {
2787e71b7053SJung-uk Kim     EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx);
27881f13597dSJung-uk Kim     int rv = -1;
27891f13597dSJung-uk Kim     /* Encrypt/decrypt must be performed in place */
27906f9291ceSJung-uk Kim     if (out != in
27916f9291ceSJung-uk Kim         || len < (EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN))
27921f13597dSJung-uk Kim         return -1;
2793b077aed3SPierre Pronchery 
2794b077aed3SPierre Pronchery     /*
2795b077aed3SPierre Pronchery      * Check for too many keys as per FIPS 140-2 IG A.5 "Key/IV Pair Uniqueness
2796b077aed3SPierre Pronchery      * Requirements from SP 800-38D".  The requirements is for one party to the
2797b077aed3SPierre Pronchery      * communication to fail after 2^64 - 1 keys.  We do this on the encrypting
2798b077aed3SPierre Pronchery      * side only.
2799b077aed3SPierre Pronchery      */
2800b077aed3SPierre Pronchery     if (ctx->encrypt && ++gctx->tls_enc_records == 0) {
2801b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, EVP_R_TOO_MANY_RECORDS);
2802b077aed3SPierre Pronchery         goto err;
2803b077aed3SPierre Pronchery     }
2804b077aed3SPierre Pronchery 
28056f9291ceSJung-uk Kim     /*
28066f9291ceSJung-uk Kim      * Set IV from start of buffer or generate IV and write to start of
28076f9291ceSJung-uk Kim      * buffer.
28081f13597dSJung-uk Kim      */
2809e71b7053SJung-uk Kim     if (EVP_CIPHER_CTX_ctrl(ctx, ctx->encrypt ? EVP_CTRL_GCM_IV_GEN
2810e71b7053SJung-uk Kim                                               : EVP_CTRL_GCM_SET_IV_INV,
28111f13597dSJung-uk Kim                             EVP_GCM_TLS_EXPLICIT_IV_LEN, out) <= 0)
28121f13597dSJung-uk Kim         goto err;
28131f13597dSJung-uk Kim     /* Use saved AAD */
28141f13597dSJung-uk Kim     if (CRYPTO_gcm128_aad(&gctx->gcm, ctx->buf, gctx->tls_aad_len))
28151f13597dSJung-uk Kim         goto err;
28161f13597dSJung-uk Kim     /* Fix buffer and length to point to payload */
28171f13597dSJung-uk Kim     in += EVP_GCM_TLS_EXPLICIT_IV_LEN;
28181f13597dSJung-uk Kim     out += EVP_GCM_TLS_EXPLICIT_IV_LEN;
28191f13597dSJung-uk Kim     len -= EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
28206f9291ceSJung-uk Kim     if (ctx->encrypt) {
28211f13597dSJung-uk Kim         /* Encrypt payload */
28226f9291ceSJung-uk Kim         if (gctx->ctr) {
28237bded2dbSJung-uk Kim             size_t bulk = 0;
28247bded2dbSJung-uk Kim #if defined(AES_GCM_ASM)
28257bded2dbSJung-uk Kim             if (len >= 32 && AES_GCM_ASM(gctx)) {
28267bded2dbSJung-uk Kim                 if (CRYPTO_gcm128_encrypt(&gctx->gcm, NULL, NULL, 0))
28277bded2dbSJung-uk Kim                     return -1;
28287bded2dbSJung-uk Kim 
28297bded2dbSJung-uk Kim                 bulk = AES_gcm_encrypt(in, out, len,
28307bded2dbSJung-uk Kim                                        gctx->gcm.key,
28317bded2dbSJung-uk Kim                                        gctx->gcm.Yi.c, gctx->gcm.Xi.u);
28327bded2dbSJung-uk Kim                 gctx->gcm.len.u[1] += bulk;
28337bded2dbSJung-uk Kim             }
28347bded2dbSJung-uk Kim #endif
28351f13597dSJung-uk Kim             if (CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm,
28367bded2dbSJung-uk Kim                                             in + bulk,
28377bded2dbSJung-uk Kim                                             out + bulk,
28387bded2dbSJung-uk Kim                                             len - bulk, gctx->ctr))
28391f13597dSJung-uk Kim                 goto err;
28406f9291ceSJung-uk Kim         } else {
28417bded2dbSJung-uk Kim             size_t bulk = 0;
28427bded2dbSJung-uk Kim #if defined(AES_GCM_ASM2)
28437bded2dbSJung-uk Kim             if (len >= 32 && AES_GCM_ASM2(gctx)) {
28447bded2dbSJung-uk Kim                 if (CRYPTO_gcm128_encrypt(&gctx->gcm, NULL, NULL, 0))
28457bded2dbSJung-uk Kim                     return -1;
28467bded2dbSJung-uk Kim 
28477bded2dbSJung-uk Kim                 bulk = AES_gcm_encrypt(in, out, len,
28487bded2dbSJung-uk Kim                                        gctx->gcm.key,
28497bded2dbSJung-uk Kim                                        gctx->gcm.Yi.c, gctx->gcm.Xi.u);
28507bded2dbSJung-uk Kim                 gctx->gcm.len.u[1] += bulk;
28517bded2dbSJung-uk Kim             }
28527bded2dbSJung-uk Kim #endif
28537bded2dbSJung-uk Kim             if (CRYPTO_gcm128_encrypt(&gctx->gcm,
28547bded2dbSJung-uk Kim                                       in + bulk, out + bulk, len - bulk))
28551f13597dSJung-uk Kim                 goto err;
28561f13597dSJung-uk Kim         }
28571f13597dSJung-uk Kim         out += len;
28581f13597dSJung-uk Kim         /* Finally write tag */
28591f13597dSJung-uk Kim         CRYPTO_gcm128_tag(&gctx->gcm, out, EVP_GCM_TLS_TAG_LEN);
28601f13597dSJung-uk Kim         rv = len + EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
28616f9291ceSJung-uk Kim     } else {
28621f13597dSJung-uk Kim         /* Decrypt */
28636f9291ceSJung-uk Kim         if (gctx->ctr) {
28647bded2dbSJung-uk Kim             size_t bulk = 0;
28657bded2dbSJung-uk Kim #if defined(AES_GCM_ASM)
28667bded2dbSJung-uk Kim             if (len >= 16 && AES_GCM_ASM(gctx)) {
28677bded2dbSJung-uk Kim                 if (CRYPTO_gcm128_decrypt(&gctx->gcm, NULL, NULL, 0))
28687bded2dbSJung-uk Kim                     return -1;
28697bded2dbSJung-uk Kim 
28707bded2dbSJung-uk Kim                 bulk = AES_gcm_decrypt(in, out, len,
28717bded2dbSJung-uk Kim                                        gctx->gcm.key,
28727bded2dbSJung-uk Kim                                        gctx->gcm.Yi.c, gctx->gcm.Xi.u);
28737bded2dbSJung-uk Kim                 gctx->gcm.len.u[1] += bulk;
28747bded2dbSJung-uk Kim             }
28757bded2dbSJung-uk Kim #endif
28761f13597dSJung-uk Kim             if (CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm,
28777bded2dbSJung-uk Kim                                             in + bulk,
28787bded2dbSJung-uk Kim                                             out + bulk,
28797bded2dbSJung-uk Kim                                             len - bulk, gctx->ctr))
28801f13597dSJung-uk Kim                 goto err;
28816f9291ceSJung-uk Kim         } else {
28827bded2dbSJung-uk Kim             size_t bulk = 0;
28837bded2dbSJung-uk Kim #if defined(AES_GCM_ASM2)
28847bded2dbSJung-uk Kim             if (len >= 16 && AES_GCM_ASM2(gctx)) {
28857bded2dbSJung-uk Kim                 if (CRYPTO_gcm128_decrypt(&gctx->gcm, NULL, NULL, 0))
28867bded2dbSJung-uk Kim                     return -1;
28877bded2dbSJung-uk Kim 
28887bded2dbSJung-uk Kim                 bulk = AES_gcm_decrypt(in, out, len,
28897bded2dbSJung-uk Kim                                        gctx->gcm.key,
28907bded2dbSJung-uk Kim                                        gctx->gcm.Yi.c, gctx->gcm.Xi.u);
28917bded2dbSJung-uk Kim                 gctx->gcm.len.u[1] += bulk;
28927bded2dbSJung-uk Kim             }
28937bded2dbSJung-uk Kim #endif
28947bded2dbSJung-uk Kim             if (CRYPTO_gcm128_decrypt(&gctx->gcm,
28957bded2dbSJung-uk Kim                                       in + bulk, out + bulk, len - bulk))
28961f13597dSJung-uk Kim                 goto err;
28971f13597dSJung-uk Kim         }
28981f13597dSJung-uk Kim         /* Retrieve tag */
28996f9291ceSJung-uk Kim         CRYPTO_gcm128_tag(&gctx->gcm, ctx->buf, EVP_GCM_TLS_TAG_LEN);
29001f13597dSJung-uk Kim         /* If tag mismatch wipe buffer */
2901ed6b93beSJung-uk Kim         if (CRYPTO_memcmp(ctx->buf, in + len, EVP_GCM_TLS_TAG_LEN)) {
29021f13597dSJung-uk Kim             OPENSSL_cleanse(out, len);
29031f13597dSJung-uk Kim             goto err;
29041f13597dSJung-uk Kim         }
29051f13597dSJung-uk Kim         rv = len;
29061f13597dSJung-uk Kim     }
29071f13597dSJung-uk Kim 
29081f13597dSJung-uk Kim  err:
29091f13597dSJung-uk Kim     gctx->iv_set = 0;
29101f13597dSJung-uk Kim     gctx->tls_aad_len = -1;
29111f13597dSJung-uk Kim     return rv;
29121f13597dSJung-uk Kim }
29131f13597dSJung-uk Kim 
2914b077aed3SPierre Pronchery #ifdef FIPS_MODULE
2915b077aed3SPierre Pronchery /*
2916b077aed3SPierre Pronchery  * See SP800-38D (GCM) Section 8 "Uniqueness requirement on IVS and keys"
2917b077aed3SPierre Pronchery  *
2918b077aed3SPierre Pronchery  * See also 8.2.2 RBG-based construction.
2919b077aed3SPierre Pronchery  * Random construction consists of a free field (which can be NULL) and a
2920b077aed3SPierre Pronchery  * random field which will use a DRBG that can return at least 96 bits of
2921b077aed3SPierre Pronchery  * entropy strength. (The DRBG must be seeded by the FIPS module).
2922b077aed3SPierre Pronchery  */
aes_gcm_iv_generate(EVP_AES_GCM_CTX * gctx,int offset)2923b077aed3SPierre Pronchery static int aes_gcm_iv_generate(EVP_AES_GCM_CTX *gctx, int offset)
2924b077aed3SPierre Pronchery {
2925b077aed3SPierre Pronchery     int sz = gctx->ivlen - offset;
2926b077aed3SPierre Pronchery 
2927b077aed3SPierre Pronchery     /* Must be at least 96 bits */
2928b077aed3SPierre Pronchery     if (sz <= 0 || gctx->ivlen < 12)
2929b077aed3SPierre Pronchery         return 0;
2930b077aed3SPierre Pronchery 
2931b077aed3SPierre Pronchery     /* Use DRBG to generate random iv */
2932b077aed3SPierre Pronchery     if (RAND_bytes(gctx->iv + offset, sz) <= 0)
2933b077aed3SPierre Pronchery         return 0;
2934b077aed3SPierre Pronchery     return 1;
2935b077aed3SPierre Pronchery }
2936b077aed3SPierre Pronchery #endif /* FIPS_MODULE */
2937b077aed3SPierre Pronchery 
aes_gcm_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t len)29381f13597dSJung-uk Kim static int aes_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
29391f13597dSJung-uk Kim                           const unsigned char *in, size_t len)
29401f13597dSJung-uk Kim {
2941e71b7053SJung-uk Kim     EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx);
2942b077aed3SPierre Pronchery 
29431f13597dSJung-uk Kim     /* If not set up, return error */
29441f13597dSJung-uk Kim     if (!gctx->key_set)
29451f13597dSJung-uk Kim         return -1;
29461f13597dSJung-uk Kim 
29471f13597dSJung-uk Kim     if (gctx->tls_aad_len >= 0)
29481f13597dSJung-uk Kim         return aes_gcm_tls_cipher(ctx, out, in, len);
29491f13597dSJung-uk Kim 
2950b077aed3SPierre Pronchery #ifdef FIPS_MODULE
2951b077aed3SPierre Pronchery     /*
2952b077aed3SPierre Pronchery      * FIPS requires generation of AES-GCM IV's inside the FIPS module.
2953b077aed3SPierre Pronchery      * The IV can still be set externally (the security policy will state that
2954b077aed3SPierre Pronchery      * this is not FIPS compliant). There are some applications
2955b077aed3SPierre Pronchery      * where setting the IV externally is the only option available.
2956b077aed3SPierre Pronchery      */
2957b077aed3SPierre Pronchery     if (!gctx->iv_set) {
2958b077aed3SPierre Pronchery         if (!ctx->encrypt || !aes_gcm_iv_generate(gctx, 0))
2959b077aed3SPierre Pronchery             return -1;
2960b077aed3SPierre Pronchery         CRYPTO_gcm128_setiv(&gctx->gcm, gctx->iv, gctx->ivlen);
2961b077aed3SPierre Pronchery         gctx->iv_set = 1;
2962b077aed3SPierre Pronchery         gctx->iv_gen_rand = 1;
2963b077aed3SPierre Pronchery     }
2964b077aed3SPierre Pronchery #else
29651f13597dSJung-uk Kim     if (!gctx->iv_set)
29661f13597dSJung-uk Kim         return -1;
2967b077aed3SPierre Pronchery #endif /* FIPS_MODULE */
2968b077aed3SPierre Pronchery 
29696f9291ceSJung-uk Kim     if (in) {
29706f9291ceSJung-uk Kim         if (out == NULL) {
29711f13597dSJung-uk Kim             if (CRYPTO_gcm128_aad(&gctx->gcm, in, len))
29721f13597dSJung-uk Kim                 return -1;
29736f9291ceSJung-uk Kim         } else if (ctx->encrypt) {
29746f9291ceSJung-uk Kim             if (gctx->ctr) {
29757bded2dbSJung-uk Kim                 size_t bulk = 0;
29767bded2dbSJung-uk Kim #if defined(AES_GCM_ASM)
29777bded2dbSJung-uk Kim                 if (len >= 32 && AES_GCM_ASM(gctx)) {
29787bded2dbSJung-uk Kim                     size_t res = (16 - gctx->gcm.mres) % 16;
29797bded2dbSJung-uk Kim 
29807bded2dbSJung-uk Kim                     if (CRYPTO_gcm128_encrypt(&gctx->gcm, in, out, res))
29817bded2dbSJung-uk Kim                         return -1;
29827bded2dbSJung-uk Kim 
29837bded2dbSJung-uk Kim                     bulk = AES_gcm_encrypt(in + res,
29847bded2dbSJung-uk Kim                                            out + res, len - res,
29857bded2dbSJung-uk Kim                                            gctx->gcm.key, gctx->gcm.Yi.c,
29867bded2dbSJung-uk Kim                                            gctx->gcm.Xi.u);
29877bded2dbSJung-uk Kim                     gctx->gcm.len.u[1] += bulk;
29887bded2dbSJung-uk Kim                     bulk += res;
29897bded2dbSJung-uk Kim                 }
29907bded2dbSJung-uk Kim #endif
29911f13597dSJung-uk Kim                 if (CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm,
29927bded2dbSJung-uk Kim                                                 in + bulk,
29937bded2dbSJung-uk Kim                                                 out + bulk,
29947bded2dbSJung-uk Kim                                                 len - bulk, gctx->ctr))
29951f13597dSJung-uk Kim                     return -1;
29966f9291ceSJung-uk Kim             } else {
29977bded2dbSJung-uk Kim                 size_t bulk = 0;
29987bded2dbSJung-uk Kim #if defined(AES_GCM_ASM2)
29997bded2dbSJung-uk Kim                 if (len >= 32 && AES_GCM_ASM2(gctx)) {
30007bded2dbSJung-uk Kim                     size_t res = (16 - gctx->gcm.mres) % 16;
30017bded2dbSJung-uk Kim 
30027bded2dbSJung-uk Kim                     if (CRYPTO_gcm128_encrypt(&gctx->gcm, in, out, res))
30037bded2dbSJung-uk Kim                         return -1;
30047bded2dbSJung-uk Kim 
30057bded2dbSJung-uk Kim                     bulk = AES_gcm_encrypt(in + res,
30067bded2dbSJung-uk Kim                                            out + res, len - res,
30077bded2dbSJung-uk Kim                                            gctx->gcm.key, gctx->gcm.Yi.c,
30087bded2dbSJung-uk Kim                                            gctx->gcm.Xi.u);
30097bded2dbSJung-uk Kim                     gctx->gcm.len.u[1] += bulk;
30107bded2dbSJung-uk Kim                     bulk += res;
30117bded2dbSJung-uk Kim                 }
30127bded2dbSJung-uk Kim #endif
30137bded2dbSJung-uk Kim                 if (CRYPTO_gcm128_encrypt(&gctx->gcm,
30147bded2dbSJung-uk Kim                                           in + bulk, out + bulk, len - bulk))
30151f13597dSJung-uk Kim                     return -1;
30161f13597dSJung-uk Kim             }
30176f9291ceSJung-uk Kim         } else {
30186f9291ceSJung-uk Kim             if (gctx->ctr) {
30197bded2dbSJung-uk Kim                 size_t bulk = 0;
30207bded2dbSJung-uk Kim #if defined(AES_GCM_ASM)
30217bded2dbSJung-uk Kim                 if (len >= 16 && AES_GCM_ASM(gctx)) {
30227bded2dbSJung-uk Kim                     size_t res = (16 - gctx->gcm.mres) % 16;
30237bded2dbSJung-uk Kim 
30247bded2dbSJung-uk Kim                     if (CRYPTO_gcm128_decrypt(&gctx->gcm, in, out, res))
30257bded2dbSJung-uk Kim                         return -1;
30267bded2dbSJung-uk Kim 
30277bded2dbSJung-uk Kim                     bulk = AES_gcm_decrypt(in + res,
30287bded2dbSJung-uk Kim                                            out + res, len - res,
30297bded2dbSJung-uk Kim                                            gctx->gcm.key,
30307bded2dbSJung-uk Kim                                            gctx->gcm.Yi.c, gctx->gcm.Xi.u);
30317bded2dbSJung-uk Kim                     gctx->gcm.len.u[1] += bulk;
30327bded2dbSJung-uk Kim                     bulk += res;
30337bded2dbSJung-uk Kim                 }
30347bded2dbSJung-uk Kim #endif
30351f13597dSJung-uk Kim                 if (CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm,
30367bded2dbSJung-uk Kim                                                 in + bulk,
30377bded2dbSJung-uk Kim                                                 out + bulk,
30387bded2dbSJung-uk Kim                                                 len - bulk, gctx->ctr))
30391f13597dSJung-uk Kim                     return -1;
30406f9291ceSJung-uk Kim             } else {
30417bded2dbSJung-uk Kim                 size_t bulk = 0;
30427bded2dbSJung-uk Kim #if defined(AES_GCM_ASM2)
30437bded2dbSJung-uk Kim                 if (len >= 16 && AES_GCM_ASM2(gctx)) {
30447bded2dbSJung-uk Kim                     size_t res = (16 - gctx->gcm.mres) % 16;
30457bded2dbSJung-uk Kim 
30467bded2dbSJung-uk Kim                     if (CRYPTO_gcm128_decrypt(&gctx->gcm, in, out, res))
30477bded2dbSJung-uk Kim                         return -1;
30487bded2dbSJung-uk Kim 
30497bded2dbSJung-uk Kim                     bulk = AES_gcm_decrypt(in + res,
30507bded2dbSJung-uk Kim                                            out + res, len - res,
30517bded2dbSJung-uk Kim                                            gctx->gcm.key,
30527bded2dbSJung-uk Kim                                            gctx->gcm.Yi.c, gctx->gcm.Xi.u);
30537bded2dbSJung-uk Kim                     gctx->gcm.len.u[1] += bulk;
30547bded2dbSJung-uk Kim                     bulk += res;
30557bded2dbSJung-uk Kim                 }
30567bded2dbSJung-uk Kim #endif
30577bded2dbSJung-uk Kim                 if (CRYPTO_gcm128_decrypt(&gctx->gcm,
30587bded2dbSJung-uk Kim                                           in + bulk, out + bulk, len - bulk))
30591f13597dSJung-uk Kim                     return -1;
30601f13597dSJung-uk Kim             }
30611f13597dSJung-uk Kim         }
30621f13597dSJung-uk Kim         return len;
30636f9291ceSJung-uk Kim     } else {
30646f9291ceSJung-uk Kim         if (!ctx->encrypt) {
306509286989SJung-uk Kim             if (gctx->taglen < 0)
306609286989SJung-uk Kim                 return -1;
30676f9291ceSJung-uk Kim             if (CRYPTO_gcm128_finish(&gctx->gcm, ctx->buf, gctx->taglen) != 0)
30681f13597dSJung-uk Kim                 return -1;
30691f13597dSJung-uk Kim             gctx->iv_set = 0;
30701f13597dSJung-uk Kim             return 0;
30711f13597dSJung-uk Kim         }
30721f13597dSJung-uk Kim         CRYPTO_gcm128_tag(&gctx->gcm, ctx->buf, 16);
30731f13597dSJung-uk Kim         gctx->taglen = 16;
30741f13597dSJung-uk Kim         /* Don't reuse the IV */
30751f13597dSJung-uk Kim         gctx->iv_set = 0;
30761f13597dSJung-uk Kim         return 0;
30771f13597dSJung-uk Kim     }
30781f13597dSJung-uk Kim 
30791f13597dSJung-uk Kim }
30801f13597dSJung-uk Kim 
30811f13597dSJung-uk Kim #define CUSTOM_FLAGS    (EVP_CIPH_FLAG_DEFAULT_ASN1 \
30821f13597dSJung-uk Kim                 | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \
3083a93cbc2bSJung-uk Kim                 | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \
3084da327cd2SJung-uk Kim                 | EVP_CIPH_CUSTOM_COPY | EVP_CIPH_CUSTOM_IV_LENGTH)
30851f13597dSJung-uk Kim 
30861f13597dSJung-uk Kim BLOCK_CIPHER_custom(NID_aes, 128, 1, 12, gcm, GCM,
3087e71b7053SJung-uk Kim                     EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS)
30881f13597dSJung-uk Kim     BLOCK_CIPHER_custom(NID_aes, 192, 1, 12, gcm, GCM,
3089e71b7053SJung-uk Kim                     EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS)
30901f13597dSJung-uk Kim     BLOCK_CIPHER_custom(NID_aes, 256, 1, 12, gcm, GCM,
3091e71b7053SJung-uk Kim                     EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS)
30921f13597dSJung-uk Kim 
aes_xts_ctrl(EVP_CIPHER_CTX * c,int type,int arg,void * ptr)30931f13597dSJung-uk Kim static int aes_xts_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
30941f13597dSJung-uk Kim {
3095e71b7053SJung-uk Kim     EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX, c);
3096da327cd2SJung-uk Kim 
30976f9291ceSJung-uk Kim     if (type == EVP_CTRL_COPY) {
3098a93cbc2bSJung-uk Kim         EVP_CIPHER_CTX *out = ptr;
3099e71b7053SJung-uk Kim         EVP_AES_XTS_CTX *xctx_out = EVP_C_DATA(EVP_AES_XTS_CTX,out);
3100da327cd2SJung-uk Kim 
31016f9291ceSJung-uk Kim         if (xctx->xts.key1) {
3102a93cbc2bSJung-uk Kim             if (xctx->xts.key1 != &xctx->ks1)
3103a93cbc2bSJung-uk Kim                 return 0;
3104a93cbc2bSJung-uk Kim             xctx_out->xts.key1 = &xctx_out->ks1;
3105a93cbc2bSJung-uk Kim         }
31066f9291ceSJung-uk Kim         if (xctx->xts.key2) {
3107a93cbc2bSJung-uk Kim             if (xctx->xts.key2 != &xctx->ks2)
3108a93cbc2bSJung-uk Kim                 return 0;
3109a93cbc2bSJung-uk Kim             xctx_out->xts.key2 = &xctx_out->ks2;
3110a93cbc2bSJung-uk Kim         }
3111a93cbc2bSJung-uk Kim         return 1;
31126f9291ceSJung-uk Kim     } else if (type != EVP_CTRL_INIT)
31131f13597dSJung-uk Kim         return -1;
31141f13597dSJung-uk Kim     /* key1 and key2 are used as an indicator both key and IV are set */
31151f13597dSJung-uk Kim     xctx->xts.key1 = NULL;
31161f13597dSJung-uk Kim     xctx->xts.key2 = NULL;
31171f13597dSJung-uk Kim     return 1;
31181f13597dSJung-uk Kim }
31191f13597dSJung-uk Kim 
aes_xts_init_key(EVP_CIPHER_CTX * ctx,const unsigned char * key,const unsigned char * iv,int enc)31201f13597dSJung-uk Kim static int aes_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
31211f13597dSJung-uk Kim                             const unsigned char *iv, int enc)
31221f13597dSJung-uk Kim {
3123e71b7053SJung-uk Kim     EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,ctx);
3124da327cd2SJung-uk Kim 
31251f13597dSJung-uk Kim     if (!iv && !key)
31261f13597dSJung-uk Kim         return 1;
31271f13597dSJung-uk Kim 
3128b077aed3SPierre Pronchery     if (key) {
31296f9291ceSJung-uk Kim         do {
3130da327cd2SJung-uk Kim             /* The key is two half length keys in reality */
3131b077aed3SPierre Pronchery             const int bytes = EVP_CIPHER_CTX_get_key_length(ctx) / 2;
3132b077aed3SPierre Pronchery             const int bits = bytes * 8;
3133da327cd2SJung-uk Kim 
3134da327cd2SJung-uk Kim             /*
3135da327cd2SJung-uk Kim              * Verify that the two keys are different.
3136da327cd2SJung-uk Kim              *
3137da327cd2SJung-uk Kim              * This addresses the vulnerability described in Rogaway's
3138da327cd2SJung-uk Kim              * September 2004 paper:
3139da327cd2SJung-uk Kim              *
3140da327cd2SJung-uk Kim              *      "Efficient Instantiations of Tweakable Blockciphers and
3141da327cd2SJung-uk Kim              *       Refinements to Modes OCB and PMAC".
3142da327cd2SJung-uk Kim              *      (http://web.cs.ucdavis.edu/~rogaway/papers/offsets.pdf)
3143da327cd2SJung-uk Kim              *
3144da327cd2SJung-uk Kim              * FIPS 140-2 IG A.9 XTS-AES Key Generation Requirements states
3145da327cd2SJung-uk Kim              * that:
3146da327cd2SJung-uk Kim              *      "The check for Key_1 != Key_2 shall be done at any place
3147da327cd2SJung-uk Kim              *       BEFORE using the keys in the XTS-AES algorithm to process
3148da327cd2SJung-uk Kim              *       data with them."
3149da327cd2SJung-uk Kim              */
3150b077aed3SPierre Pronchery             if ((!allow_insecure_decrypt || enc)
3151b077aed3SPierre Pronchery                     && CRYPTO_memcmp(key, key + bytes, bytes) == 0) {
3152b077aed3SPierre Pronchery                 ERR_raise(ERR_LIB_EVP, EVP_R_XTS_DUPLICATED_KEYS);
3153da327cd2SJung-uk Kim                 return 0;
3154da327cd2SJung-uk Kim             }
3155da327cd2SJung-uk Kim 
31561f13597dSJung-uk Kim #ifdef AES_XTS_ASM
31571f13597dSJung-uk Kim             xctx->stream = enc ? AES_xts_encrypt : AES_xts_decrypt;
31581f13597dSJung-uk Kim #else
31591f13597dSJung-uk Kim             xctx->stream = NULL;
31601f13597dSJung-uk Kim #endif
31611f13597dSJung-uk Kim             /* key_len is two AES keys */
31627bded2dbSJung-uk Kim #ifdef HWAES_CAPABLE
31637bded2dbSJung-uk Kim             if (HWAES_CAPABLE) {
31647bded2dbSJung-uk Kim                 if (enc) {
3165b077aed3SPierre Pronchery                     HWAES_set_encrypt_key(key, bits, &xctx->ks1.ks);
31667bded2dbSJung-uk Kim                     xctx->xts.block1 = (block128_f) HWAES_encrypt;
3167e71b7053SJung-uk Kim # ifdef HWAES_xts_encrypt
3168e71b7053SJung-uk Kim                     xctx->stream = HWAES_xts_encrypt;
3169e71b7053SJung-uk Kim # endif
31707bded2dbSJung-uk Kim                 } else {
3171b077aed3SPierre Pronchery                     HWAES_set_decrypt_key(key, bits, &xctx->ks1.ks);
31727bded2dbSJung-uk Kim                     xctx->xts.block1 = (block128_f) HWAES_decrypt;
3173e71b7053SJung-uk Kim # ifdef HWAES_xts_decrypt
3174e71b7053SJung-uk Kim                     xctx->stream = HWAES_xts_decrypt;
3175e71b7053SJung-uk Kim #endif
31767bded2dbSJung-uk Kim                 }
31777bded2dbSJung-uk Kim 
3178b077aed3SPierre Pronchery                 HWAES_set_encrypt_key(key + bytes, bits, &xctx->ks2.ks);
31797bded2dbSJung-uk Kim                 xctx->xts.block2 = (block128_f) HWAES_encrypt;
31807bded2dbSJung-uk Kim 
31817bded2dbSJung-uk Kim                 xctx->xts.key1 = &xctx->ks1;
31827bded2dbSJung-uk Kim                 break;
31837bded2dbSJung-uk Kim             } else
31847bded2dbSJung-uk Kim #endif
31851f13597dSJung-uk Kim #ifdef BSAES_CAPABLE
31861f13597dSJung-uk Kim             if (BSAES_CAPABLE)
3187b077aed3SPierre Pronchery                 xctx->stream = enc ? ossl_bsaes_xts_encrypt : ossl_bsaes_xts_decrypt;
31881f13597dSJung-uk Kim             else
31891f13597dSJung-uk Kim #endif
31901f13597dSJung-uk Kim #ifdef VPAES_CAPABLE
31916f9291ceSJung-uk Kim             if (VPAES_CAPABLE) {
31926f9291ceSJung-uk Kim                 if (enc) {
3193b077aed3SPierre Pronchery                     vpaes_set_encrypt_key(key, bits, &xctx->ks1.ks);
31941f13597dSJung-uk Kim                     xctx->xts.block1 = (block128_f) vpaes_encrypt;
31956f9291ceSJung-uk Kim                 } else {
3196b077aed3SPierre Pronchery                     vpaes_set_decrypt_key(key, bits, &xctx->ks1.ks);
31971f13597dSJung-uk Kim                     xctx->xts.block1 = (block128_f) vpaes_decrypt;
31981f13597dSJung-uk Kim                 }
31991f13597dSJung-uk Kim 
3200b077aed3SPierre Pronchery                 vpaes_set_encrypt_key(key + bytes, bits, &xctx->ks2.ks);
32011f13597dSJung-uk Kim                 xctx->xts.block2 = (block128_f) vpaes_encrypt;
32021f13597dSJung-uk Kim 
32031f13597dSJung-uk Kim                 xctx->xts.key1 = &xctx->ks1;
32041f13597dSJung-uk Kim                 break;
32056f9291ceSJung-uk Kim             } else
32061f13597dSJung-uk Kim #endif
3207de78d5d8SJung-uk Kim                 (void)0;        /* terminate potentially open 'else' */
3208de78d5d8SJung-uk Kim 
32096f9291ceSJung-uk Kim             if (enc) {
3210b077aed3SPierre Pronchery                 AES_set_encrypt_key(key, bits, &xctx->ks1.ks);
32111f13597dSJung-uk Kim                 xctx->xts.block1 = (block128_f) AES_encrypt;
32126f9291ceSJung-uk Kim             } else {
3213b077aed3SPierre Pronchery                 AES_set_decrypt_key(key, bits, &xctx->ks1.ks);
32141f13597dSJung-uk Kim                 xctx->xts.block1 = (block128_f) AES_decrypt;
32151f13597dSJung-uk Kim             }
32161f13597dSJung-uk Kim 
3217b077aed3SPierre Pronchery             AES_set_encrypt_key(key + bytes, bits, &xctx->ks2.ks);
32181f13597dSJung-uk Kim             xctx->xts.block2 = (block128_f) AES_encrypt;
32191f13597dSJung-uk Kim 
32201f13597dSJung-uk Kim             xctx->xts.key1 = &xctx->ks1;
32211f13597dSJung-uk Kim         } while (0);
3222b077aed3SPierre Pronchery     }
32231f13597dSJung-uk Kim 
32246f9291ceSJung-uk Kim     if (iv) {
32251f13597dSJung-uk Kim         xctx->xts.key2 = &xctx->ks2;
3226b077aed3SPierre Pronchery         memcpy(ctx->iv, iv, 16);
32271f13597dSJung-uk Kim     }
32281f13597dSJung-uk Kim 
32291f13597dSJung-uk Kim     return 1;
32301f13597dSJung-uk Kim }
32311f13597dSJung-uk Kim 
aes_xts_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t len)32321f13597dSJung-uk Kim static int aes_xts_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
32331f13597dSJung-uk Kim                           const unsigned char *in, size_t len)
32341f13597dSJung-uk Kim {
3235e71b7053SJung-uk Kim     EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,ctx);
3236b077aed3SPierre Pronchery 
3237b077aed3SPierre Pronchery     if (xctx->xts.key1 == NULL
3238b077aed3SPierre Pronchery             || xctx->xts.key2 == NULL
3239b077aed3SPierre Pronchery             || out == NULL
3240b077aed3SPierre Pronchery             || in == NULL
3241b077aed3SPierre Pronchery             || len < AES_BLOCK_SIZE)
32421f13597dSJung-uk Kim         return 0;
3243b077aed3SPierre Pronchery 
3244b077aed3SPierre Pronchery     /*
3245b077aed3SPierre Pronchery      * Impose a limit of 2^20 blocks per data unit as specified by
3246b077aed3SPierre Pronchery      * IEEE Std 1619-2018.  The earlier and obsolete IEEE Std 1619-2007
3247b077aed3SPierre Pronchery      * indicated that this was a SHOULD NOT rather than a MUST NOT.
3248b077aed3SPierre Pronchery      * NIST SP 800-38E mandates the same limit.
3249b077aed3SPierre Pronchery      */
3250b077aed3SPierre Pronchery     if (len > XTS_MAX_BLOCKS_PER_DATA_UNIT * AES_BLOCK_SIZE) {
3251b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, EVP_R_XTS_DATA_UNIT_IS_TOO_LARGE);
32521f13597dSJung-uk Kim         return 0;
3253b077aed3SPierre Pronchery     }
3254b077aed3SPierre Pronchery 
32551f13597dSJung-uk Kim     if (xctx->stream)
32561f13597dSJung-uk Kim         (*xctx->stream) (in, out, len,
3257e71b7053SJung-uk Kim                          xctx->xts.key1, xctx->xts.key2,
3258b077aed3SPierre Pronchery                          ctx->iv);
3259b077aed3SPierre Pronchery     else if (CRYPTO_xts128_encrypt(&xctx->xts, ctx->iv, in, out, len,
3260b077aed3SPierre Pronchery                                    EVP_CIPHER_CTX_is_encrypting(ctx)))
32611f13597dSJung-uk Kim         return 0;
32621f13597dSJung-uk Kim     return 1;
32631f13597dSJung-uk Kim }
32641f13597dSJung-uk Kim 
32651f13597dSJung-uk Kim #define aes_xts_cleanup NULL
32661f13597dSJung-uk Kim 
32671f13597dSJung-uk Kim #define XTS_FLAGS       (EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CUSTOM_IV \
3268a93cbc2bSJung-uk Kim                          | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \
3269a93cbc2bSJung-uk Kim                          | EVP_CIPH_CUSTOM_COPY)
32701f13597dSJung-uk Kim 
3271e71b7053SJung-uk Kim BLOCK_CIPHER_custom(NID_aes, 128, 1, 16, xts, XTS, XTS_FLAGS)
3272e71b7053SJung-uk Kim     BLOCK_CIPHER_custom(NID_aes, 256, 1, 16, xts, XTS, XTS_FLAGS)
32731f13597dSJung-uk Kim 
aes_ccm_ctrl(EVP_CIPHER_CTX * c,int type,int arg,void * ptr)32741f13597dSJung-uk Kim static int aes_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
32751f13597dSJung-uk Kim {
3276e71b7053SJung-uk Kim     EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,c);
32776f9291ceSJung-uk Kim     switch (type) {
32781f13597dSJung-uk Kim     case EVP_CTRL_INIT:
32791f13597dSJung-uk Kim         cctx->key_set = 0;
32801f13597dSJung-uk Kim         cctx->iv_set = 0;
32811f13597dSJung-uk Kim         cctx->L = 8;
32821f13597dSJung-uk Kim         cctx->M = 12;
32831f13597dSJung-uk Kim         cctx->tag_set = 0;
32841f13597dSJung-uk Kim         cctx->len_set = 0;
3285e71b7053SJung-uk Kim         cctx->tls_aad_len = -1;
32861f13597dSJung-uk Kim         return 1;
3287b077aed3SPierre Pronchery 
3288da327cd2SJung-uk Kim     case EVP_CTRL_GET_IVLEN:
3289da327cd2SJung-uk Kim         *(int *)ptr = 15 - cctx->L;
3290da327cd2SJung-uk Kim         return 1;
3291b077aed3SPierre Pronchery 
3292e71b7053SJung-uk Kim     case EVP_CTRL_AEAD_TLS1_AAD:
3293e71b7053SJung-uk Kim         /* Save the AAD for later use */
3294e71b7053SJung-uk Kim         if (arg != EVP_AEAD_TLS1_AAD_LEN)
3295e71b7053SJung-uk Kim             return 0;
3296e71b7053SJung-uk Kim         memcpy(EVP_CIPHER_CTX_buf_noconst(c), ptr, arg);
3297e71b7053SJung-uk Kim         cctx->tls_aad_len = arg;
3298e71b7053SJung-uk Kim         {
3299e71b7053SJung-uk Kim             uint16_t len =
3300e71b7053SJung-uk Kim                 EVP_CIPHER_CTX_buf_noconst(c)[arg - 2] << 8
3301e71b7053SJung-uk Kim                 | EVP_CIPHER_CTX_buf_noconst(c)[arg - 1];
3302e71b7053SJung-uk Kim             /* Correct length for explicit IV */
3303e71b7053SJung-uk Kim             if (len < EVP_CCM_TLS_EXPLICIT_IV_LEN)
3304e71b7053SJung-uk Kim                 return 0;
3305e71b7053SJung-uk Kim             len -= EVP_CCM_TLS_EXPLICIT_IV_LEN;
3306e71b7053SJung-uk Kim             /* If decrypting correct for tag too */
3307b077aed3SPierre Pronchery             if (!EVP_CIPHER_CTX_is_encrypting(c)) {
3308e71b7053SJung-uk Kim                 if (len < cctx->M)
3309e71b7053SJung-uk Kim                     return 0;
3310e71b7053SJung-uk Kim                 len -= cctx->M;
3311e71b7053SJung-uk Kim             }
3312e71b7053SJung-uk Kim             EVP_CIPHER_CTX_buf_noconst(c)[arg - 2] = len >> 8;
3313e71b7053SJung-uk Kim             EVP_CIPHER_CTX_buf_noconst(c)[arg - 1] = len & 0xff;
3314e71b7053SJung-uk Kim         }
3315e71b7053SJung-uk Kim         /* Extra padding: tag appended to record */
3316e71b7053SJung-uk Kim         return cctx->M;
3317e71b7053SJung-uk Kim 
3318e71b7053SJung-uk Kim     case EVP_CTRL_CCM_SET_IV_FIXED:
3319e71b7053SJung-uk Kim         /* Sanity check length */
3320e71b7053SJung-uk Kim         if (arg != EVP_CCM_TLS_FIXED_IV_LEN)
3321e71b7053SJung-uk Kim             return 0;
3322e71b7053SJung-uk Kim         /* Just copy to first part of IV */
3323b077aed3SPierre Pronchery         memcpy(c->iv, ptr, arg);
3324e71b7053SJung-uk Kim         return 1;
3325e71b7053SJung-uk Kim 
3326e71b7053SJung-uk Kim     case EVP_CTRL_AEAD_SET_IVLEN:
33271f13597dSJung-uk Kim         arg = 15 - arg;
3328e71b7053SJung-uk Kim         /* fall thru */
33291f13597dSJung-uk Kim     case EVP_CTRL_CCM_SET_L:
33301f13597dSJung-uk Kim         if (arg < 2 || arg > 8)
33311f13597dSJung-uk Kim             return 0;
33321f13597dSJung-uk Kim         cctx->L = arg;
33331f13597dSJung-uk Kim         return 1;
33341f13597dSJung-uk Kim 
3335e71b7053SJung-uk Kim     case EVP_CTRL_AEAD_SET_TAG:
33361f13597dSJung-uk Kim         if ((arg & 1) || arg < 4 || arg > 16)
33371f13597dSJung-uk Kim             return 0;
3338b077aed3SPierre Pronchery         if (EVP_CIPHER_CTX_is_encrypting(c) && ptr)
33391f13597dSJung-uk Kim             return 0;
33406f9291ceSJung-uk Kim         if (ptr) {
33411f13597dSJung-uk Kim             cctx->tag_set = 1;
3342e71b7053SJung-uk Kim             memcpy(EVP_CIPHER_CTX_buf_noconst(c), ptr, arg);
33431f13597dSJung-uk Kim         }
33441f13597dSJung-uk Kim         cctx->M = arg;
33451f13597dSJung-uk Kim         return 1;
33461f13597dSJung-uk Kim 
3347e71b7053SJung-uk Kim     case EVP_CTRL_AEAD_GET_TAG:
3348b077aed3SPierre Pronchery         if (!EVP_CIPHER_CTX_is_encrypting(c) || !cctx->tag_set)
33491f13597dSJung-uk Kim             return 0;
33501f13597dSJung-uk Kim         if (!CRYPTO_ccm128_tag(&cctx->ccm, ptr, (size_t)arg))
33511f13597dSJung-uk Kim             return 0;
33521f13597dSJung-uk Kim         cctx->tag_set = 0;
33531f13597dSJung-uk Kim         cctx->iv_set = 0;
33541f13597dSJung-uk Kim         cctx->len_set = 0;
33551f13597dSJung-uk Kim         return 1;
33561f13597dSJung-uk Kim 
3357a93cbc2bSJung-uk Kim     case EVP_CTRL_COPY:
3358a93cbc2bSJung-uk Kim         {
3359a93cbc2bSJung-uk Kim             EVP_CIPHER_CTX *out = ptr;
3360e71b7053SJung-uk Kim             EVP_AES_CCM_CTX *cctx_out = EVP_C_DATA(EVP_AES_CCM_CTX,out);
33616f9291ceSJung-uk Kim             if (cctx->ccm.key) {
3362a93cbc2bSJung-uk Kim                 if (cctx->ccm.key != &cctx->ks)
3363a93cbc2bSJung-uk Kim                     return 0;
3364a93cbc2bSJung-uk Kim                 cctx_out->ccm.key = &cctx_out->ks;
3365a93cbc2bSJung-uk Kim             }
3366a93cbc2bSJung-uk Kim             return 1;
3367a93cbc2bSJung-uk Kim         }
3368a93cbc2bSJung-uk Kim 
33691f13597dSJung-uk Kim     default:
33701f13597dSJung-uk Kim         return -1;
33711f13597dSJung-uk Kim 
33721f13597dSJung-uk Kim     }
33731f13597dSJung-uk Kim }
33741f13597dSJung-uk Kim 
aes_ccm_init_key(EVP_CIPHER_CTX * ctx,const unsigned char * key,const unsigned char * iv,int enc)33751f13597dSJung-uk Kim static int aes_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
33761f13597dSJung-uk Kim                             const unsigned char *iv, int enc)
33771f13597dSJung-uk Kim {
3378e71b7053SJung-uk Kim     EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx);
33791f13597dSJung-uk Kim     if (!iv && !key)
33801f13597dSJung-uk Kim         return 1;
33816f9291ceSJung-uk Kim     if (key)
33826f9291ceSJung-uk Kim         do {
33837bded2dbSJung-uk Kim #ifdef HWAES_CAPABLE
33847bded2dbSJung-uk Kim             if (HWAES_CAPABLE) {
3385b077aed3SPierre Pronchery                 HWAES_set_encrypt_key(key,
3386b077aed3SPierre Pronchery                                       EVP_CIPHER_CTX_get_key_length(ctx) * 8,
3387e71b7053SJung-uk Kim                                       &cctx->ks.ks);
33887bded2dbSJung-uk Kim 
33897bded2dbSJung-uk Kim                 CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L,
33907bded2dbSJung-uk Kim                                    &cctx->ks, (block128_f) HWAES_encrypt);
33917bded2dbSJung-uk Kim                 cctx->str = NULL;
33927bded2dbSJung-uk Kim                 cctx->key_set = 1;
33937bded2dbSJung-uk Kim                 break;
33947bded2dbSJung-uk Kim             } else
33957bded2dbSJung-uk Kim #endif
33961f13597dSJung-uk Kim #ifdef VPAES_CAPABLE
33976f9291ceSJung-uk Kim             if (VPAES_CAPABLE) {
3398b077aed3SPierre Pronchery                 vpaes_set_encrypt_key(key,
3399b077aed3SPierre Pronchery                                       EVP_CIPHER_CTX_get_key_length(ctx) * 8,
3400e71b7053SJung-uk Kim                                       &cctx->ks.ks);
34011f13597dSJung-uk Kim                 CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L,
34021f13597dSJung-uk Kim                                    &cctx->ks, (block128_f) vpaes_encrypt);
340309286989SJung-uk Kim                 cctx->str = NULL;
34041f13597dSJung-uk Kim                 cctx->key_set = 1;
34051f13597dSJung-uk Kim                 break;
34061f13597dSJung-uk Kim             }
34071f13597dSJung-uk Kim #endif
3408b077aed3SPierre Pronchery             AES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
3409e71b7053SJung-uk Kim                                 &cctx->ks.ks);
34101f13597dSJung-uk Kim             CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L,
34111f13597dSJung-uk Kim                                &cctx->ks, (block128_f) AES_encrypt);
34121f13597dSJung-uk Kim             cctx->str = NULL;
34131f13597dSJung-uk Kim             cctx->key_set = 1;
34141f13597dSJung-uk Kim         } while (0);
34156f9291ceSJung-uk Kim     if (iv) {
3416b077aed3SPierre Pronchery         memcpy(ctx->iv, iv, 15 - cctx->L);
34171f13597dSJung-uk Kim         cctx->iv_set = 1;
34181f13597dSJung-uk Kim     }
34191f13597dSJung-uk Kim     return 1;
34201f13597dSJung-uk Kim }
34211f13597dSJung-uk Kim 
aes_ccm_tls_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t len)3422e71b7053SJung-uk Kim static int aes_ccm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
3423e71b7053SJung-uk Kim                               const unsigned char *in, size_t len)
3424e71b7053SJung-uk Kim {
3425e71b7053SJung-uk Kim     EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx);
3426e71b7053SJung-uk Kim     CCM128_CONTEXT *ccm = &cctx->ccm;
3427e71b7053SJung-uk Kim     /* Encrypt/decrypt must be performed in place */
3428e71b7053SJung-uk Kim     if (out != in || len < (EVP_CCM_TLS_EXPLICIT_IV_LEN + (size_t)cctx->M))
3429e71b7053SJung-uk Kim         return -1;
3430e71b7053SJung-uk Kim     /* If encrypting set explicit IV from sequence number (start of AAD) */
3431b077aed3SPierre Pronchery     if (EVP_CIPHER_CTX_is_encrypting(ctx))
3432e71b7053SJung-uk Kim         memcpy(out, EVP_CIPHER_CTX_buf_noconst(ctx),
3433e71b7053SJung-uk Kim                EVP_CCM_TLS_EXPLICIT_IV_LEN);
3434e71b7053SJung-uk Kim     /* Get rest of IV from explicit IV */
3435b077aed3SPierre Pronchery     memcpy(ctx->iv + EVP_CCM_TLS_FIXED_IV_LEN, in,
3436e71b7053SJung-uk Kim            EVP_CCM_TLS_EXPLICIT_IV_LEN);
3437e71b7053SJung-uk Kim     /* Correct length value */
3438e71b7053SJung-uk Kim     len -= EVP_CCM_TLS_EXPLICIT_IV_LEN + cctx->M;
3439b077aed3SPierre Pronchery     if (CRYPTO_ccm128_setiv(ccm, ctx->iv, 15 - cctx->L,
3440e71b7053SJung-uk Kim                             len))
3441e71b7053SJung-uk Kim             return -1;
3442e71b7053SJung-uk Kim     /* Use saved AAD */
3443b077aed3SPierre Pronchery     CRYPTO_ccm128_aad(ccm, EVP_CIPHER_CTX_buf_noconst(ctx),
3444b077aed3SPierre Pronchery                       cctx->tls_aad_len);
3445e71b7053SJung-uk Kim     /* Fix buffer to point to payload */
3446e71b7053SJung-uk Kim     in += EVP_CCM_TLS_EXPLICIT_IV_LEN;
3447e71b7053SJung-uk Kim     out += EVP_CCM_TLS_EXPLICIT_IV_LEN;
3448b077aed3SPierre Pronchery     if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
3449e71b7053SJung-uk Kim         if (cctx->str ? CRYPTO_ccm128_encrypt_ccm64(ccm, in, out, len,
3450e71b7053SJung-uk Kim                                                     cctx->str) :
3451e71b7053SJung-uk Kim             CRYPTO_ccm128_encrypt(ccm, in, out, len))
3452e71b7053SJung-uk Kim             return -1;
3453e71b7053SJung-uk Kim         if (!CRYPTO_ccm128_tag(ccm, out + len, cctx->M))
3454e71b7053SJung-uk Kim             return -1;
3455e71b7053SJung-uk Kim         return len + EVP_CCM_TLS_EXPLICIT_IV_LEN + cctx->M;
3456e71b7053SJung-uk Kim     } else {
3457e71b7053SJung-uk Kim         if (cctx->str ? !CRYPTO_ccm128_decrypt_ccm64(ccm, in, out, len,
3458e71b7053SJung-uk Kim                                                      cctx->str) :
3459e71b7053SJung-uk Kim             !CRYPTO_ccm128_decrypt(ccm, in, out, len)) {
3460e71b7053SJung-uk Kim             unsigned char tag[16];
3461e71b7053SJung-uk Kim             if (CRYPTO_ccm128_tag(ccm, tag, cctx->M)) {
3462e71b7053SJung-uk Kim                 if (!CRYPTO_memcmp(tag, in + len, cctx->M))
3463e71b7053SJung-uk Kim                     return len;
3464e71b7053SJung-uk Kim             }
3465e71b7053SJung-uk Kim         }
3466e71b7053SJung-uk Kim         OPENSSL_cleanse(out, len);
3467e71b7053SJung-uk Kim         return -1;
3468e71b7053SJung-uk Kim     }
3469e71b7053SJung-uk Kim }
3470e71b7053SJung-uk Kim 
aes_ccm_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t len)34711f13597dSJung-uk Kim static int aes_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
34721f13597dSJung-uk Kim                           const unsigned char *in, size_t len)
34731f13597dSJung-uk Kim {
3474e71b7053SJung-uk Kim     EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx);
34751f13597dSJung-uk Kim     CCM128_CONTEXT *ccm = &cctx->ccm;
34761f13597dSJung-uk Kim     /* If not set up, return error */
3477e71b7053SJung-uk Kim     if (!cctx->key_set)
34781f13597dSJung-uk Kim         return -1;
3479e71b7053SJung-uk Kim 
3480e71b7053SJung-uk Kim     if (cctx->tls_aad_len >= 0)
3481e71b7053SJung-uk Kim         return aes_ccm_tls_cipher(ctx, out, in, len);
3482e71b7053SJung-uk Kim 
3483e71b7053SJung-uk Kim     /* EVP_*Final() doesn't return any data */
3484e71b7053SJung-uk Kim     if (in == NULL && out != NULL)
3485e71b7053SJung-uk Kim         return 0;
3486e71b7053SJung-uk Kim 
3487e71b7053SJung-uk Kim     if (!cctx->iv_set)
3488e71b7053SJung-uk Kim         return -1;
3489e71b7053SJung-uk Kim 
34906f9291ceSJung-uk Kim     if (!out) {
34916f9291ceSJung-uk Kim         if (!in) {
3492b077aed3SPierre Pronchery             if (CRYPTO_ccm128_setiv(ccm, ctx->iv,
3493e71b7053SJung-uk Kim                                     15 - cctx->L, len))
34941f13597dSJung-uk Kim                 return -1;
34951f13597dSJung-uk Kim             cctx->len_set = 1;
34961f13597dSJung-uk Kim             return len;
34971f13597dSJung-uk Kim         }
34981f13597dSJung-uk Kim         /* If have AAD need message length */
34991f13597dSJung-uk Kim         if (!cctx->len_set && len)
35001f13597dSJung-uk Kim             return -1;
35011f13597dSJung-uk Kim         CRYPTO_ccm128_aad(ccm, in, len);
35021f13597dSJung-uk Kim         return len;
35031f13597dSJung-uk Kim     }
3504610a21fdSJung-uk Kim 
3505610a21fdSJung-uk Kim     /* The tag must be set before actually decrypting data */
3506b077aed3SPierre Pronchery     if (!EVP_CIPHER_CTX_is_encrypting(ctx) && !cctx->tag_set)
3507610a21fdSJung-uk Kim         return -1;
3508610a21fdSJung-uk Kim 
35091f13597dSJung-uk Kim     /* If not set length yet do it */
35106f9291ceSJung-uk Kim     if (!cctx->len_set) {
3511b077aed3SPierre Pronchery         if (CRYPTO_ccm128_setiv(ccm, ctx->iv, 15 - cctx->L, len))
35121f13597dSJung-uk Kim             return -1;
35131f13597dSJung-uk Kim         cctx->len_set = 1;
35141f13597dSJung-uk Kim     }
3515b077aed3SPierre Pronchery     if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
35161f13597dSJung-uk Kim         if (cctx->str ? CRYPTO_ccm128_encrypt_ccm64(ccm, in, out, len,
35171f13597dSJung-uk Kim                                                     cctx->str) :
35181f13597dSJung-uk Kim             CRYPTO_ccm128_encrypt(ccm, in, out, len))
35191f13597dSJung-uk Kim             return -1;
35201f13597dSJung-uk Kim         cctx->tag_set = 1;
35211f13597dSJung-uk Kim         return len;
35226f9291ceSJung-uk Kim     } else {
35231f13597dSJung-uk Kim         int rv = -1;
35241f13597dSJung-uk Kim         if (cctx->str ? !CRYPTO_ccm128_decrypt_ccm64(ccm, in, out, len,
35251f13597dSJung-uk Kim                                                      cctx->str) :
35266f9291ceSJung-uk Kim             !CRYPTO_ccm128_decrypt(ccm, in, out, len)) {
35271f13597dSJung-uk Kim             unsigned char tag[16];
35286f9291ceSJung-uk Kim             if (CRYPTO_ccm128_tag(ccm, tag, cctx->M)) {
3529e71b7053SJung-uk Kim                 if (!CRYPTO_memcmp(tag, EVP_CIPHER_CTX_buf_noconst(ctx),
3530e71b7053SJung-uk Kim                                    cctx->M))
35311f13597dSJung-uk Kim                     rv = len;
35321f13597dSJung-uk Kim             }
35331f13597dSJung-uk Kim         }
35341f13597dSJung-uk Kim         if (rv == -1)
35351f13597dSJung-uk Kim             OPENSSL_cleanse(out, len);
35361f13597dSJung-uk Kim         cctx->iv_set = 0;
35371f13597dSJung-uk Kim         cctx->tag_set = 0;
35381f13597dSJung-uk Kim         cctx->len_set = 0;
35391f13597dSJung-uk Kim         return rv;
35401f13597dSJung-uk Kim     }
35411f13597dSJung-uk Kim }
35421f13597dSJung-uk Kim 
35431f13597dSJung-uk Kim #define aes_ccm_cleanup NULL
35441f13597dSJung-uk Kim 
35456f9291ceSJung-uk Kim BLOCK_CIPHER_custom(NID_aes, 128, 1, 12, ccm, CCM,
3546e71b7053SJung-uk Kim                     EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS)
35476f9291ceSJung-uk Kim BLOCK_CIPHER_custom(NID_aes, 192, 1, 12, ccm, CCM,
3548e71b7053SJung-uk Kim                     EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS)
35496f9291ceSJung-uk Kim BLOCK_CIPHER_custom(NID_aes, 256, 1, 12, ccm, CCM,
3550e71b7053SJung-uk Kim                     EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS)
3551e71b7053SJung-uk Kim 
35527bded2dbSJung-uk Kim typedef struct {
35537bded2dbSJung-uk Kim     union {
3554b077aed3SPierre Pronchery         OSSL_UNION_ALIGN;
35557bded2dbSJung-uk Kim         AES_KEY ks;
35567bded2dbSJung-uk Kim     } ks;
35577bded2dbSJung-uk Kim     /* Indicates if IV has been set */
35587bded2dbSJung-uk Kim     unsigned char *iv;
35597bded2dbSJung-uk Kim } EVP_AES_WRAP_CTX;
35607bded2dbSJung-uk Kim 
aes_wrap_init_key(EVP_CIPHER_CTX * ctx,const unsigned char * key,const unsigned char * iv,int enc)35617bded2dbSJung-uk Kim static int aes_wrap_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
35627bded2dbSJung-uk Kim                              const unsigned char *iv, int enc)
35637bded2dbSJung-uk Kim {
3564b077aed3SPierre Pronchery     int len;
3565e71b7053SJung-uk Kim     EVP_AES_WRAP_CTX *wctx = EVP_C_DATA(EVP_AES_WRAP_CTX,ctx);
3566b077aed3SPierre Pronchery 
3567b077aed3SPierre Pronchery     if (iv == NULL && key == NULL)
35687bded2dbSJung-uk Kim         return 1;
3569b077aed3SPierre Pronchery     if (key != NULL) {
3570b077aed3SPierre Pronchery         if (EVP_CIPHER_CTX_is_encrypting(ctx))
3571b077aed3SPierre Pronchery             AES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
3572e71b7053SJung-uk Kim                                 &wctx->ks.ks);
35737bded2dbSJung-uk Kim         else
3574b077aed3SPierre Pronchery             AES_set_decrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
3575e71b7053SJung-uk Kim                                 &wctx->ks.ks);
3576b077aed3SPierre Pronchery         if (iv == NULL)
35777bded2dbSJung-uk Kim             wctx->iv = NULL;
35787bded2dbSJung-uk Kim     }
3579b077aed3SPierre Pronchery     if (iv != NULL) {
3580b077aed3SPierre Pronchery         if ((len = EVP_CIPHER_CTX_get_iv_length(ctx)) < 0)
3581b077aed3SPierre Pronchery             return 0;
3582b077aed3SPierre Pronchery         memcpy(ctx->iv, iv, len);
3583b077aed3SPierre Pronchery         wctx->iv = ctx->iv;
35847bded2dbSJung-uk Kim     }
35857bded2dbSJung-uk Kim     return 1;
35867bded2dbSJung-uk Kim }
35877bded2dbSJung-uk Kim 
aes_wrap_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t inlen)35887bded2dbSJung-uk Kim static int aes_wrap_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
35897bded2dbSJung-uk Kim                            const unsigned char *in, size_t inlen)
35907bded2dbSJung-uk Kim {
3591e71b7053SJung-uk Kim     EVP_AES_WRAP_CTX *wctx = EVP_C_DATA(EVP_AES_WRAP_CTX,ctx);
35927bded2dbSJung-uk Kim     size_t rv;
3593e71b7053SJung-uk Kim     /* AES wrap with padding has IV length of 4, without padding 8 */
3594b077aed3SPierre Pronchery     int pad = EVP_CIPHER_CTX_get_iv_length(ctx) == 4;
3595e71b7053SJung-uk Kim     /* No final operation so always return zero length */
35967bded2dbSJung-uk Kim     if (!in)
35977bded2dbSJung-uk Kim         return 0;
3598e71b7053SJung-uk Kim     /* Input length must always be non-zero */
3599e71b7053SJung-uk Kim     if (!inlen)
36007bded2dbSJung-uk Kim         return -1;
3601e71b7053SJung-uk Kim     /* If decrypting need at least 16 bytes and multiple of 8 */
3602b077aed3SPierre Pronchery     if (!EVP_CIPHER_CTX_is_encrypting(ctx) && (inlen < 16 || inlen & 0x7))
36037bded2dbSJung-uk Kim         return -1;
3604e71b7053SJung-uk Kim     /* If not padding input must be multiple of 8 */
3605e71b7053SJung-uk Kim     if (!pad && inlen & 0x7)
36067bded2dbSJung-uk Kim         return -1;
3607b077aed3SPierre Pronchery     if (ossl_is_partially_overlapping(out, in, inlen)) {
3608b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_EVP, EVP_R_PARTIALLY_OVERLAPPING);
3609e71b7053SJung-uk Kim         return 0;
3610e71b7053SJung-uk Kim     }
36117bded2dbSJung-uk Kim     if (!out) {
3612b077aed3SPierre Pronchery         if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
3613e71b7053SJung-uk Kim             /* If padding round up to multiple of 8 */
3614e71b7053SJung-uk Kim             if (pad)
3615e71b7053SJung-uk Kim                 inlen = (inlen + 7) / 8 * 8;
3616e71b7053SJung-uk Kim             /* 8 byte prefix */
36177bded2dbSJung-uk Kim             return inlen + 8;
3618e71b7053SJung-uk Kim         } else {
3619e71b7053SJung-uk Kim             /*
3620e71b7053SJung-uk Kim              * If not padding output will be exactly 8 bytes smaller than
3621e71b7053SJung-uk Kim              * input. If padding it will be at least 8 bytes smaller but we
3622e71b7053SJung-uk Kim              * don't know how much.
3623e71b7053SJung-uk Kim              */
36247bded2dbSJung-uk Kim             return inlen - 8;
36257bded2dbSJung-uk Kim         }
3626e71b7053SJung-uk Kim     }
3627e71b7053SJung-uk Kim     if (pad) {
3628b077aed3SPierre Pronchery         if (EVP_CIPHER_CTX_is_encrypting(ctx))
3629e71b7053SJung-uk Kim             rv = CRYPTO_128_wrap_pad(&wctx->ks.ks, wctx->iv,
3630e71b7053SJung-uk Kim                                      out, in, inlen,
36317bded2dbSJung-uk Kim                                      (block128_f) AES_encrypt);
36327bded2dbSJung-uk Kim         else
3633e71b7053SJung-uk Kim             rv = CRYPTO_128_unwrap_pad(&wctx->ks.ks, wctx->iv,
3634e71b7053SJung-uk Kim                                        out, in, inlen,
36357bded2dbSJung-uk Kim                                        (block128_f) AES_decrypt);
3636e71b7053SJung-uk Kim     } else {
3637b077aed3SPierre Pronchery         if (EVP_CIPHER_CTX_is_encrypting(ctx))
3638e71b7053SJung-uk Kim             rv = CRYPTO_128_wrap(&wctx->ks.ks, wctx->iv,
3639e71b7053SJung-uk Kim                                  out, in, inlen, (block128_f) AES_encrypt);
3640e71b7053SJung-uk Kim         else
3641e71b7053SJung-uk Kim             rv = CRYPTO_128_unwrap(&wctx->ks.ks, wctx->iv,
3642e71b7053SJung-uk Kim                                    out, in, inlen, (block128_f) AES_decrypt);
3643e71b7053SJung-uk Kim     }
36447bded2dbSJung-uk Kim     return rv ? (int)rv : -1;
36457bded2dbSJung-uk Kim }
36467bded2dbSJung-uk Kim 
36477bded2dbSJung-uk Kim #define WRAP_FLAGS      (EVP_CIPH_WRAP_MODE \
36487bded2dbSJung-uk Kim                 | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \
36497bded2dbSJung-uk Kim                 | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_FLAG_DEFAULT_ASN1)
36507bded2dbSJung-uk Kim 
36517bded2dbSJung-uk Kim static const EVP_CIPHER aes_128_wrap = {
36527bded2dbSJung-uk Kim     NID_id_aes128_wrap,
3653b077aed3SPierre Pronchery     8, 16, 8, WRAP_FLAGS, EVP_ORIG_GLOBAL,
36547bded2dbSJung-uk Kim     aes_wrap_init_key, aes_wrap_cipher,
36557bded2dbSJung-uk Kim     NULL,
36567bded2dbSJung-uk Kim     sizeof(EVP_AES_WRAP_CTX),
36577bded2dbSJung-uk Kim     NULL, NULL, NULL, NULL
36587bded2dbSJung-uk Kim };
36597bded2dbSJung-uk Kim 
EVP_aes_128_wrap(void)36607bded2dbSJung-uk Kim const EVP_CIPHER *EVP_aes_128_wrap(void)
36617bded2dbSJung-uk Kim {
36627bded2dbSJung-uk Kim     return &aes_128_wrap;
36637bded2dbSJung-uk Kim }
36647bded2dbSJung-uk Kim 
36657bded2dbSJung-uk Kim static const EVP_CIPHER aes_192_wrap = {
36667bded2dbSJung-uk Kim     NID_id_aes192_wrap,
3667b077aed3SPierre Pronchery     8, 24, 8, WRAP_FLAGS, EVP_ORIG_GLOBAL,
36687bded2dbSJung-uk Kim     aes_wrap_init_key, aes_wrap_cipher,
36697bded2dbSJung-uk Kim     NULL,
36707bded2dbSJung-uk Kim     sizeof(EVP_AES_WRAP_CTX),
36717bded2dbSJung-uk Kim     NULL, NULL, NULL, NULL
36727bded2dbSJung-uk Kim };
36737bded2dbSJung-uk Kim 
EVP_aes_192_wrap(void)36747bded2dbSJung-uk Kim const EVP_CIPHER *EVP_aes_192_wrap(void)
36757bded2dbSJung-uk Kim {
36767bded2dbSJung-uk Kim     return &aes_192_wrap;
36777bded2dbSJung-uk Kim }
36787bded2dbSJung-uk Kim 
36797bded2dbSJung-uk Kim static const EVP_CIPHER aes_256_wrap = {
36807bded2dbSJung-uk Kim     NID_id_aes256_wrap,
3681b077aed3SPierre Pronchery     8, 32, 8, WRAP_FLAGS, EVP_ORIG_GLOBAL,
36827bded2dbSJung-uk Kim     aes_wrap_init_key, aes_wrap_cipher,
36837bded2dbSJung-uk Kim     NULL,
36847bded2dbSJung-uk Kim     sizeof(EVP_AES_WRAP_CTX),
36857bded2dbSJung-uk Kim     NULL, NULL, NULL, NULL
36867bded2dbSJung-uk Kim };
36877bded2dbSJung-uk Kim 
EVP_aes_256_wrap(void)36887bded2dbSJung-uk Kim const EVP_CIPHER *EVP_aes_256_wrap(void)
36897bded2dbSJung-uk Kim {
36907bded2dbSJung-uk Kim     return &aes_256_wrap;
36917bded2dbSJung-uk Kim }
3692e71b7053SJung-uk Kim 
3693e71b7053SJung-uk Kim static const EVP_CIPHER aes_128_wrap_pad = {
3694e71b7053SJung-uk Kim     NID_id_aes128_wrap_pad,
3695b077aed3SPierre Pronchery     8, 16, 4, WRAP_FLAGS, EVP_ORIG_GLOBAL,
3696e71b7053SJung-uk Kim     aes_wrap_init_key, aes_wrap_cipher,
3697e71b7053SJung-uk Kim     NULL,
3698e71b7053SJung-uk Kim     sizeof(EVP_AES_WRAP_CTX),
3699e71b7053SJung-uk Kim     NULL, NULL, NULL, NULL
3700e71b7053SJung-uk Kim };
3701e71b7053SJung-uk Kim 
EVP_aes_128_wrap_pad(void)3702e71b7053SJung-uk Kim const EVP_CIPHER *EVP_aes_128_wrap_pad(void)
3703e71b7053SJung-uk Kim {
3704e71b7053SJung-uk Kim     return &aes_128_wrap_pad;
3705e71b7053SJung-uk Kim }
3706e71b7053SJung-uk Kim 
3707e71b7053SJung-uk Kim static const EVP_CIPHER aes_192_wrap_pad = {
3708e71b7053SJung-uk Kim     NID_id_aes192_wrap_pad,
3709b077aed3SPierre Pronchery     8, 24, 4, WRAP_FLAGS, EVP_ORIG_GLOBAL,
3710e71b7053SJung-uk Kim     aes_wrap_init_key, aes_wrap_cipher,
3711e71b7053SJung-uk Kim     NULL,
3712e71b7053SJung-uk Kim     sizeof(EVP_AES_WRAP_CTX),
3713e71b7053SJung-uk Kim     NULL, NULL, NULL, NULL
3714e71b7053SJung-uk Kim };
3715e71b7053SJung-uk Kim 
EVP_aes_192_wrap_pad(void)3716e71b7053SJung-uk Kim const EVP_CIPHER *EVP_aes_192_wrap_pad(void)
3717e71b7053SJung-uk Kim {
3718e71b7053SJung-uk Kim     return &aes_192_wrap_pad;
3719e71b7053SJung-uk Kim }
3720e71b7053SJung-uk Kim 
3721e71b7053SJung-uk Kim static const EVP_CIPHER aes_256_wrap_pad = {
3722e71b7053SJung-uk Kim     NID_id_aes256_wrap_pad,
3723b077aed3SPierre Pronchery     8, 32, 4, WRAP_FLAGS, EVP_ORIG_GLOBAL,
3724e71b7053SJung-uk Kim     aes_wrap_init_key, aes_wrap_cipher,
3725e71b7053SJung-uk Kim     NULL,
3726e71b7053SJung-uk Kim     sizeof(EVP_AES_WRAP_CTX),
3727e71b7053SJung-uk Kim     NULL, NULL, NULL, NULL
3728e71b7053SJung-uk Kim };
3729e71b7053SJung-uk Kim 
EVP_aes_256_wrap_pad(void)3730e71b7053SJung-uk Kim const EVP_CIPHER *EVP_aes_256_wrap_pad(void)
3731e71b7053SJung-uk Kim {
3732e71b7053SJung-uk Kim     return &aes_256_wrap_pad;
3733e71b7053SJung-uk Kim }
3734e71b7053SJung-uk Kim 
3735e71b7053SJung-uk Kim #ifndef OPENSSL_NO_OCB
aes_ocb_ctrl(EVP_CIPHER_CTX * c,int type,int arg,void * ptr)3736e71b7053SJung-uk Kim static int aes_ocb_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
3737e71b7053SJung-uk Kim {
3738e71b7053SJung-uk Kim     EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,c);
3739e71b7053SJung-uk Kim     EVP_CIPHER_CTX *newc;
3740e71b7053SJung-uk Kim     EVP_AES_OCB_CTX *new_octx;
3741e71b7053SJung-uk Kim 
3742e71b7053SJung-uk Kim     switch (type) {
3743e71b7053SJung-uk Kim     case EVP_CTRL_INIT:
3744e71b7053SJung-uk Kim         octx->key_set = 0;
3745e71b7053SJung-uk Kim         octx->iv_set = 0;
3746b077aed3SPierre Pronchery         octx->ivlen = EVP_CIPHER_get_iv_length(c->cipher);
3747b077aed3SPierre Pronchery         octx->iv = c->iv;
3748e71b7053SJung-uk Kim         octx->taglen = 16;
3749e71b7053SJung-uk Kim         octx->data_buf_len = 0;
3750e71b7053SJung-uk Kim         octx->aad_buf_len = 0;
3751e71b7053SJung-uk Kim         return 1;
3752e71b7053SJung-uk Kim 
3753da327cd2SJung-uk Kim     case EVP_CTRL_GET_IVLEN:
3754da327cd2SJung-uk Kim         *(int *)ptr = octx->ivlen;
3755da327cd2SJung-uk Kim         return 1;
3756da327cd2SJung-uk Kim 
3757e71b7053SJung-uk Kim     case EVP_CTRL_AEAD_SET_IVLEN:
3758e71b7053SJung-uk Kim         /* IV len must be 1 to 15 */
3759e71b7053SJung-uk Kim         if (arg <= 0 || arg > 15)
3760e71b7053SJung-uk Kim             return 0;
3761e71b7053SJung-uk Kim 
3762e71b7053SJung-uk Kim         octx->ivlen = arg;
3763e71b7053SJung-uk Kim         return 1;
3764e71b7053SJung-uk Kim 
3765e71b7053SJung-uk Kim     case EVP_CTRL_AEAD_SET_TAG:
3766b077aed3SPierre Pronchery         if (ptr == NULL) {
3767e71b7053SJung-uk Kim             /* Tag len must be 0 to 16 */
3768e71b7053SJung-uk Kim             if (arg < 0 || arg > 16)
3769e71b7053SJung-uk Kim                 return 0;
3770e71b7053SJung-uk Kim 
3771e71b7053SJung-uk Kim             octx->taglen = arg;
3772e71b7053SJung-uk Kim             return 1;
3773e71b7053SJung-uk Kim         }
3774b077aed3SPierre Pronchery         if (arg != octx->taglen || EVP_CIPHER_CTX_is_encrypting(c))
3775e71b7053SJung-uk Kim             return 0;
3776e71b7053SJung-uk Kim         memcpy(octx->tag, ptr, arg);
3777e71b7053SJung-uk Kim         return 1;
3778e71b7053SJung-uk Kim 
3779e71b7053SJung-uk Kim     case EVP_CTRL_AEAD_GET_TAG:
3780b077aed3SPierre Pronchery         if (arg != octx->taglen || !EVP_CIPHER_CTX_is_encrypting(c))
3781e71b7053SJung-uk Kim             return 0;
3782e71b7053SJung-uk Kim 
3783e71b7053SJung-uk Kim         memcpy(ptr, octx->tag, arg);
3784e71b7053SJung-uk Kim         return 1;
3785e71b7053SJung-uk Kim 
3786e71b7053SJung-uk Kim     case EVP_CTRL_COPY:
3787e71b7053SJung-uk Kim         newc = (EVP_CIPHER_CTX *)ptr;
3788e71b7053SJung-uk Kim         new_octx = EVP_C_DATA(EVP_AES_OCB_CTX,newc);
3789e71b7053SJung-uk Kim         return CRYPTO_ocb128_copy_ctx(&new_octx->ocb, &octx->ocb,
3790e71b7053SJung-uk Kim                                       &new_octx->ksenc.ks,
3791e71b7053SJung-uk Kim                                       &new_octx->ksdec.ks);
3792e71b7053SJung-uk Kim 
3793e71b7053SJung-uk Kim     default:
3794e71b7053SJung-uk Kim         return -1;
3795e71b7053SJung-uk Kim 
3796e71b7053SJung-uk Kim     }
3797e71b7053SJung-uk Kim }
3798e71b7053SJung-uk Kim 
aes_ocb_init_key(EVP_CIPHER_CTX * ctx,const unsigned char * key,const unsigned char * iv,int enc)3799e71b7053SJung-uk Kim static int aes_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
3800e71b7053SJung-uk Kim                             const unsigned char *iv, int enc)
3801e71b7053SJung-uk Kim {
3802e71b7053SJung-uk Kim     EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,ctx);
3803e71b7053SJung-uk Kim     if (!iv && !key)
3804e71b7053SJung-uk Kim         return 1;
3805e71b7053SJung-uk Kim     if (key) {
3806e71b7053SJung-uk Kim         do {
3807e71b7053SJung-uk Kim             /*
3808e71b7053SJung-uk Kim              * We set both the encrypt and decrypt key here because decrypt
3809e71b7053SJung-uk Kim              * needs both. We could possibly optimise to remove setting the
3810e71b7053SJung-uk Kim              * decrypt for an encryption operation.
3811e71b7053SJung-uk Kim              */
3812e71b7053SJung-uk Kim # ifdef HWAES_CAPABLE
3813e71b7053SJung-uk Kim             if (HWAES_CAPABLE) {
3814b077aed3SPierre Pronchery                 HWAES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
3815e71b7053SJung-uk Kim                                       &octx->ksenc.ks);
3816b077aed3SPierre Pronchery                 HWAES_set_decrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
3817e71b7053SJung-uk Kim                                       &octx->ksdec.ks);
3818e71b7053SJung-uk Kim                 if (!CRYPTO_ocb128_init(&octx->ocb,
3819e71b7053SJung-uk Kim                                         &octx->ksenc.ks, &octx->ksdec.ks,
3820e71b7053SJung-uk Kim                                         (block128_f) HWAES_encrypt,
3821e71b7053SJung-uk Kim                                         (block128_f) HWAES_decrypt,
3822e71b7053SJung-uk Kim                                         enc ? HWAES_ocb_encrypt
3823e71b7053SJung-uk Kim                                             : HWAES_ocb_decrypt))
3824e71b7053SJung-uk Kim                     return 0;
3825e71b7053SJung-uk Kim                 break;
3826e71b7053SJung-uk Kim             }
3827e71b7053SJung-uk Kim # endif
3828e71b7053SJung-uk Kim # ifdef VPAES_CAPABLE
3829e71b7053SJung-uk Kim             if (VPAES_CAPABLE) {
3830b077aed3SPierre Pronchery                 vpaes_set_encrypt_key(key,
3831b077aed3SPierre Pronchery                                       EVP_CIPHER_CTX_get_key_length(ctx) * 8,
3832e71b7053SJung-uk Kim                                       &octx->ksenc.ks);
3833b077aed3SPierre Pronchery                 vpaes_set_decrypt_key(key,
3834b077aed3SPierre Pronchery                                       EVP_CIPHER_CTX_get_key_length(ctx) * 8,
3835e71b7053SJung-uk Kim                                       &octx->ksdec.ks);
3836e71b7053SJung-uk Kim                 if (!CRYPTO_ocb128_init(&octx->ocb,
3837e71b7053SJung-uk Kim                                         &octx->ksenc.ks, &octx->ksdec.ks,
3838e71b7053SJung-uk Kim                                         (block128_f) vpaes_encrypt,
3839e71b7053SJung-uk Kim                                         (block128_f) vpaes_decrypt,
3840e71b7053SJung-uk Kim                                         NULL))
3841e71b7053SJung-uk Kim                     return 0;
3842e71b7053SJung-uk Kim                 break;
3843e71b7053SJung-uk Kim             }
3844e71b7053SJung-uk Kim # endif
3845b077aed3SPierre Pronchery             AES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
3846e71b7053SJung-uk Kim                                 &octx->ksenc.ks);
3847b077aed3SPierre Pronchery             AES_set_decrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8,
3848e71b7053SJung-uk Kim                                 &octx->ksdec.ks);
3849e71b7053SJung-uk Kim             if (!CRYPTO_ocb128_init(&octx->ocb,
3850e71b7053SJung-uk Kim                                     &octx->ksenc.ks, &octx->ksdec.ks,
3851e71b7053SJung-uk Kim                                     (block128_f) AES_encrypt,
3852e71b7053SJung-uk Kim                                     (block128_f) AES_decrypt,
3853e71b7053SJung-uk Kim                                     NULL))
3854e71b7053SJung-uk Kim                 return 0;
3855e71b7053SJung-uk Kim         }
3856e71b7053SJung-uk Kim         while (0);
3857e71b7053SJung-uk Kim 
3858e71b7053SJung-uk Kim         /*
3859e71b7053SJung-uk Kim          * If we have an iv we can set it directly, otherwise use saved IV.
3860e71b7053SJung-uk Kim          */
3861e71b7053SJung-uk Kim         if (iv == NULL && octx->iv_set)
3862e71b7053SJung-uk Kim             iv = octx->iv;
3863e71b7053SJung-uk Kim         if (iv) {
3864e71b7053SJung-uk Kim             if (CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen)
3865e71b7053SJung-uk Kim                 != 1)
3866e71b7053SJung-uk Kim                 return 0;
3867e71b7053SJung-uk Kim             octx->iv_set = 1;
3868e71b7053SJung-uk Kim         }
3869e71b7053SJung-uk Kim         octx->key_set = 1;
3870e71b7053SJung-uk Kim     } else {
3871e71b7053SJung-uk Kim         /* If key set use IV, otherwise copy */
3872e71b7053SJung-uk Kim         if (octx->key_set)
3873e71b7053SJung-uk Kim             CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen);
3874e71b7053SJung-uk Kim         else
3875e71b7053SJung-uk Kim             memcpy(octx->iv, iv, octx->ivlen);
3876e71b7053SJung-uk Kim         octx->iv_set = 1;
3877e71b7053SJung-uk Kim     }
3878e71b7053SJung-uk Kim     return 1;
3879e71b7053SJung-uk Kim }
3880e71b7053SJung-uk Kim 
aes_ocb_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t len)3881e71b7053SJung-uk Kim static int aes_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
3882e71b7053SJung-uk Kim                           const unsigned char *in, size_t len)
3883e71b7053SJung-uk Kim {
3884e71b7053SJung-uk Kim     unsigned char *buf;
3885e71b7053SJung-uk Kim     int *buf_len;
3886e71b7053SJung-uk Kim     int written_len = 0;
3887e71b7053SJung-uk Kim     size_t trailing_len;
3888e71b7053SJung-uk Kim     EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,ctx);
3889e71b7053SJung-uk Kim 
3890e71b7053SJung-uk Kim     /* If IV or Key not set then return error */
3891e71b7053SJung-uk Kim     if (!octx->iv_set)
3892e71b7053SJung-uk Kim         return -1;
3893e71b7053SJung-uk Kim 
3894e71b7053SJung-uk Kim     if (!octx->key_set)
3895e71b7053SJung-uk Kim         return -1;
3896e71b7053SJung-uk Kim 
3897e71b7053SJung-uk Kim     if (in != NULL) {
3898e71b7053SJung-uk Kim         /*
3899e71b7053SJung-uk Kim          * Need to ensure we are only passing full blocks to low level OCB
3900e71b7053SJung-uk Kim          * routines. We do it here rather than in EVP_EncryptUpdate/
3901e71b7053SJung-uk Kim          * EVP_DecryptUpdate because we need to pass full blocks of AAD too
3902e71b7053SJung-uk Kim          * and those routines don't support that
3903e71b7053SJung-uk Kim          */
3904e71b7053SJung-uk Kim 
3905e71b7053SJung-uk Kim         /* Are we dealing with AAD or normal data here? */
3906e71b7053SJung-uk Kim         if (out == NULL) {
3907e71b7053SJung-uk Kim             buf = octx->aad_buf;
3908e71b7053SJung-uk Kim             buf_len = &(octx->aad_buf_len);
3909e71b7053SJung-uk Kim         } else {
3910e71b7053SJung-uk Kim             buf = octx->data_buf;
3911e71b7053SJung-uk Kim             buf_len = &(octx->data_buf_len);
3912e71b7053SJung-uk Kim 
3913b077aed3SPierre Pronchery             if (ossl_is_partially_overlapping(out + *buf_len, in, len)) {
3914b077aed3SPierre Pronchery                 ERR_raise(ERR_LIB_EVP, EVP_R_PARTIALLY_OVERLAPPING);
3915e71b7053SJung-uk Kim                 return 0;
3916e71b7053SJung-uk Kim             }
3917e71b7053SJung-uk Kim         }
3918e71b7053SJung-uk Kim 
3919e71b7053SJung-uk Kim         /*
3920e71b7053SJung-uk Kim          * If we've got a partially filled buffer from a previous call then
3921e71b7053SJung-uk Kim          * use that data first
3922e71b7053SJung-uk Kim          */
3923e71b7053SJung-uk Kim         if (*buf_len > 0) {
3924e71b7053SJung-uk Kim             unsigned int remaining;
3925e71b7053SJung-uk Kim 
3926e71b7053SJung-uk Kim             remaining = AES_BLOCK_SIZE - (*buf_len);
3927e71b7053SJung-uk Kim             if (remaining > len) {
3928e71b7053SJung-uk Kim                 memcpy(buf + (*buf_len), in, len);
3929e71b7053SJung-uk Kim                 *(buf_len) += len;
3930e71b7053SJung-uk Kim                 return 0;
3931e71b7053SJung-uk Kim             }
3932e71b7053SJung-uk Kim             memcpy(buf + (*buf_len), in, remaining);
3933e71b7053SJung-uk Kim 
3934e71b7053SJung-uk Kim             /*
3935e71b7053SJung-uk Kim              * If we get here we've filled the buffer, so process it
3936e71b7053SJung-uk Kim              */
3937e71b7053SJung-uk Kim             len -= remaining;
3938e71b7053SJung-uk Kim             in += remaining;
3939e71b7053SJung-uk Kim             if (out == NULL) {
3940e71b7053SJung-uk Kim                 if (!CRYPTO_ocb128_aad(&octx->ocb, buf, AES_BLOCK_SIZE))
3941e71b7053SJung-uk Kim                     return -1;
3942b077aed3SPierre Pronchery             } else if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
3943e71b7053SJung-uk Kim                 if (!CRYPTO_ocb128_encrypt(&octx->ocb, buf, out,
3944e71b7053SJung-uk Kim                                            AES_BLOCK_SIZE))
3945e71b7053SJung-uk Kim                     return -1;
3946e71b7053SJung-uk Kim             } else {
3947e71b7053SJung-uk Kim                 if (!CRYPTO_ocb128_decrypt(&octx->ocb, buf, out,
3948e71b7053SJung-uk Kim                                            AES_BLOCK_SIZE))
3949e71b7053SJung-uk Kim                     return -1;
3950e71b7053SJung-uk Kim             }
3951e71b7053SJung-uk Kim             written_len = AES_BLOCK_SIZE;
3952e71b7053SJung-uk Kim             *buf_len = 0;
3953e71b7053SJung-uk Kim             if (out != NULL)
3954e71b7053SJung-uk Kim                 out += AES_BLOCK_SIZE;
3955e71b7053SJung-uk Kim         }
3956e71b7053SJung-uk Kim 
3957e71b7053SJung-uk Kim         /* Do we have a partial block to handle at the end? */
3958e71b7053SJung-uk Kim         trailing_len = len % AES_BLOCK_SIZE;
3959e71b7053SJung-uk Kim 
3960e71b7053SJung-uk Kim         /*
3961e71b7053SJung-uk Kim          * If we've got some full blocks to handle, then process these first
3962e71b7053SJung-uk Kim          */
3963e71b7053SJung-uk Kim         if (len != trailing_len) {
3964e71b7053SJung-uk Kim             if (out == NULL) {
3965e71b7053SJung-uk Kim                 if (!CRYPTO_ocb128_aad(&octx->ocb, in, len - trailing_len))
3966e71b7053SJung-uk Kim                     return -1;
3967b077aed3SPierre Pronchery             } else if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
3968e71b7053SJung-uk Kim                 if (!CRYPTO_ocb128_encrypt
3969e71b7053SJung-uk Kim                     (&octx->ocb, in, out, len - trailing_len))
3970e71b7053SJung-uk Kim                     return -1;
3971e71b7053SJung-uk Kim             } else {
3972e71b7053SJung-uk Kim                 if (!CRYPTO_ocb128_decrypt
3973e71b7053SJung-uk Kim                     (&octx->ocb, in, out, len - trailing_len))
3974e71b7053SJung-uk Kim                     return -1;
3975e71b7053SJung-uk Kim             }
3976e71b7053SJung-uk Kim             written_len += len - trailing_len;
3977e71b7053SJung-uk Kim             in += len - trailing_len;
3978e71b7053SJung-uk Kim         }
3979e71b7053SJung-uk Kim 
3980e71b7053SJung-uk Kim         /* Handle any trailing partial block */
3981e71b7053SJung-uk Kim         if (trailing_len > 0) {
3982e71b7053SJung-uk Kim             memcpy(buf, in, trailing_len);
3983e71b7053SJung-uk Kim             *buf_len = trailing_len;
3984e71b7053SJung-uk Kim         }
3985e71b7053SJung-uk Kim 
3986e71b7053SJung-uk Kim         return written_len;
3987e71b7053SJung-uk Kim     } else {
3988e71b7053SJung-uk Kim         /*
3989e71b7053SJung-uk Kim          * First of all empty the buffer of any partial block that we might
3990e71b7053SJung-uk Kim          * have been provided - both for data and AAD
3991e71b7053SJung-uk Kim          */
3992e71b7053SJung-uk Kim         if (octx->data_buf_len > 0) {
3993b077aed3SPierre Pronchery             if (EVP_CIPHER_CTX_is_encrypting(ctx)) {
3994e71b7053SJung-uk Kim                 if (!CRYPTO_ocb128_encrypt(&octx->ocb, octx->data_buf, out,
3995e71b7053SJung-uk Kim                                            octx->data_buf_len))
3996e71b7053SJung-uk Kim                     return -1;
3997e71b7053SJung-uk Kim             } else {
3998e71b7053SJung-uk Kim                 if (!CRYPTO_ocb128_decrypt(&octx->ocb, octx->data_buf, out,
3999e71b7053SJung-uk Kim                                            octx->data_buf_len))
4000e71b7053SJung-uk Kim                     return -1;
4001e71b7053SJung-uk Kim             }
4002e71b7053SJung-uk Kim             written_len = octx->data_buf_len;
4003e71b7053SJung-uk Kim             octx->data_buf_len = 0;
4004e71b7053SJung-uk Kim         }
4005e71b7053SJung-uk Kim         if (octx->aad_buf_len > 0) {
4006e71b7053SJung-uk Kim             if (!CRYPTO_ocb128_aad
4007e71b7053SJung-uk Kim                 (&octx->ocb, octx->aad_buf, octx->aad_buf_len))
4008e71b7053SJung-uk Kim                 return -1;
4009e71b7053SJung-uk Kim             octx->aad_buf_len = 0;
4010e71b7053SJung-uk Kim         }
4011e71b7053SJung-uk Kim         /* If decrypting then verify */
4012b077aed3SPierre Pronchery         if (!EVP_CIPHER_CTX_is_encrypting(ctx)) {
4013e71b7053SJung-uk Kim             if (octx->taglen < 0)
4014e71b7053SJung-uk Kim                 return -1;
4015e71b7053SJung-uk Kim             if (CRYPTO_ocb128_finish(&octx->ocb,
4016e71b7053SJung-uk Kim                                      octx->tag, octx->taglen) != 0)
4017e71b7053SJung-uk Kim                 return -1;
4018e71b7053SJung-uk Kim             octx->iv_set = 0;
4019e71b7053SJung-uk Kim             return written_len;
4020e71b7053SJung-uk Kim         }
4021e71b7053SJung-uk Kim         /* If encrypting then just get the tag */
4022e71b7053SJung-uk Kim         if (CRYPTO_ocb128_tag(&octx->ocb, octx->tag, 16) != 1)
4023e71b7053SJung-uk Kim             return -1;
4024e71b7053SJung-uk Kim         /* Don't reuse the IV */
4025e71b7053SJung-uk Kim         octx->iv_set = 0;
4026e71b7053SJung-uk Kim         return written_len;
4027e71b7053SJung-uk Kim     }
4028e71b7053SJung-uk Kim }
4029e71b7053SJung-uk Kim 
aes_ocb_cleanup(EVP_CIPHER_CTX * c)4030e71b7053SJung-uk Kim static int aes_ocb_cleanup(EVP_CIPHER_CTX *c)
4031e71b7053SJung-uk Kim {
4032e71b7053SJung-uk Kim     EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,c);
4033e71b7053SJung-uk Kim     CRYPTO_ocb128_cleanup(&octx->ocb);
4034e71b7053SJung-uk Kim     return 1;
4035e71b7053SJung-uk Kim }
4036e71b7053SJung-uk Kim 
4037e71b7053SJung-uk Kim BLOCK_CIPHER_custom(NID_aes, 128, 16, 12, ocb, OCB,
4038e71b7053SJung-uk Kim                     EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS)
4039e71b7053SJung-uk Kim BLOCK_CIPHER_custom(NID_aes, 192, 16, 12, ocb, OCB,
4040e71b7053SJung-uk Kim                     EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS)
4041e71b7053SJung-uk Kim BLOCK_CIPHER_custom(NID_aes, 256, 16, 12, ocb, OCB,
4042e71b7053SJung-uk Kim                     EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS)
4043e71b7053SJung-uk Kim #endif                         /* OPENSSL_NO_OCB */
4044