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