Newer
Older
/*
* Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
#include <openssl/opensslconf.h>
#include <openssl/crypto.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <string.h>
#include <assert.h>
#include <openssl/aes.h>
#include "internal/evp_int.h"
#include "modes_lcl.h"
#include <openssl/rand.h>
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
typedef struct {
union {
double align;
AES_KEY ks;
} ks;
block128_f block;
union {
cbc128_f cbc;
ctr128_f ctr;
} stream;
} EVP_AES_KEY;
typedef struct {
union {
double align;
AES_KEY ks;
} ks; /* AES key schedule to use */
int key_set; /* Set if key initialised */
int iv_set; /* Set if an iv is set */
GCM128_CONTEXT gcm;
unsigned char *iv; /* Temporary IV store */
int ivlen; /* IV length */
int taglen;
int iv_gen; /* It is OK to generate IVs */
int tls_aad_len; /* TLS AAD length */
ctr128_f ctr;
} EVP_AES_GCM_CTX;
typedef struct {
union {
double align;
AES_KEY ks;
} ks1, ks2; /* AES key schedules to use */
XTS128_CONTEXT xts;
void (*stream) (const unsigned char *in,
unsigned char *out, size_t length,
const AES_KEY *key1, const AES_KEY *key2,
const unsigned char iv[16]);
} EVP_AES_XTS_CTX;
typedef struct {
union {
double align;
AES_KEY ks;
} ks; /* AES key schedule to use */
int key_set; /* Set if key initialised */
int iv_set; /* Set if an iv is set */
int tag_set; /* Set if tag is valid */
int len_set; /* Set if message length set */
int L, M; /* L and M parameters from RFC3610 */
CCM128_CONTEXT ccm;
ccm128_f str;
} EVP_AES_CCM_CTX;
union {
double align;
AES_KEY ks;
} ksenc; /* AES key schedule to use for encryption */
union {
double align;
AES_KEY ks;
} ksdec; /* AES key schedule to use for decryption */
int key_set; /* Set if key initialised */
int iv_set; /* Set if an iv is set */
OCB128_CONTEXT ocb;
unsigned char *iv; /* Temporary IV store */
unsigned char tag[16];
unsigned char data_buf[16]; /* Store partial data blocks */
unsigned char aad_buf[16]; /* Store partial AAD blocks */
int data_buf_len;
int aad_buf_len;
int ivlen; /* IV length */
int taglen;
} EVP_AES_OCB_CTX;
#define MAXBITCHUNK ((size_t)1<<(sizeof(size_t)*8-4))
Andy Polyakov
committed
int vpaes_set_encrypt_key(const unsigned char *userKey, int bits,
int vpaes_set_decrypt_key(const unsigned char *userKey, int bits,
void vpaes_encrypt(const unsigned char *in, unsigned char *out,
void vpaes_decrypt(const unsigned char *in, unsigned char *out,
void vpaes_cbc_encrypt(const unsigned char *in,
unsigned char *out,
size_t length,
const AES_KEY *key, unsigned char *ivec, int enc);
void bsaes_cbc_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char ivec[16], int enc);
void bsaes_ctr32_encrypt_blocks(const unsigned char *in, unsigned char *out,
size_t len, const AES_KEY *key,
const unsigned char ivec[16]);
void bsaes_xts_encrypt(const unsigned char *inp, unsigned char *out,
size_t len, const AES_KEY *key1,
const AES_KEY *key2, const unsigned char iv[16]);
void bsaes_xts_decrypt(const unsigned char *inp, unsigned char *out,
size_t len, const AES_KEY *key1,
const AES_KEY *key2, const unsigned char iv[16]);
void AES_ctr32_encrypt(const unsigned char *in, unsigned char *out,
size_t blocks, const AES_KEY *key,
const unsigned char ivec[AES_BLOCK_SIZE]);
void AES_xts_encrypt(const char *inp, char *out, size_t len,
const AES_KEY *key1, const AES_KEY *key2,
const unsigned char iv[16]);
void AES_xts_decrypt(const char *inp, char *out, size_t len,
const AES_KEY *key1, const AES_KEY *key2,
const unsigned char iv[16]);
#if defined(OPENSSL_CPUID_OBJ) && (defined(__powerpc__) || defined(__ppc__) || defined(_ARCH_PPC))
# include "ppc_arch.h"
# ifdef VPAES_ASM
# define VPAES_CAPABLE (OPENSSL_ppccap_P & PPC_ALTIVEC)
# define HWAES_CAPABLE (OPENSSL_ppccap_P & PPC_CRYPTO207)
# define HWAES_set_encrypt_key aes_p8_set_encrypt_key
# define HWAES_set_decrypt_key aes_p8_set_decrypt_key
# define HWAES_encrypt aes_p8_encrypt
# define HWAES_decrypt aes_p8_decrypt
# define HWAES_cbc_encrypt aes_p8_cbc_encrypt
# define HWAES_ctr32_encrypt_blocks aes_p8_ctr32_encrypt_blocks
# define HWAES_xts_encrypt aes_p8_xts_encrypt
# define HWAES_xts_decrypt aes_p8_xts_decrypt
#if defined(AES_ASM) && !defined(I386_ONLY) && ( \
((defined(__i386) || defined(__i386__) || \
defined(_M_IX86)) && defined(OPENSSL_IA32_SSE2))|| \
defined(__x86_64) || defined(__x86_64__) || \
defined(_M_AMD64) || defined(_M_X64) )
# ifdef VPAES_ASM
# define VPAES_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(41-32)))
# endif
# ifdef BSAES_ASM
# define BSAES_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(41-32)))
# endif
Andy Polyakov
committed
/*
* AES-NI section
*/
# define AESNI_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(57-32)))
int aesni_set_encrypt_key(const unsigned char *userKey, int bits,
int aesni_set_decrypt_key(const unsigned char *userKey, int bits,
void aesni_encrypt(const unsigned char *in, unsigned char *out,
void aesni_decrypt(const unsigned char *in, unsigned char *out,
void aesni_ecb_encrypt(const unsigned char *in,
unsigned char *out,
size_t length, const AES_KEY *key, int enc);
void aesni_cbc_encrypt(const unsigned char *in,
unsigned char *out,
size_t length,
const AES_KEY *key, unsigned char *ivec, int enc);
void aesni_ctr32_encrypt_blocks(const unsigned char *in,
unsigned char *out,
size_t blocks,
const void *key, const unsigned char *ivec);
Andy Polyakov
committed
void aesni_xts_encrypt(const unsigned char *in,
unsigned char *out,
size_t length,
const AES_KEY *key1, const AES_KEY *key2,
const unsigned char iv[16]);
Andy Polyakov
committed
void aesni_xts_decrypt(const unsigned char *in,
unsigned char *out,
size_t length,
const AES_KEY *key1, const AES_KEY *key2,
const unsigned char iv[16]);
void aesni_ccm64_encrypt_blocks(const unsigned char *in,
unsigned char *out,
size_t blocks,
const void *key,
const unsigned char ivec[16],
unsigned char cmac[16]);
void aesni_ccm64_decrypt_blocks(const unsigned char *in,
unsigned char *out,
size_t blocks,
const void *key,
const unsigned char ivec[16],
unsigned char cmac[16]);
# if defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)
size_t aesni_gcm_encrypt(const unsigned char *in,
unsigned char *out,
size_t len,
const void *key, unsigned char ivec[16], u64 *Xi);
size_t aesni_gcm_decrypt(const unsigned char *in,
unsigned char *out,
size_t len,
const void *key, unsigned char ivec[16], u64 *Xi);
void gcm_ghash_avx(u64 Xi[2], const u128 Htable[16], const u8 *in,
size_t len);
# define AES_GCM_ASM(gctx) (gctx->ctr==aesni_ctr32_encrypt_blocks && \
# define AES_GCM_ASM2(gctx) (gctx->gcm.block==(block128_f)aesni_encrypt && \
# undef AES_GCM_ASM2 /* minor size optimization */
# endif
Andy Polyakov
committed
static int aesni_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
int ret, mode;
EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
mode = EVP_CIPHER_CTX_mode(ctx);
if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE)
&& !enc) {
ret = aesni_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
&dat->ks.ks);
dat->block = (block128_f) aesni_decrypt;
dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
(cbc128_f) aesni_cbc_encrypt : NULL;
} else {
ret = aesni_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
&dat->ks.ks);
dat->block = (block128_f) aesni_encrypt;
if (mode == EVP_CIPH_CBC_MODE)
dat->stream.cbc = (cbc128_f) aesni_cbc_encrypt;
else if (mode == EVP_CIPH_CTR_MODE)
dat->stream.ctr = (ctr128_f) aesni_ctr32_encrypt_blocks;
else
dat->stream.cbc = NULL;
}
if (ret < 0) {
EVPerr(EVP_F_AESNI_INIT_KEY, EVP_R_AES_KEY_SETUP_FAILED);
return 0;
}
return 1;
}
static int aesni_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
aesni_cbc_encrypt(in, out, len, &EVP_C_DATA(EVP_AES_KEY,ctx)->ks.ks,
EVP_CIPHER_CTX_iv_noconst(ctx),
EVP_CIPHER_CTX_encrypting(ctx));
static int aesni_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
size_t bl = EVP_CIPHER_CTX_block_size(ctx);
aesni_ecb_encrypt(in, out, len, &EVP_C_DATA(EVP_AES_KEY,ctx)->ks.ks,
EVP_CIPHER_CTX_encrypting(ctx));
static int aesni_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
static int aesni_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
static int aesni_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
static int aesni_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
Andy Polyakov
committed
static int aesni_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
Andy Polyakov
committed
static int aesni_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx);
if (!iv && !key)
return 1;
if (key) {
aesni_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
&gctx->ks.ks);
CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, (block128_f) aesni_encrypt);
gctx->ctr = (ctr128_f) aesni_ctr32_encrypt_blocks;
/*
* If we have an iv can set it directly, otherwise use saved IV.
*/
if (iv == NULL && gctx->iv_set)
iv = gctx->iv;
if (iv) {
CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen);
gctx->iv_set = 1;
}
gctx->key_set = 1;
} else {
/* If key set use IV, otherwise copy */
if (gctx->key_set)
CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen);
else
memcpy(gctx->iv, iv, gctx->ivlen);
gctx->iv_set = 1;
gctx->iv_gen = 0;
}
return 1;
}
Andy Polyakov
committed
static int aesni_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
Andy Polyakov
committed
static int aesni_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,ctx);
if (!iv && !key)
return 1;
if (key) {
/* key_len is two AES keys */
if (enc) {
aesni_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 4,
&xctx->ks1.ks);
xctx->xts.block1 = (block128_f) aesni_encrypt;
xctx->stream = aesni_xts_encrypt;
} else {
aesni_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 4,
&xctx->ks1.ks);
xctx->xts.block1 = (block128_f) aesni_decrypt;
xctx->stream = aesni_xts_decrypt;
}
aesni_set_encrypt_key(key + EVP_CIPHER_CTX_key_length(ctx) / 2,
EVP_CIPHER_CTX_key_length(ctx) * 4,
&xctx->ks2.ks);
xctx->xts.block2 = (block128_f) aesni_encrypt;
xctx->xts.key1 = &xctx->ks1;
}
if (iv) {
xctx->xts.key2 = &xctx->ks2;
memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 16);
Andy Polyakov
committed
static int aesni_xts_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
Andy Polyakov
committed
static int aesni_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx);
if (!iv && !key)
return 1;
if (key) {
aesni_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
&cctx->ks.ks);
CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L,
&cctx->ks, (block128_f) aesni_encrypt);
cctx->str = enc ? (ccm128_f) aesni_ccm64_encrypt_blocks :
(ccm128_f) aesni_ccm64_decrypt_blocks;
cctx->key_set = 1;
}
if (iv) {
memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 15 - cctx->L);
cctx->iv_set = 1;
}
return 1;
}
Andy Polyakov
committed
static int aesni_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
Andy Polyakov
committed
void aesni_ocb_encrypt(const unsigned char *in, unsigned char *out,
size_t blocks, const void *key,
size_t start_block_num,
unsigned char offset_i[16],
const unsigned char L_[][16],
unsigned char checksum[16]);
void aesni_ocb_decrypt(const unsigned char *in, unsigned char *out,
size_t blocks, const void *key,
size_t start_block_num,
unsigned char offset_i[16],
const unsigned char L_[][16],
unsigned char checksum[16]);
static int aesni_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,ctx);
if (!iv && !key)
return 1;
if (key) {
do {
/*
* We set both the encrypt and decrypt key here because decrypt
* needs both. We could possibly optimise to remove setting the
* decrypt for an encryption operation.
*/
aesni_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
&octx->ksenc.ks);
aesni_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
&octx->ksdec.ks);
if (!CRYPTO_ocb128_init(&octx->ocb,
&octx->ksenc.ks, &octx->ksdec.ks,
(block128_f) aesni_decrypt,
enc ? aesni_ocb_encrypt
: aesni_ocb_decrypt))
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
return 0;
}
while (0);
/*
* If we have an iv we can set it directly, otherwise use saved IV.
*/
if (iv == NULL && octx->iv_set)
iv = octx->iv;
if (iv) {
if (CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen)
!= 1)
return 0;
octx->iv_set = 1;
}
octx->key_set = 1;
} else {
/* If key set use IV, otherwise copy */
if (octx->key_set)
CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen);
else
memcpy(octx->iv, iv, octx->ivlen);
octx->iv_set = 1;
}
return 1;
}
static int aesni_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \
Andy Polyakov
committed
static const EVP_CIPHER aesni_##keylen##_##mode = { \
nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
aesni_init_key, \
aesni_##mode##_cipher, \
NULL, \
sizeof(EVP_AES_KEY), \
NULL,NULL,NULL,NULL }; \
Andy Polyakov
committed
static const EVP_CIPHER aes_##keylen##_##mode = { \
nid##_##keylen##_##nmode,blocksize, \
keylen/8,ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
aes_init_key, \
aes_##mode##_cipher, \
NULL, \
sizeof(EVP_AES_KEY), \
NULL,NULL,NULL,NULL }; \
Andy Polyakov
committed
const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
{ return AESNI_CAPABLE?&aesni_##keylen##_##mode:&aes_##keylen##_##mode; }
Andy Polyakov
committed
# define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags) \
Andy Polyakov
committed
static const EVP_CIPHER aesni_##keylen##_##mode = { \
nid##_##keylen##_##mode,blocksize, \
(EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
aesni_##mode##_init_key, \
aesni_##mode##_cipher, \
aes_##mode##_cleanup, \
sizeof(EVP_AES_##MODE##_CTX), \
NULL,NULL,aes_##mode##_ctrl,NULL }; \
Andy Polyakov
committed
static const EVP_CIPHER aes_##keylen##_##mode = { \
nid##_##keylen##_##mode,blocksize, \
(EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
aes_##mode##_init_key, \
aes_##mode##_cipher, \
aes_##mode##_cleanup, \
sizeof(EVP_AES_##MODE##_CTX), \
NULL,NULL,aes_##mode##_ctrl,NULL }; \
Andy Polyakov
committed
const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
{ return AESNI_CAPABLE?&aesni_##keylen##_##mode:&aes_##keylen##_##mode; }
#elif defined(AES_ASM) && (defined(__sparc) || defined(__sparc__))
extern unsigned int OPENSSL_sparcv9cap_P[];
/*
* Initial Fujitsu SPARC64 X support
*/
# define HWAES_CAPABLE (OPENSSL_sparcv9cap_P[0] & SPARCV9_FJAESX)
# define HWAES_set_encrypt_key aes_fx_set_encrypt_key
# define HWAES_set_decrypt_key aes_fx_set_decrypt_key
# define HWAES_encrypt aes_fx_encrypt
# define HWAES_decrypt aes_fx_decrypt
# define SPARC_AES_CAPABLE (OPENSSL_sparcv9cap_P[1] & CFR_AES)
void aes_t4_set_encrypt_key(const unsigned char *key, int bits, AES_KEY *ks);
void aes_t4_set_decrypt_key(const unsigned char *key, int bits, AES_KEY *ks);
void aes_t4_encrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key);
void aes_t4_decrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key);
/*
* Key-length specific subroutines were chosen for following reason.
* Each SPARC T4 core can execute up to 8 threads which share core's
* resources. Loading as much key material to registers allows to
* minimize references to shared memory interface, as well as amount
* of instructions in inner loops [much needed on T4]. But then having
* non-key-length specific routines would require conditional branches
* either in inner loops or on subroutines' entries. Former is hardly
* acceptable, while latter means code size increase to size occupied
* by multiple key-length specific subroutines, so why fight?
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
void aes128_t4_cbc_encrypt(const unsigned char *in, unsigned char *out,
size_t len, const AES_KEY *key,
unsigned char *ivec);
void aes128_t4_cbc_decrypt(const unsigned char *in, unsigned char *out,
size_t len, const AES_KEY *key,
unsigned char *ivec);
void aes192_t4_cbc_encrypt(const unsigned char *in, unsigned char *out,
size_t len, const AES_KEY *key,
unsigned char *ivec);
void aes192_t4_cbc_decrypt(const unsigned char *in, unsigned char *out,
size_t len, const AES_KEY *key,
unsigned char *ivec);
void aes256_t4_cbc_encrypt(const unsigned char *in, unsigned char *out,
size_t len, const AES_KEY *key,
unsigned char *ivec);
void aes256_t4_cbc_decrypt(const unsigned char *in, unsigned char *out,
size_t len, const AES_KEY *key,
unsigned char *ivec);
void aes128_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out,
size_t blocks, const AES_KEY *key,
unsigned char *ivec);
void aes192_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out,
size_t blocks, const AES_KEY *key,
unsigned char *ivec);
void aes256_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out,
size_t blocks, const AES_KEY *key,
unsigned char *ivec);
void aes128_t4_xts_encrypt(const unsigned char *in, unsigned char *out,
size_t blocks, const AES_KEY *key1,
const AES_KEY *key2, const unsigned char *ivec);
void aes128_t4_xts_decrypt(const unsigned char *in, unsigned char *out,
size_t blocks, const AES_KEY *key1,
const AES_KEY *key2, const unsigned char *ivec);
void aes256_t4_xts_encrypt(const unsigned char *in, unsigned char *out,
size_t blocks, const AES_KEY *key1,
const AES_KEY *key2, const unsigned char *ivec);
void aes256_t4_xts_decrypt(const unsigned char *in, unsigned char *out,
size_t blocks, const AES_KEY *key1,
const AES_KEY *key2, const unsigned char *ivec);
static int aes_t4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
int ret, mode, bits;
EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
mode = EVP_CIPHER_CTX_mode(ctx);
bits = EVP_CIPHER_CTX_key_length(ctx) * 8;
if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE)
&& !enc) {
ret = 0;
aes_t4_set_decrypt_key(key, bits, &dat->ks.ks);
dat->block = (block128_f) aes_t4_decrypt;
switch (bits) {
case 128:
dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
(cbc128_f) aes128_t4_cbc_decrypt : NULL;
break;
case 192:
dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
(cbc128_f) aes192_t4_cbc_decrypt : NULL;
break;
case 256:
dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
(cbc128_f) aes256_t4_cbc_decrypt : NULL;
break;
default:
ret = -1;
}
} else {
ret = 0;
aes_t4_set_encrypt_key(key, bits, &dat->ks.ks);
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
dat->block = (block128_f) aes_t4_encrypt;
switch (bits) {
case 128:
if (mode == EVP_CIPH_CBC_MODE)
dat->stream.cbc = (cbc128_f) aes128_t4_cbc_encrypt;
else if (mode == EVP_CIPH_CTR_MODE)
dat->stream.ctr = (ctr128_f) aes128_t4_ctr32_encrypt;
else
dat->stream.cbc = NULL;
break;
case 192:
if (mode == EVP_CIPH_CBC_MODE)
dat->stream.cbc = (cbc128_f) aes192_t4_cbc_encrypt;
else if (mode == EVP_CIPH_CTR_MODE)
dat->stream.ctr = (ctr128_f) aes192_t4_ctr32_encrypt;
else
dat->stream.cbc = NULL;
break;
case 256:
if (mode == EVP_CIPH_CBC_MODE)
dat->stream.cbc = (cbc128_f) aes256_t4_cbc_encrypt;
else if (mode == EVP_CIPH_CTR_MODE)
dat->stream.ctr = (ctr128_f) aes256_t4_ctr32_encrypt;
else
dat->stream.cbc = NULL;
break;
default:
ret = -1;
}
}
if (ret < 0) {
EVPerr(EVP_F_AES_T4_INIT_KEY, EVP_R_AES_KEY_SETUP_FAILED);
return 0;
}
return 1;
}
static int aes_t4_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
static int aes_t4_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
static int aes_t4_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
static int aes_t4_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
static int aes_t4_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
static int aes_t4_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
static int aes_t4_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
static int aes_t4_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx);
if (!iv && !key)
return 1;
if (key) {
int bits = EVP_CIPHER_CTX_key_length(ctx) * 8;
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
aes_t4_set_encrypt_key(key, bits, &gctx->ks.ks);
CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks,
(block128_f) aes_t4_encrypt);
switch (bits) {
case 128:
gctx->ctr = (ctr128_f) aes128_t4_ctr32_encrypt;
break;
case 192:
gctx->ctr = (ctr128_f) aes192_t4_ctr32_encrypt;
break;
case 256:
gctx->ctr = (ctr128_f) aes256_t4_ctr32_encrypt;
break;
default:
return 0;
}
/*
* If we have an iv can set it directly, otherwise use saved IV.
*/
if (iv == NULL && gctx->iv_set)
iv = gctx->iv;
if (iv) {
CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen);
gctx->iv_set = 1;
}
gctx->key_set = 1;
} else {
/* If key set use IV, otherwise copy */
if (gctx->key_set)
CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen);
else
memcpy(gctx->iv, iv, gctx->ivlen);
gctx->iv_set = 1;
gctx->iv_gen = 0;
}
return 1;
}
static int aes_t4_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
static int aes_t4_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,ctx);
if (!iv && !key)
return 1;
if (key) {
int bits = EVP_CIPHER_CTX_key_length(ctx) * 4;
xctx->stream = NULL;
/* key_len is two AES keys */
if (enc) {
aes_t4_set_encrypt_key(key, bits, &xctx->ks1.ks);
xctx->xts.block1 = (block128_f) aes_t4_encrypt;
switch (bits) {
case 128:
xctx->stream = aes128_t4_xts_encrypt;
break;
case 256:
xctx->stream = aes256_t4_xts_encrypt;
break;
default:
return 0;
}
} else {
aes_t4_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 4,
&xctx->ks1.ks);
xctx->xts.block1 = (block128_f) aes_t4_decrypt;
switch (bits) {
case 128:
xctx->stream = aes128_t4_xts_decrypt;
break;
case 256:
xctx->stream = aes256_t4_xts_decrypt;
break;
default:
return 0;
}
}
aes_t4_set_encrypt_key(key + EVP_CIPHER_CTX_key_length(ctx) / 2,
EVP_CIPHER_CTX_key_length(ctx) * 4,
&xctx->ks2.ks);
xctx->xts.block2 = (block128_f) aes_t4_encrypt;
xctx->xts.key1 = &xctx->ks1;
}
if (iv) {
xctx->xts.key2 = &xctx->ks2;
memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 16);
static int aes_t4_xts_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
static int aes_t4_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx);
if (!iv && !key)
return 1;
if (key) {
int bits = EVP_CIPHER_CTX_key_length(ctx) * 8;
aes_t4_set_encrypt_key(key, bits, &cctx->ks.ks);
CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L,
&cctx->ks, (block128_f) aes_t4_encrypt);
cctx->key_set = 1;
}
if (iv) {
memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 15 - cctx->L);
cctx->iv_set = 1;
}
return 1;
}
static int aes_t4_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
static int aes_t4_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,ctx);
if (!iv && !key)
return 1;
if (key) {
do {
/*
* We set both the encrypt and decrypt key here because decrypt
* needs both. We could possibly optimise to remove setting the
* decrypt for an encryption operation.
*/
aes_t4_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
&octx->ksenc.ks);
aes_t4_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
&octx->ksdec.ks);
if (!CRYPTO_ocb128_init(&octx->ocb,
&octx->ksenc.ks, &octx->ksdec.ks,
(block128_f) aes_t4_decrypt,
NULL))
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
return 0;
}
while (0);
/*
* If we have an iv we can set it directly, otherwise use saved IV.
*/
if (iv == NULL && octx->iv_set)
iv = octx->iv;
if (iv) {
if (CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen)
!= 1)
return 0;
octx->iv_set = 1;
}
octx->key_set = 1;
} else {
/* If key set use IV, otherwise copy */
if (octx->key_set)
CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen);
else
memcpy(octx->iv, iv, octx->ivlen);
octx->iv_set = 1;
}
return 1;
}
static int aes_t4_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \
static const EVP_CIPHER aes_t4_##keylen##_##mode = { \
nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
aes_t4_init_key, \
aes_t4_##mode##_cipher, \
NULL, \
sizeof(EVP_AES_KEY), \
NULL,NULL,NULL,NULL }; \
static const EVP_CIPHER aes_##keylen##_##mode = { \
nid##_##keylen##_##nmode,blocksize, \
keylen/8,ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
aes_init_key, \
aes_##mode##_cipher, \
NULL, \
sizeof(EVP_AES_KEY), \
NULL,NULL,NULL,NULL }; \
const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
{ return SPARC_AES_CAPABLE?&aes_t4_##keylen##_##mode:&aes_##keylen##_##mode; }
# define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags) \
static const EVP_CIPHER aes_t4_##keylen##_##mode = { \
nid##_##keylen##_##mode,blocksize, \
(EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
aes_t4_##mode##_init_key, \
aes_t4_##mode##_cipher, \
aes_##mode##_cleanup, \
sizeof(EVP_AES_##MODE##_CTX), \
NULL,NULL,aes_##mode##_ctrl,NULL }; \
static const EVP_CIPHER aes_##keylen##_##mode = { \
nid##_##keylen##_##mode,blocksize, \
(EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
aes_##mode##_init_key, \
aes_##mode##_cipher, \
aes_##mode##_cleanup, \
sizeof(EVP_AES_##MODE##_CTX), \
NULL,NULL,aes_##mode##_ctrl,NULL }; \
const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
{ return SPARC_AES_CAPABLE?&aes_t4_##keylen##_##mode:&aes_##keylen##_##mode; }
Andy Polyakov
committed
# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \
Andy Polyakov
committed
static const EVP_CIPHER aes_##keylen##_##mode = { \
nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
aes_init_key, \
aes_##mode##_cipher, \
NULL, \
sizeof(EVP_AES_KEY), \
NULL,NULL,NULL,NULL }; \
Andy Polyakov
committed
const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
{ return &aes_##keylen##_##mode; }
# define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags) \
Andy Polyakov
committed
static const EVP_CIPHER aes_##keylen##_##mode = { \
nid##_##keylen##_##mode,blocksize, \
(EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
aes_##mode##_init_key, \
aes_##mode##_cipher, \
aes_##mode##_cleanup, \
sizeof(EVP_AES_##MODE##_CTX), \
NULL,NULL,aes_##mode##_ctrl,NULL }; \
Andy Polyakov
committed
const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
{ return &aes_##keylen##_##mode; }
#if defined(OPENSSL_CPUID_OBJ) && (defined(__arm__) || defined(__arm) || defined(__aarch64__))
# include "arm_arch.h"
# if __ARM_MAX_ARCH__>=7
# if defined(BSAES_ASM)
# define BSAES_CAPABLE (OPENSSL_armcap_P & ARMV7_NEON)
# endif
# if defined(VPAES_ASM)
# define VPAES_CAPABLE (OPENSSL_armcap_P & ARMV7_NEON)
# define HWAES_CAPABLE (OPENSSL_armcap_P & ARMV8_AES)
# define HWAES_set_encrypt_key aes_v8_set_encrypt_key
# define HWAES_set_decrypt_key aes_v8_set_decrypt_key
# define HWAES_encrypt aes_v8_encrypt
# define HWAES_decrypt aes_v8_decrypt
# define HWAES_cbc_encrypt aes_v8_cbc_encrypt
# define HWAES_ctr32_encrypt_blocks aes_v8_ctr32_encrypt_blocks
int HWAES_set_encrypt_key(const unsigned char *userKey, const int bits,