2014-06-20 20:00:00 +01:00
|
|
|
/* ====================================================================
|
|
|
|
* Copyright (c) 2001-2011 The OpenSSL Project. All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
*
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
*
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in
|
|
|
|
* the documentation and/or other materials provided with the
|
|
|
|
* distribution.
|
|
|
|
*
|
|
|
|
* 3. All advertising materials mentioning features or use of this
|
|
|
|
* software must display the following acknowledgment:
|
|
|
|
* "This product includes software developed by the OpenSSL Project
|
|
|
|
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
|
|
|
*
|
|
|
|
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
|
|
|
* endorse or promote products derived from this software without
|
|
|
|
* prior written permission. For written permission, please contact
|
|
|
|
* openssl-core@openssl.org.
|
|
|
|
*
|
|
|
|
* 5. Products derived from this software may not be called "OpenSSL"
|
|
|
|
* nor may "OpenSSL" appear in their names without prior written
|
|
|
|
* permission of the OpenSSL Project.
|
|
|
|
*
|
|
|
|
* 6. Redistributions of any form whatsoever must retain the following
|
|
|
|
* acknowledgment:
|
|
|
|
* "This product includes software developed by the OpenSSL Project
|
|
|
|
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
|
|
|
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
|
|
|
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
|
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
|
|
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
* ==================================================================== */
|
|
|
|
|
2015-01-31 01:08:37 +00:00
|
|
|
#include <string.h>
|
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
#include <openssl/aead.h>
|
2014-06-20 20:00:00 +01:00
|
|
|
#include <openssl/aes.h>
|
|
|
|
#include <openssl/cipher.h>
|
|
|
|
#include <openssl/cpu.h>
|
|
|
|
#include <openssl/err.h>
|
|
|
|
#include <openssl/mem.h>
|
2016-03-25 22:07:11 +00:00
|
|
|
#include <openssl/nid.h>
|
2014-06-20 20:00:00 +01:00
|
|
|
#include <openssl/rand.h>
|
2014-06-20 20:00:00 +01:00
|
|
|
|
|
|
|
#include "internal.h"
|
2015-03-13 19:11:00 +00:00
|
|
|
#include "../internal.h"
|
2017-04-13 19:38:40 +01:00
|
|
|
#include "../fipsmodule/modes/internal.h"
|
2014-06-20 20:00:00 +01:00
|
|
|
|
2015-01-16 22:06:22 +00:00
|
|
|
#if defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)
|
2015-08-25 02:03:17 +01:00
|
|
|
#include <openssl/arm_arch.h>
|
2015-01-16 22:06:22 +00:00
|
|
|
#endif
|
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
|
2016-06-09 21:48:33 +01:00
|
|
|
OPENSSL_MSVC_PRAGMA(warning(disable: 4702)) /* Unreachable code. */
|
Fix build when using Visual Studio 2015 Update 1.
Many of the compatibility issues are described at
https://msdn.microsoft.com/en-us/library/mt612856.aspx. The macros
that suppressed warnings on a per-function basis no longer work in
Update 1, so replace them with #pragmas. Update 1 warns when |size_t|
arguments to |printf| are casted, so stop doing that casting.
Unfortunately, this requires an ugly hack to continue working in
MSVC 2013 as MSVC 2013 doesn't support "%zu". Finally, Update 1 has new
warnings, some of which need to be suppressed.
---
Updated by davidben to give up on suppressing warnings in crypto/x509 and
crypto/x509v3 as those directories aren't changed much from upstream. In each
of these cases, upstream opted just blindly initialize the variable, so do the
same. Also switch C4265 to level 4, per Microsoft's recommendation and work
around a bug in limits.h that happens to get fixed by Google include order
style.
(limits.h is sensitive to whether corecrt.h, pulled in by stddef.h and some
other headers, is included before it. The reason it affected just one file is
we often put the file's header first, which means base.h is pulling in
stddef.h. Relying on this is ugly, but it's no worse than what everything else
is doing and this doesn't seem worth making something as tame as limits.h so
messy to use.)
Change-Id: I02d1f935356899f424d3525d03eca401bfa3e6cd
Reviewed-on: https://boringssl-review.googlesource.com/7480
Reviewed-by: David Benjamin <davidben@google.com>
2016-01-18 08:21:42 +00:00
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
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;
|
|
|
|
uint8_t *iv; /* Temporary IV store */
|
|
|
|
int ivlen; /* IV length */
|
|
|
|
int taglen;
|
|
|
|
int iv_gen; /* It is OK to generate IVs */
|
|
|
|
ctr128_f ctr;
|
|
|
|
} EVP_AES_GCM_CTX;
|
|
|
|
|
|
|
|
#if !defined(OPENSSL_NO_ASM) && \
|
|
|
|
(defined(OPENSSL_X86_64) || defined(OPENSSL_X86))
|
|
|
|
#define VPAES
|
2014-08-20 21:24:00 +01:00
|
|
|
static char vpaes_capable(void) {
|
2014-06-20 20:00:00 +01:00
|
|
|
return (OPENSSL_ia32cap_P[1] & (1 << (41 - 32))) != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(OPENSSL_X86_64)
|
|
|
|
#define BSAES
|
2014-08-20 21:24:00 +01:00
|
|
|
static char bsaes_capable(void) {
|
2014-06-20 20:00:00 +01:00
|
|
|
return vpaes_capable();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-01-09 23:44:37 +00:00
|
|
|
#elif !defined(OPENSSL_NO_ASM) && \
|
|
|
|
(defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64))
|
|
|
|
|
2015-05-29 14:02:09 +01:00
|
|
|
#if defined(OPENSSL_ARM) && __ARM_MAX_ARCH__ >= 7
|
2014-06-20 20:00:00 +01:00
|
|
|
#define BSAES
|
2014-08-20 21:24:00 +01:00
|
|
|
static char bsaes_capable(void) {
|
2014-06-20 20:00:00 +01:00
|
|
|
return CRYPTO_is_NEON_capable();
|
|
|
|
}
|
2015-01-09 23:44:37 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#define HWAES
|
2015-09-25 03:14:04 +01:00
|
|
|
static int hwaes_capable(void) {
|
2015-10-16 23:46:46 +01:00
|
|
|
return CRYPTO_is_ARMv8_AES_capable();
|
2015-01-09 23:44:37 +00:00
|
|
|
}
|
|
|
|
|
2016-09-23 20:47:24 +01:00
|
|
|
#elif !defined(OPENSSL_NO_ASM) && defined(OPENSSL_PPC64LE)
|
|
|
|
|
|
|
|
#define HWAES
|
|
|
|
static int hwaes_capable(void) {
|
|
|
|
return CRYPTO_is_PPC64LE_vcrypto_capable();
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* OPENSSL_PPC64LE */
|
2015-01-09 23:44:37 +00:00
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
|
|
|
|
#if defined(BSAES)
|
|
|
|
/* On platforms where BSAES gets defined (just above), then these functions are
|
|
|
|
* provided by asm. */
|
|
|
|
void bsaes_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
|
|
|
|
const AES_KEY *key, uint8_t ivec[16], int enc);
|
|
|
|
void bsaes_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t len,
|
|
|
|
const AES_KEY *key, const uint8_t ivec[16]);
|
|
|
|
#else
|
2014-08-20 21:24:00 +01:00
|
|
|
static char bsaes_capable(void) {
|
2014-06-20 20:00:00 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* On other platforms, bsaes_capable() will always return false and so the
|
|
|
|
* following will never be called. */
|
2015-09-25 03:14:04 +01:00
|
|
|
static void bsaes_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
|
|
|
|
const AES_KEY *key, uint8_t ivec[16], int enc) {
|
2014-06-20 20:00:00 +01:00
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
2015-09-25 03:14:04 +01:00
|
|
|
static void bsaes_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out,
|
|
|
|
size_t len, const AES_KEY *key,
|
|
|
|
const uint8_t ivec[16]) {
|
2014-06-20 20:00:00 +01:00
|
|
|
abort();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(VPAES)
|
2014-06-20 20:00:00 +01:00
|
|
|
/* On platforms where VPAES gets defined (just above), then these functions are
|
2014-06-20 20:00:00 +01:00
|
|
|
* provided by asm. */
|
|
|
|
int vpaes_set_encrypt_key(const uint8_t *userKey, int bits, AES_KEY *key);
|
|
|
|
int vpaes_set_decrypt_key(const uint8_t *userKey, int bits, AES_KEY *key);
|
|
|
|
|
|
|
|
void vpaes_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
|
|
|
|
void vpaes_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
|
|
|
|
|
|
|
|
void vpaes_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
|
|
|
|
const AES_KEY *key, uint8_t *ivec, int enc);
|
|
|
|
#else
|
2014-08-20 21:24:00 +01:00
|
|
|
static char vpaes_capable(void) {
|
2014-06-20 20:00:00 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* On other platforms, vpaes_capable() will always return false and so the
|
|
|
|
* following will never be called. */
|
2015-09-25 03:14:04 +01:00
|
|
|
static int vpaes_set_encrypt_key(const uint8_t *userKey, int bits,
|
|
|
|
AES_KEY *key) {
|
2014-06-20 20:00:00 +01:00
|
|
|
abort();
|
|
|
|
}
|
2015-09-25 03:14:04 +01:00
|
|
|
static int vpaes_set_decrypt_key(const uint8_t *userKey, int bits,
|
|
|
|
AES_KEY *key) {
|
2014-06-20 20:00:00 +01:00
|
|
|
abort();
|
|
|
|
}
|
2015-09-25 03:14:04 +01:00
|
|
|
static void vpaes_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
|
2014-06-20 20:00:00 +01:00
|
|
|
abort();
|
|
|
|
}
|
2015-09-25 03:14:04 +01:00
|
|
|
static void vpaes_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
|
2014-06-20 20:00:00 +01:00
|
|
|
abort();
|
|
|
|
}
|
2015-09-25 03:14:04 +01:00
|
|
|
static void vpaes_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
|
|
|
|
const AES_KEY *key, uint8_t *ivec, int enc) {
|
2014-06-20 20:00:00 +01:00
|
|
|
abort();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-09-23 20:47:24 +01:00
|
|
|
#if defined(HWAES)
|
|
|
|
int aes_hw_set_encrypt_key(const uint8_t *user_key, const int bits,
|
|
|
|
AES_KEY *key);
|
|
|
|
int aes_hw_set_decrypt_key(const uint8_t *user_key, const int bits,
|
|
|
|
AES_KEY *key);
|
|
|
|
void aes_hw_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
|
|
|
|
void aes_hw_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
|
|
|
|
void aes_hw_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
|
|
|
|
const AES_KEY *key, uint8_t *ivec, const int enc);
|
|
|
|
void aes_hw_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t len,
|
|
|
|
const AES_KEY *key, const uint8_t ivec[16]);
|
|
|
|
#else
|
2015-01-09 23:44:37 +00:00
|
|
|
/* If HWAES isn't defined then we provide dummy functions for each of the hwaes
|
|
|
|
* functions. */
|
2015-09-25 03:14:04 +01:00
|
|
|
static int hwaes_capable(void) {
|
2015-01-09 23:44:37 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-09-23 20:47:24 +01:00
|
|
|
static int aes_hw_set_encrypt_key(const uint8_t *user_key, int bits,
|
2015-09-25 03:14:04 +01:00
|
|
|
AES_KEY *key) {
|
2015-01-09 23:44:37 +00:00
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
2016-09-23 20:47:24 +01:00
|
|
|
static int aes_hw_set_decrypt_key(const uint8_t *user_key, int bits,
|
2015-09-25 03:14:04 +01:00
|
|
|
AES_KEY *key) {
|
2015-01-09 23:44:37 +00:00
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
2016-09-23 20:47:24 +01:00
|
|
|
static void aes_hw_encrypt(const uint8_t *in, uint8_t *out,
|
2015-09-25 03:14:04 +01:00
|
|
|
const AES_KEY *key) {
|
2015-01-09 23:44:37 +00:00
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
2016-09-23 20:47:24 +01:00
|
|
|
static void aes_hw_decrypt(const uint8_t *in, uint8_t *out,
|
2015-09-25 03:14:04 +01:00
|
|
|
const AES_KEY *key) {
|
2015-01-09 23:44:37 +00:00
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
2016-09-23 20:47:24 +01:00
|
|
|
static void aes_hw_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
|
2015-09-25 03:14:04 +01:00
|
|
|
const AES_KEY *key, uint8_t *ivec, int enc) {
|
2015-01-09 23:44:37 +00:00
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
2016-09-23 20:47:24 +01:00
|
|
|
static void aes_hw_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out,
|
2015-09-25 03:14:04 +01:00
|
|
|
size_t len, const AES_KEY *key,
|
|
|
|
const uint8_t ivec[16]) {
|
2015-01-09 23:44:37 +00:00
|
|
|
abort();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
#if !defined(OPENSSL_NO_ASM) && \
|
|
|
|
(defined(OPENSSL_X86_64) || defined(OPENSSL_X86))
|
|
|
|
int aesni_set_encrypt_key(const uint8_t *userKey, int bits, AES_KEY *key);
|
|
|
|
int aesni_set_decrypt_key(const uint8_t *userKey, int bits, AES_KEY *key);
|
|
|
|
|
|
|
|
void aesni_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
|
|
|
|
void aesni_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
|
|
|
|
|
|
|
|
void aesni_ecb_encrypt(const uint8_t *in, uint8_t *out, size_t length,
|
|
|
|
const AES_KEY *key, int enc);
|
|
|
|
void aesni_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
|
|
|
|
const AES_KEY *key, uint8_t *ivec, int enc);
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
/* On other platforms, aesni_capable() will always return false and so the
|
|
|
|
* following will never be called. */
|
2015-09-25 03:14:04 +01:00
|
|
|
static void aesni_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
|
2014-06-20 20:00:00 +01:00
|
|
|
abort();
|
|
|
|
}
|
2015-09-25 03:14:04 +01:00
|
|
|
static int aesni_set_encrypt_key(const uint8_t *userKey, int bits,
|
|
|
|
AES_KEY *key) {
|
2014-06-20 20:00:00 +01:00
|
|
|
abort();
|
|
|
|
}
|
2015-09-25 03:14:04 +01:00
|
|
|
static void aesni_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out,
|
|
|
|
size_t blocks, const void *key,
|
|
|
|
const uint8_t *ivec) {
|
2014-06-20 20:00:00 +01:00
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static int aes_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
|
Fix build when using Visual Studio 2015 Update 1.
Many of the compatibility issues are described at
https://msdn.microsoft.com/en-us/library/mt612856.aspx. The macros
that suppressed warnings on a per-function basis no longer work in
Update 1, so replace them with #pragmas. Update 1 warns when |size_t|
arguments to |printf| are casted, so stop doing that casting.
Unfortunately, this requires an ugly hack to continue working in
MSVC 2013 as MSVC 2013 doesn't support "%zu". Finally, Update 1 has new
warnings, some of which need to be suppressed.
---
Updated by davidben to give up on suppressing warnings in crypto/x509 and
crypto/x509v3 as those directories aren't changed much from upstream. In each
of these cases, upstream opted just blindly initialize the variable, so do the
same. Also switch C4265 to level 4, per Microsoft's recommendation and work
around a bug in limits.h that happens to get fixed by Google include order
style.
(limits.h is sensitive to whether corecrt.h, pulled in by stddef.h and some
other headers, is included before it. The reason it affected just one file is
we often put the file's header first, which means base.h is pulling in
stddef.h. Relying on this is ugly, but it's no worse than what everything else
is doing and this doesn't seem worth making something as tame as limits.h so
messy to use.)
Change-Id: I02d1f935356899f424d3525d03eca401bfa3e6cd
Reviewed-on: https://boringssl-review.googlesource.com/7480
Reviewed-by: David Benjamin <davidben@google.com>
2016-01-18 08:21:42 +00:00
|
|
|
const uint8_t *iv, int enc) {
|
2014-06-20 20:00:00 +01:00
|
|
|
int ret, mode;
|
|
|
|
EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
|
|
|
|
|
|
|
|
mode = ctx->cipher->flags & EVP_CIPH_MODE_MASK;
|
|
|
|
if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) && !enc) {
|
2015-01-09 23:44:37 +00:00
|
|
|
if (hwaes_capable()) {
|
2016-09-23 20:47:24 +01:00
|
|
|
ret = aes_hw_set_decrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
|
|
|
|
dat->block = (block128_f)aes_hw_decrypt;
|
2015-01-09 23:44:37 +00:00
|
|
|
dat->stream.cbc = NULL;
|
|
|
|
if (mode == EVP_CIPH_CBC_MODE) {
|
2016-09-23 20:47:24 +01:00
|
|
|
dat->stream.cbc = (cbc128_f)aes_hw_cbc_encrypt;
|
2015-01-09 23:44:37 +00:00
|
|
|
}
|
|
|
|
} else if (bsaes_capable() && mode == EVP_CIPH_CBC_MODE) {
|
2014-06-20 20:00:00 +01:00
|
|
|
ret = AES_set_decrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
|
|
|
|
dat->block = (block128_f)AES_decrypt;
|
|
|
|
dat->stream.cbc = (cbc128_f)bsaes_cbc_encrypt;
|
|
|
|
} else if (vpaes_capable()) {
|
|
|
|
ret = vpaes_set_decrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
|
|
|
|
dat->block = (block128_f)vpaes_decrypt;
|
|
|
|
dat->stream.cbc =
|
|
|
|
mode == EVP_CIPH_CBC_MODE ? (cbc128_f)vpaes_cbc_encrypt : NULL;
|
|
|
|
} else {
|
|
|
|
ret = AES_set_decrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
|
|
|
|
dat->block = (block128_f)AES_decrypt;
|
|
|
|
dat->stream.cbc =
|
|
|
|
mode == EVP_CIPH_CBC_MODE ? (cbc128_f)AES_cbc_encrypt : NULL;
|
|
|
|
}
|
2015-01-09 23:44:37 +00:00
|
|
|
} else if (hwaes_capable()) {
|
2016-09-23 20:47:24 +01:00
|
|
|
ret = aes_hw_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
|
|
|
|
dat->block = (block128_f)aes_hw_encrypt;
|
2015-01-09 23:44:37 +00:00
|
|
|
dat->stream.cbc = NULL;
|
|
|
|
if (mode == EVP_CIPH_CBC_MODE) {
|
2016-09-23 20:47:24 +01:00
|
|
|
dat->stream.cbc = (cbc128_f)aes_hw_cbc_encrypt;
|
2015-01-09 23:44:37 +00:00
|
|
|
} else if (mode == EVP_CIPH_CTR_MODE) {
|
2016-09-23 20:47:24 +01:00
|
|
|
dat->stream.ctr = (ctr128_f)aes_hw_ctr32_encrypt_blocks;
|
2015-01-09 23:44:37 +00:00
|
|
|
}
|
2014-06-20 20:00:00 +01:00
|
|
|
} else if (bsaes_capable() && mode == EVP_CIPH_CTR_MODE) {
|
|
|
|
ret = AES_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
|
|
|
|
dat->block = (block128_f)AES_encrypt;
|
|
|
|
dat->stream.ctr = (ctr128_f)bsaes_ctr32_encrypt_blocks;
|
|
|
|
} else if (vpaes_capable()) {
|
|
|
|
ret = vpaes_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
|
|
|
|
dat->block = (block128_f)vpaes_encrypt;
|
|
|
|
dat->stream.cbc =
|
|
|
|
mode == EVP_CIPH_CBC_MODE ? (cbc128_f)vpaes_cbc_encrypt : NULL;
|
|
|
|
} else {
|
|
|
|
ret = AES_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
|
|
|
|
dat->block = (block128_f)AES_encrypt;
|
|
|
|
dat->stream.cbc =
|
|
|
|
mode == EVP_CIPH_CBC_MODE ? (cbc128_f)AES_cbc_encrypt : NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ret < 0) {
|
2015-06-29 05:28:17 +01:00
|
|
|
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_AES_KEY_SETUP_FAILED);
|
2014-06-20 20:00:00 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2015-02-24 20:44:40 +00:00
|
|
|
static int aes_cbc_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
|
|
|
|
size_t len) {
|
2014-06-20 20:00:00 +01:00
|
|
|
EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
|
|
|
|
|
|
|
|
if (dat->stream.cbc) {
|
|
|
|
(*dat->stream.cbc)(in, out, len, &dat->ks, ctx->iv, ctx->encrypt);
|
|
|
|
} else if (ctx->encrypt) {
|
|
|
|
CRYPTO_cbc128_encrypt(in, out, len, &dat->ks, ctx->iv, dat->block);
|
|
|
|
} else {
|
|
|
|
CRYPTO_cbc128_decrypt(in, out, len, &dat->ks, ctx->iv, dat->block);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2015-02-24 20:44:40 +00:00
|
|
|
static int aes_ecb_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
|
|
|
|
size_t len) {
|
2014-06-20 20:00:00 +01:00
|
|
|
size_t bl = ctx->cipher->block_size;
|
|
|
|
EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
|
|
|
|
|
|
|
|
if (len < bl) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2016-09-05 17:47:25 +01:00
|
|
|
len -= bl;
|
|
|
|
for (size_t i = 0; i <= len; i += bl) {
|
2014-06-20 20:00:00 +01:00
|
|
|
(*dat->block)(in + i, out + i, &dat->ks);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2015-02-24 20:44:40 +00:00
|
|
|
static int aes_ctr_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
|
|
|
|
size_t len) {
|
2014-06-20 20:00:00 +01:00
|
|
|
EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
|
|
|
|
|
|
|
|
if (dat->stream.ctr) {
|
2016-04-16 20:20:07 +01:00
|
|
|
CRYPTO_ctr128_encrypt_ctr32(in, out, len, &dat->ks, ctx->iv, ctx->buf,
|
|
|
|
&ctx->num, dat->stream.ctr);
|
2014-06-20 20:00:00 +01:00
|
|
|
} else {
|
2016-04-16 20:20:07 +01:00
|
|
|
CRYPTO_ctr128_encrypt(in, out, len, &dat->ks, ctx->iv, ctx->buf, &ctx->num,
|
2014-06-20 20:00:00 +01:00
|
|
|
dat->block);
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2015-02-24 20:44:40 +00:00
|
|
|
static int aes_ofb_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
|
|
|
|
size_t len) {
|
|
|
|
EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
|
|
|
|
|
|
|
|
CRYPTO_ofb128_encrypt(in, out, len, &dat->ks, ctx->iv, &ctx->num, dat->block);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2015-03-13 18:49:22 +00:00
|
|
|
static char aesni_capable(void);
|
|
|
|
|
2017-04-07 19:46:13 +01:00
|
|
|
ctr128_f aes_ctr_set_key(AES_KEY *aes_key, GCM128_CONTEXT *gcm_ctx,
|
|
|
|
block128_f *out_block, const uint8_t *key,
|
|
|
|
size_t key_bytes) {
|
2015-03-13 18:49:22 +00:00
|
|
|
if (aesni_capable()) {
|
2017-04-07 19:46:13 +01:00
|
|
|
aesni_set_encrypt_key(key, key_bytes * 8, aes_key);
|
2015-03-13 18:49:22 +00:00
|
|
|
if (gcm_ctx != NULL) {
|
2017-04-21 19:29:57 +01:00
|
|
|
CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)aesni_encrypt, 1);
|
2015-03-13 18:49:22 +00:00
|
|
|
}
|
|
|
|
if (out_block) {
|
|
|
|
*out_block = (block128_f) aesni_encrypt;
|
|
|
|
}
|
|
|
|
return (ctr128_f)aesni_ctr32_encrypt_blocks;
|
|
|
|
}
|
|
|
|
|
2015-01-09 23:44:37 +00:00
|
|
|
if (hwaes_capable()) {
|
2017-04-07 19:46:13 +01:00
|
|
|
aes_hw_set_encrypt_key(key, key_bytes * 8, aes_key);
|
2015-03-13 18:49:22 +00:00
|
|
|
if (gcm_ctx != NULL) {
|
2017-04-21 19:29:57 +01:00
|
|
|
CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)aes_hw_encrypt, 0);
|
2015-03-13 18:49:22 +00:00
|
|
|
}
|
|
|
|
if (out_block) {
|
2016-09-23 20:47:24 +01:00
|
|
|
*out_block = (block128_f) aes_hw_encrypt;
|
2015-03-13 18:49:22 +00:00
|
|
|
}
|
2016-09-23 20:47:24 +01:00
|
|
|
return (ctr128_f)aes_hw_ctr32_encrypt_blocks;
|
2015-01-09 23:44:37 +00:00
|
|
|
}
|
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
if (bsaes_capable()) {
|
2017-04-07 19:46:13 +01:00
|
|
|
AES_set_encrypt_key(key, key_bytes * 8, aes_key);
|
2015-03-13 18:49:22 +00:00
|
|
|
if (gcm_ctx != NULL) {
|
2017-04-21 19:29:57 +01:00
|
|
|
CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)AES_encrypt, 0);
|
2015-03-13 18:49:22 +00:00
|
|
|
}
|
|
|
|
if (out_block) {
|
|
|
|
*out_block = (block128_f) AES_encrypt;
|
|
|
|
}
|
2014-06-20 20:00:00 +01:00
|
|
|
return (ctr128_f)bsaes_ctr32_encrypt_blocks;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vpaes_capable()) {
|
2017-04-07 19:46:13 +01:00
|
|
|
vpaes_set_encrypt_key(key, key_bytes * 8, aes_key);
|
2015-03-13 18:49:22 +00:00
|
|
|
if (out_block) {
|
|
|
|
*out_block = (block128_f) vpaes_encrypt;
|
|
|
|
}
|
|
|
|
if (gcm_ctx != NULL) {
|
2017-04-21 19:29:57 +01:00
|
|
|
CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)vpaes_encrypt, 0);
|
2015-03-13 18:49:22 +00:00
|
|
|
}
|
2014-06-20 20:00:00 +01:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2017-04-07 19:46:13 +01:00
|
|
|
AES_set_encrypt_key(key, key_bytes * 8, aes_key);
|
2015-03-13 18:49:22 +00:00
|
|
|
if (gcm_ctx != NULL) {
|
2017-04-21 19:29:57 +01:00
|
|
|
CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)AES_encrypt, 0);
|
2015-03-13 18:49:22 +00:00
|
|
|
}
|
|
|
|
if (out_block) {
|
|
|
|
*out_block = (block128_f) AES_encrypt;
|
|
|
|
}
|
2014-06-20 20:00:00 +01:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
static int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
|
|
|
|
const uint8_t *iv, int enc) {
|
|
|
|
EVP_AES_GCM_CTX *gctx = ctx->cipher_data;
|
|
|
|
if (!iv && !key) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (key) {
|
2015-03-13 18:49:22 +00:00
|
|
|
gctx->ctr =
|
|
|
|
aes_ctr_set_key(&gctx->ks.ks, &gctx->gcm, NULL, key, ctx->key_len);
|
2014-06-20 20:00:00 +01:00
|
|
|
/* If we have an iv can set it directly, otherwise use saved IV. */
|
2014-06-20 20:00:00 +01:00
|
|
|
if (iv == NULL && gctx->iv_set) {
|
|
|
|
iv = gctx->iv;
|
|
|
|
}
|
|
|
|
if (iv) {
|
2015-09-27 07:12:01 +01:00
|
|
|
CRYPTO_gcm128_setiv(&gctx->gcm, &gctx->ks.ks, iv, gctx->ivlen);
|
2014-06-20 20:00:00 +01:00
|
|
|
gctx->iv_set = 1;
|
|
|
|
}
|
|
|
|
gctx->key_set = 1;
|
|
|
|
} else {
|
|
|
|
/* If key set use IV, otherwise copy */
|
|
|
|
if (gctx->key_set) {
|
2015-09-27 07:12:01 +01:00
|
|
|
CRYPTO_gcm128_setiv(&gctx->gcm, &gctx->ks.ks, iv, gctx->ivlen);
|
2014-06-20 20:00:00 +01:00
|
|
|
} else {
|
2016-12-13 06:07:13 +00:00
|
|
|
OPENSSL_memcpy(gctx->iv, iv, gctx->ivlen);
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
|
|
|
gctx->iv_set = 1;
|
|
|
|
gctx->iv_gen = 0;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2015-02-23 07:15:50 +00:00
|
|
|
static void aes_gcm_cleanup(EVP_CIPHER_CTX *c) {
|
2014-06-20 20:00:00 +01:00
|
|
|
EVP_AES_GCM_CTX *gctx = c->cipher_data;
|
|
|
|
OPENSSL_cleanse(&gctx->gcm, sizeof(gctx->gcm));
|
|
|
|
if (gctx->iv != c->iv) {
|
|
|
|
OPENSSL_free(gctx->iv);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* increment counter (64-bit int) by 1 */
|
|
|
|
static void ctr64_inc(uint8_t *counter) {
|
|
|
|
int n = 8;
|
|
|
|
uint8_t c;
|
|
|
|
|
|
|
|
do {
|
|
|
|
--n;
|
|
|
|
c = counter[n];
|
|
|
|
++c;
|
|
|
|
counter[n] = c;
|
|
|
|
if (c) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} while (n);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) {
|
|
|
|
EVP_AES_GCM_CTX *gctx = c->cipher_data;
|
|
|
|
switch (type) {
|
|
|
|
case EVP_CTRL_INIT:
|
|
|
|
gctx->key_set = 0;
|
|
|
|
gctx->iv_set = 0;
|
|
|
|
gctx->ivlen = c->cipher->iv_len;
|
|
|
|
gctx->iv = c->iv;
|
|
|
|
gctx->taglen = -1;
|
|
|
|
gctx->iv_gen = 0;
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
case EVP_CTRL_GCM_SET_IVLEN:
|
|
|
|
if (arg <= 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Allocate memory for IV if needed */
|
|
|
|
if (arg > EVP_MAX_IV_LENGTH && arg > gctx->ivlen) {
|
|
|
|
if (gctx->iv != c->iv) {
|
|
|
|
OPENSSL_free(gctx->iv);
|
|
|
|
}
|
|
|
|
gctx->iv = OPENSSL_malloc(arg);
|
|
|
|
if (!gctx->iv) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
gctx->ivlen = arg;
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
case EVP_CTRL_GCM_SET_TAG:
|
|
|
|
if (arg <= 0 || arg > 16 || c->encrypt) {
|
|
|
|
return 0;
|
|
|
|
}
|
2016-12-13 06:07:13 +00:00
|
|
|
OPENSSL_memcpy(c->buf, ptr, arg);
|
2014-06-20 20:00:00 +01:00
|
|
|
gctx->taglen = arg;
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
case EVP_CTRL_GCM_GET_TAG:
|
|
|
|
if (arg <= 0 || arg > 16 || !c->encrypt || gctx->taglen < 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
2016-12-13 06:07:13 +00:00
|
|
|
OPENSSL_memcpy(ptr, c->buf, arg);
|
2014-06-20 20:00:00 +01:00
|
|
|
return 1;
|
|
|
|
|
|
|
|
case EVP_CTRL_GCM_SET_IV_FIXED:
|
|
|
|
/* Special case: -1 length restores whole IV */
|
|
|
|
if (arg == -1) {
|
2016-12-13 06:07:13 +00:00
|
|
|
OPENSSL_memcpy(gctx->iv, ptr, gctx->ivlen);
|
2014-06-20 20:00:00 +01:00
|
|
|
gctx->iv_gen = 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
/* Fixed field must be at least 4 bytes and invocation field
|
|
|
|
* at least 8. */
|
|
|
|
if (arg < 4 || (gctx->ivlen - arg) < 8) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (arg) {
|
2016-12-13 06:07:13 +00:00
|
|
|
OPENSSL_memcpy(gctx->iv, ptr, arg);
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
2014-12-16 12:48:10 +00:00
|
|
|
if (c->encrypt && !RAND_bytes(gctx->iv + arg, gctx->ivlen - arg)) {
|
2014-06-20 20:00:00 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
gctx->iv_gen = 1;
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
case EVP_CTRL_GCM_IV_GEN:
|
|
|
|
if (gctx->iv_gen == 0 || gctx->key_set == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
2015-09-27 07:12:01 +01:00
|
|
|
CRYPTO_gcm128_setiv(&gctx->gcm, &gctx->ks.ks, gctx->iv, gctx->ivlen);
|
2014-06-20 20:00:00 +01:00
|
|
|
if (arg <= 0 || arg > gctx->ivlen) {
|
|
|
|
arg = gctx->ivlen;
|
|
|
|
}
|
2016-12-13 06:07:13 +00:00
|
|
|
OPENSSL_memcpy(ptr, gctx->iv + gctx->ivlen - arg, arg);
|
2014-06-20 20:00:00 +01:00
|
|
|
/* Invocation field will be at least 8 bytes in size and
|
|
|
|
* so no need to check wrap around or increment more than
|
|
|
|
* last 8 bytes. */
|
|
|
|
ctr64_inc(gctx->iv + gctx->ivlen - 8);
|
|
|
|
gctx->iv_set = 1;
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
case EVP_CTRL_GCM_SET_IV_INV:
|
|
|
|
if (gctx->iv_gen == 0 || gctx->key_set == 0 || c->encrypt) {
|
|
|
|
return 0;
|
|
|
|
}
|
2016-12-13 06:07:13 +00:00
|
|
|
OPENSSL_memcpy(gctx->iv + gctx->ivlen - arg, ptr, arg);
|
2015-09-27 07:12:01 +01:00
|
|
|
CRYPTO_gcm128_setiv(&gctx->gcm, &gctx->ks.ks, gctx->iv, gctx->ivlen);
|
2014-06-20 20:00:00 +01:00
|
|
|
gctx->iv_set = 1;
|
|
|
|
return 1;
|
|
|
|
|
2014-07-25 01:42:11 +01:00
|
|
|
case EVP_CTRL_COPY: {
|
|
|
|
EVP_CIPHER_CTX *out = ptr;
|
|
|
|
EVP_AES_GCM_CTX *gctx_out = out->cipher_data;
|
|
|
|
if (gctx->iv == c->iv) {
|
|
|
|
gctx_out->iv = out->iv;
|
|
|
|
} else {
|
|
|
|
gctx_out->iv = OPENSSL_malloc(gctx->ivlen);
|
|
|
|
if (!gctx_out->iv) {
|
|
|
|
return 0;
|
|
|
|
}
|
2016-12-13 06:07:13 +00:00
|
|
|
OPENSSL_memcpy(gctx_out->iv, gctx->iv, gctx->ivlen);
|
2014-07-25 01:42:11 +01:00
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
default:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int aes_gcm_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
|
|
|
|
size_t len) {
|
|
|
|
EVP_AES_GCM_CTX *gctx = ctx->cipher_data;
|
2014-06-20 20:00:00 +01:00
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
/* If not set up, return error */
|
2014-06-20 20:00:00 +01:00
|
|
|
if (!gctx->key_set) {
|
2014-06-20 20:00:00 +01:00
|
|
|
return -1;
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
|
|
|
if (!gctx->iv_set) {
|
2014-06-20 20:00:00 +01:00
|
|
|
return -1;
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
if (in) {
|
|
|
|
if (out == NULL) {
|
2014-06-20 20:00:00 +01:00
|
|
|
if (!CRYPTO_gcm128_aad(&gctx->gcm, in, len)) {
|
2014-06-20 20:00:00 +01:00
|
|
|
return -1;
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
2014-06-20 20:00:00 +01:00
|
|
|
} else if (ctx->encrypt) {
|
|
|
|
if (gctx->ctr) {
|
2016-02-18 04:59:19 +00:00
|
|
|
if (!CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm, &gctx->ks.ks, in, out, len,
|
|
|
|
gctx->ctr)) {
|
2014-06-20 20:00:00 +01:00
|
|
|
return -1;
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
2014-06-20 20:00:00 +01:00
|
|
|
} else {
|
2016-02-18 04:59:19 +00:00
|
|
|
if (!CRYPTO_gcm128_encrypt(&gctx->gcm, &gctx->ks.ks, in, out, len)) {
|
2014-06-20 20:00:00 +01:00
|
|
|
return -1;
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (gctx->ctr) {
|
2016-02-18 04:59:19 +00:00
|
|
|
if (!CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm, &gctx->ks.ks, in, out, len,
|
|
|
|
gctx->ctr)) {
|
2014-06-20 20:00:00 +01:00
|
|
|
return -1;
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
2014-06-20 20:00:00 +01:00
|
|
|
} else {
|
2016-02-18 04:59:19 +00:00
|
|
|
if (!CRYPTO_gcm128_decrypt(&gctx->gcm, &gctx->ks.ks, in, out, len)) {
|
2014-06-20 20:00:00 +01:00
|
|
|
return -1;
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return len;
|
|
|
|
} else {
|
|
|
|
if (!ctx->encrypt) {
|
2014-06-20 20:00:00 +01:00
|
|
|
if (gctx->taglen < 0 ||
|
2015-08-14 21:05:21 +01:00
|
|
|
!CRYPTO_gcm128_finish(&gctx->gcm, ctx->buf, gctx->taglen)) {
|
2014-06-20 20:00:00 +01:00
|
|
|
return -1;
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
2014-06-20 20:00:00 +01:00
|
|
|
gctx->iv_set = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
CRYPTO_gcm128_tag(&gctx->gcm, ctx->buf, 16);
|
|
|
|
gctx->taglen = 16;
|
|
|
|
/* Don't reuse the IV */
|
|
|
|
gctx->iv_set = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static const EVP_CIPHER aes_128_cbc = {
|
|
|
|
NID_aes_128_cbc, 16 /* block_size */, 16 /* key_size */,
|
|
|
|
16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CBC_MODE,
|
|
|
|
NULL /* app_data */, aes_init_key, aes_cbc_cipher,
|
|
|
|
NULL /* cleanup */, NULL /* ctrl */};
|
|
|
|
|
|
|
|
static const EVP_CIPHER aes_128_ctr = {
|
|
|
|
NID_aes_128_ctr, 1 /* block_size */, 16 /* key_size */,
|
|
|
|
16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CTR_MODE,
|
|
|
|
NULL /* app_data */, aes_init_key, aes_ctr_cipher,
|
|
|
|
NULL /* cleanup */, NULL /* ctrl */};
|
|
|
|
|
|
|
|
static const EVP_CIPHER aes_128_ecb = {
|
|
|
|
NID_aes_128_ecb, 16 /* block_size */, 16 /* key_size */,
|
2014-10-21 00:20:55 +01:00
|
|
|
0 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_ECB_MODE,
|
2014-06-20 20:00:00 +01:00
|
|
|
NULL /* app_data */, aes_init_key, aes_ecb_cipher,
|
|
|
|
NULL /* cleanup */, NULL /* ctrl */};
|
|
|
|
|
2015-02-24 20:44:40 +00:00
|
|
|
static const EVP_CIPHER aes_128_ofb = {
|
|
|
|
NID_aes_128_ofb128, 1 /* block_size */, 16 /* key_size */,
|
|
|
|
16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_OFB_MODE,
|
|
|
|
NULL /* app_data */, aes_init_key, aes_ofb_cipher,
|
|
|
|
NULL /* cleanup */, NULL /* ctrl */};
|
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
static const EVP_CIPHER aes_128_gcm = {
|
|
|
|
NID_aes_128_gcm, 1 /* block_size */, 16 /* key_size */, 12 /* iv_len */,
|
|
|
|
sizeof(EVP_AES_GCM_CTX),
|
|
|
|
EVP_CIPH_GCM_MODE | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER |
|
|
|
|
EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT |
|
|
|
|
EVP_CIPH_FLAG_AEAD_CIPHER,
|
|
|
|
NULL /* app_data */, aes_gcm_init_key, aes_gcm_cipher, aes_gcm_cleanup,
|
|
|
|
aes_gcm_ctrl};
|
|
|
|
|
|
|
|
|
2015-04-02 21:09:01 +01:00
|
|
|
static const EVP_CIPHER aes_192_cbc = {
|
|
|
|
NID_aes_192_cbc, 16 /* block_size */, 24 /* key_size */,
|
|
|
|
16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CBC_MODE,
|
|
|
|
NULL /* app_data */, aes_init_key, aes_cbc_cipher,
|
|
|
|
NULL /* cleanup */, NULL /* ctrl */};
|
|
|
|
|
|
|
|
static const EVP_CIPHER aes_192_ctr = {
|
|
|
|
NID_aes_192_ctr, 1 /* block_size */, 24 /* key_size */,
|
|
|
|
16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CTR_MODE,
|
|
|
|
NULL /* app_data */, aes_init_key, aes_ctr_cipher,
|
|
|
|
NULL /* cleanup */, NULL /* ctrl */};
|
|
|
|
|
2015-05-05 01:41:23 +01:00
|
|
|
static const EVP_CIPHER aes_192_ecb = {
|
|
|
|
NID_aes_192_ecb, 16 /* block_size */, 24 /* key_size */,
|
|
|
|
0 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_ECB_MODE,
|
|
|
|
NULL /* app_data */, aes_init_key, aes_ecb_cipher,
|
|
|
|
NULL /* cleanup */, NULL /* ctrl */};
|
|
|
|
|
2015-04-02 21:09:01 +01:00
|
|
|
static const EVP_CIPHER aes_192_gcm = {
|
|
|
|
NID_aes_192_gcm, 1 /* block_size */, 24 /* key_size */, 12 /* iv_len */,
|
|
|
|
sizeof(EVP_AES_GCM_CTX),
|
|
|
|
EVP_CIPH_GCM_MODE | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER |
|
|
|
|
EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT |
|
|
|
|
EVP_CIPH_FLAG_AEAD_CIPHER,
|
|
|
|
NULL /* app_data */, aes_gcm_init_key, aes_gcm_cipher, aes_gcm_cleanup,
|
|
|
|
aes_gcm_ctrl};
|
|
|
|
|
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
static const EVP_CIPHER aes_256_cbc = {
|
2015-02-02 19:22:49 +00:00
|
|
|
NID_aes_256_cbc, 16 /* block_size */, 32 /* key_size */,
|
2014-06-20 20:00:00 +01:00
|
|
|
16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CBC_MODE,
|
|
|
|
NULL /* app_data */, aes_init_key, aes_cbc_cipher,
|
|
|
|
NULL /* cleanup */, NULL /* ctrl */};
|
|
|
|
|
|
|
|
static const EVP_CIPHER aes_256_ctr = {
|
2015-02-02 19:22:49 +00:00
|
|
|
NID_aes_256_ctr, 1 /* block_size */, 32 /* key_size */,
|
2014-06-20 20:00:00 +01:00
|
|
|
16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CTR_MODE,
|
|
|
|
NULL /* app_data */, aes_init_key, aes_ctr_cipher,
|
|
|
|
NULL /* cleanup */, NULL /* ctrl */};
|
|
|
|
|
|
|
|
static const EVP_CIPHER aes_256_ecb = {
|
2015-02-02 19:22:49 +00:00
|
|
|
NID_aes_256_ecb, 16 /* block_size */, 32 /* key_size */,
|
2014-10-21 00:20:55 +01:00
|
|
|
0 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_ECB_MODE,
|
2014-06-20 20:00:00 +01:00
|
|
|
NULL /* app_data */, aes_init_key, aes_ecb_cipher,
|
|
|
|
NULL /* cleanup */, NULL /* ctrl */};
|
|
|
|
|
2015-02-24 20:44:40 +00:00
|
|
|
static const EVP_CIPHER aes_256_ofb = {
|
|
|
|
NID_aes_256_ofb128, 1 /* block_size */, 32 /* key_size */,
|
|
|
|
16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_OFB_MODE,
|
|
|
|
NULL /* app_data */, aes_init_key, aes_ofb_cipher,
|
|
|
|
NULL /* cleanup */, NULL /* ctrl */};
|
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
static const EVP_CIPHER aes_256_gcm = {
|
2015-02-02 19:22:49 +00:00
|
|
|
NID_aes_256_gcm, 1 /* block_size */, 32 /* key_size */, 12 /* iv_len */,
|
2014-06-20 20:00:00 +01:00
|
|
|
sizeof(EVP_AES_GCM_CTX),
|
|
|
|
EVP_CIPH_GCM_MODE | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER |
|
|
|
|
EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT |
|
|
|
|
EVP_CIPH_FLAG_AEAD_CIPHER,
|
|
|
|
NULL /* app_data */, aes_gcm_init_key, aes_gcm_cipher, aes_gcm_cleanup,
|
|
|
|
aes_gcm_ctrl};
|
|
|
|
|
|
|
|
#if !defined(OPENSSL_NO_ASM) && \
|
|
|
|
(defined(OPENSSL_X86_64) || defined(OPENSSL_X86))
|
|
|
|
|
|
|
|
/* AES-NI section. */
|
|
|
|
|
2014-08-20 21:24:00 +01:00
|
|
|
static char aesni_capable(void) {
|
2014-06-20 20:00:00 +01:00
|
|
|
return (OPENSSL_ia32cap_P[1] & (1 << (57 - 32))) != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int aesni_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
|
|
|
|
const uint8_t *iv, int enc) {
|
|
|
|
int ret, mode;
|
|
|
|
EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
|
|
|
|
|
|
|
|
mode = ctx->cipher->flags & EVP_CIPH_MODE_MASK;
|
|
|
|
if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) && !enc) {
|
|
|
|
ret = aesni_set_decrypt_key(key, ctx->key_len * 8, ctx->cipher_data);
|
|
|
|
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, ctx->key_len * 8, ctx->cipher_data);
|
|
|
|
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) {
|
2015-06-29 05:28:17 +01:00
|
|
|
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_AES_KEY_SETUP_FAILED);
|
2014-06-20 20:00:00 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int aesni_cbc_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out,
|
|
|
|
const uint8_t *in, size_t len) {
|
|
|
|
aesni_cbc_encrypt(in, out, len, ctx->cipher_data, ctx->iv, ctx->encrypt);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int aesni_ecb_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out,
|
|
|
|
const uint8_t *in, size_t len) {
|
|
|
|
size_t bl = ctx->cipher->block_size;
|
|
|
|
|
|
|
|
if (len < bl) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
aesni_ecb_encrypt(in, out, len, ctx->cipher_data, ctx->encrypt);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int aesni_gcm_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
|
|
|
|
const uint8_t *iv, int enc) {
|
|
|
|
EVP_AES_GCM_CTX *gctx = ctx->cipher_data;
|
2014-06-20 20:00:00 +01:00
|
|
|
if (!iv && !key) {
|
2014-06-20 20:00:00 +01:00
|
|
|
return 1;
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
2014-06-20 20:00:00 +01:00
|
|
|
if (key) {
|
|
|
|
aesni_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks);
|
2017-04-21 19:29:57 +01:00
|
|
|
CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, (block128_f)aesni_encrypt, 1);
|
2014-06-20 20:00:00 +01:00
|
|
|
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) {
|
2015-09-27 07:12:01 +01:00
|
|
|
CRYPTO_gcm128_setiv(&gctx->gcm, &gctx->ks.ks, iv, gctx->ivlen);
|
2014-06-20 20:00:00 +01:00
|
|
|
gctx->iv_set = 1;
|
|
|
|
}
|
|
|
|
gctx->key_set = 1;
|
|
|
|
} else {
|
|
|
|
/* If key set use IV, otherwise copy */
|
|
|
|
if (gctx->key_set) {
|
2015-09-27 07:12:01 +01:00
|
|
|
CRYPTO_gcm128_setiv(&gctx->gcm, &gctx->ks.ks, iv, gctx->ivlen);
|
2014-06-20 20:00:00 +01:00
|
|
|
} else {
|
2016-12-13 06:07:13 +00:00
|
|
|
OPENSSL_memcpy(gctx->iv, iv, gctx->ivlen);
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
|
|
|
gctx->iv_set = 1;
|
|
|
|
gctx->iv_gen = 0;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const EVP_CIPHER aesni_128_cbc = {
|
|
|
|
NID_aes_128_cbc, 16 /* block_size */, 16 /* key_size */,
|
|
|
|
16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CBC_MODE,
|
|
|
|
NULL /* app_data */, aesni_init_key, aesni_cbc_cipher,
|
|
|
|
NULL /* cleanup */, NULL /* ctrl */};
|
|
|
|
|
|
|
|
static const EVP_CIPHER aesni_128_ctr = {
|
|
|
|
NID_aes_128_ctr, 1 /* block_size */, 16 /* key_size */,
|
|
|
|
16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CTR_MODE,
|
|
|
|
NULL /* app_data */, aesni_init_key, aes_ctr_cipher,
|
|
|
|
NULL /* cleanup */, NULL /* ctrl */};
|
|
|
|
|
|
|
|
static const EVP_CIPHER aesni_128_ecb = {
|
|
|
|
NID_aes_128_ecb, 16 /* block_size */, 16 /* key_size */,
|
2014-10-21 00:20:55 +01:00
|
|
|
0 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_ECB_MODE,
|
2014-06-20 20:00:00 +01:00
|
|
|
NULL /* app_data */, aesni_init_key, aesni_ecb_cipher,
|
|
|
|
NULL /* cleanup */, NULL /* ctrl */};
|
|
|
|
|
2015-02-24 20:44:40 +00:00
|
|
|
static const EVP_CIPHER aesni_128_ofb = {
|
|
|
|
NID_aes_128_ofb128, 1 /* block_size */, 16 /* key_size */,
|
|
|
|
16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_OFB_MODE,
|
|
|
|
NULL /* app_data */, aesni_init_key, aes_ofb_cipher,
|
|
|
|
NULL /* cleanup */, NULL /* ctrl */};
|
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
static const EVP_CIPHER aesni_128_gcm = {
|
|
|
|
NID_aes_128_gcm, 1 /* block_size */, 16 /* key_size */, 12 /* iv_len */,
|
|
|
|
sizeof(EVP_AES_GCM_CTX),
|
|
|
|
EVP_CIPH_GCM_MODE | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER |
|
|
|
|
EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT |
|
|
|
|
EVP_CIPH_FLAG_AEAD_CIPHER,
|
|
|
|
NULL /* app_data */, aesni_gcm_init_key, aes_gcm_cipher, aes_gcm_cleanup,
|
|
|
|
aes_gcm_ctrl};
|
|
|
|
|
|
|
|
|
2015-04-02 21:09:01 +01:00
|
|
|
static const EVP_CIPHER aesni_192_cbc = {
|
|
|
|
NID_aes_192_cbc, 16 /* block_size */, 24 /* key_size */,
|
|
|
|
16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CBC_MODE,
|
|
|
|
NULL /* app_data */, aesni_init_key, aesni_cbc_cipher,
|
|
|
|
NULL /* cleanup */, NULL /* ctrl */};
|
|
|
|
|
|
|
|
static const EVP_CIPHER aesni_192_ctr = {
|
|
|
|
NID_aes_192_ctr, 1 /* block_size */, 24 /* key_size */,
|
|
|
|
16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CTR_MODE,
|
|
|
|
NULL /* app_data */, aesni_init_key, aes_ctr_cipher,
|
|
|
|
NULL /* cleanup */, NULL /* ctrl */};
|
|
|
|
|
2015-05-05 01:41:23 +01:00
|
|
|
static const EVP_CIPHER aesni_192_ecb = {
|
|
|
|
NID_aes_192_ecb, 16 /* block_size */, 24 /* key_size */,
|
|
|
|
0 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_ECB_MODE,
|
|
|
|
NULL /* app_data */, aesni_init_key, aesni_ecb_cipher,
|
|
|
|
NULL /* cleanup */, NULL /* ctrl */};
|
|
|
|
|
2015-04-02 21:09:01 +01:00
|
|
|
static const EVP_CIPHER aesni_192_gcm = {
|
|
|
|
NID_aes_192_gcm, 1 /* block_size */, 24 /* key_size */, 12 /* iv_len */,
|
|
|
|
sizeof(EVP_AES_GCM_CTX),
|
|
|
|
EVP_CIPH_GCM_MODE | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER |
|
|
|
|
EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT |
|
|
|
|
EVP_CIPH_FLAG_AEAD_CIPHER,
|
|
|
|
NULL /* app_data */, aesni_gcm_init_key, aes_gcm_cipher, aes_gcm_cleanup,
|
|
|
|
aes_gcm_ctrl};
|
|
|
|
|
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
static const EVP_CIPHER aesni_256_cbc = {
|
2015-02-02 19:22:49 +00:00
|
|
|
NID_aes_256_cbc, 16 /* block_size */, 32 /* key_size */,
|
2014-06-20 20:00:00 +01:00
|
|
|
16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CBC_MODE,
|
|
|
|
NULL /* app_data */, aesni_init_key, aesni_cbc_cipher,
|
|
|
|
NULL /* cleanup */, NULL /* ctrl */};
|
|
|
|
|
|
|
|
static const EVP_CIPHER aesni_256_ctr = {
|
2015-02-02 19:22:49 +00:00
|
|
|
NID_aes_256_ctr, 1 /* block_size */, 32 /* key_size */,
|
2014-06-20 20:00:00 +01:00
|
|
|
16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CTR_MODE,
|
|
|
|
NULL /* app_data */, aesni_init_key, aes_ctr_cipher,
|
|
|
|
NULL /* cleanup */, NULL /* ctrl */};
|
|
|
|
|
|
|
|
static const EVP_CIPHER aesni_256_ecb = {
|
2015-02-02 19:22:49 +00:00
|
|
|
NID_aes_256_ecb, 16 /* block_size */, 32 /* key_size */,
|
2014-10-21 00:20:55 +01:00
|
|
|
0 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_ECB_MODE,
|
2014-06-20 20:00:00 +01:00
|
|
|
NULL /* app_data */, aesni_init_key, aesni_ecb_cipher,
|
|
|
|
NULL /* cleanup */, NULL /* ctrl */};
|
|
|
|
|
2015-02-24 20:44:40 +00:00
|
|
|
static const EVP_CIPHER aesni_256_ofb = {
|
|
|
|
NID_aes_256_ofb128, 1 /* block_size */, 32 /* key_size */,
|
|
|
|
16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_OFB_MODE,
|
|
|
|
NULL /* app_data */, aesni_init_key, aes_ofb_cipher,
|
|
|
|
NULL /* cleanup */, NULL /* ctrl */};
|
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
static const EVP_CIPHER aesni_256_gcm = {
|
|
|
|
NID_aes_256_gcm, 1 /* block_size */, 32 /* key_size */, 12 /* iv_len */,
|
|
|
|
sizeof(EVP_AES_GCM_CTX),
|
|
|
|
EVP_CIPH_GCM_MODE | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER |
|
2014-07-25 01:42:11 +01:00
|
|
|
EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT | EVP_CIPH_CUSTOM_COPY |
|
2014-06-20 20:00:00 +01:00
|
|
|
EVP_CIPH_FLAG_AEAD_CIPHER,
|
|
|
|
NULL /* app_data */, aesni_gcm_init_key, aes_gcm_cipher, aes_gcm_cleanup,
|
|
|
|
aes_gcm_ctrl};
|
|
|
|
|
|
|
|
#define EVP_CIPHER_FUNCTION(keybits, mode) \
|
|
|
|
const EVP_CIPHER *EVP_aes_##keybits##_##mode(void) { \
|
|
|
|
if (aesni_capable()) { \
|
|
|
|
return &aesni_##keybits##_##mode; \
|
|
|
|
} else { \
|
|
|
|
return &aes_##keybits##_##mode; \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
#else /* ^^^ OPENSSL_X86_64 || OPENSSL_X86 */
|
|
|
|
|
2014-08-20 21:24:00 +01:00
|
|
|
static char aesni_capable(void) {
|
2014-06-20 20:00:00 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
#define EVP_CIPHER_FUNCTION(keybits, mode) \
|
|
|
|
const EVP_CIPHER *EVP_aes_##keybits##_##mode(void) { \
|
|
|
|
return &aes_##keybits##_##mode; \
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
EVP_CIPHER_FUNCTION(128, cbc)
|
|
|
|
EVP_CIPHER_FUNCTION(128, ctr)
|
|
|
|
EVP_CIPHER_FUNCTION(128, ecb)
|
2015-02-24 20:44:40 +00:00
|
|
|
EVP_CIPHER_FUNCTION(128, ofb)
|
2014-06-20 20:00:00 +01:00
|
|
|
EVP_CIPHER_FUNCTION(128, gcm)
|
|
|
|
|
2015-04-02 21:09:01 +01:00
|
|
|
EVP_CIPHER_FUNCTION(192, cbc)
|
|
|
|
EVP_CIPHER_FUNCTION(192, ctr)
|
2015-05-05 01:41:23 +01:00
|
|
|
EVP_CIPHER_FUNCTION(192, ecb)
|
2015-04-02 21:09:01 +01:00
|
|
|
EVP_CIPHER_FUNCTION(192, gcm)
|
|
|
|
|
2014-06-20 20:00:00 +01:00
|
|
|
EVP_CIPHER_FUNCTION(256, cbc)
|
|
|
|
EVP_CIPHER_FUNCTION(256, ctr)
|
|
|
|
EVP_CIPHER_FUNCTION(256, ecb)
|
2015-02-24 20:44:40 +00:00
|
|
|
EVP_CIPHER_FUNCTION(256, ofb)
|
2014-06-20 20:00:00 +01:00
|
|
|
EVP_CIPHER_FUNCTION(256, gcm)
|
2014-06-20 20:00:00 +01:00
|
|
|
|
|
|
|
|
|
|
|
#define EVP_AEAD_AES_GCM_TAG_LEN 16
|
|
|
|
|
|
|
|
struct aead_aes_gcm_ctx {
|
|
|
|
union {
|
|
|
|
double align;
|
|
|
|
AES_KEY ks;
|
|
|
|
} ks;
|
|
|
|
GCM128_CONTEXT gcm;
|
|
|
|
ctr128_f ctr;
|
|
|
|
uint8_t tag_len;
|
|
|
|
};
|
|
|
|
|
|
|
|
static int aead_aes_gcm_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
|
|
|
|
size_t key_len, size_t tag_len) {
|
|
|
|
struct aead_aes_gcm_ctx *gcm_ctx;
|
|
|
|
const size_t key_bits = key_len * 8;
|
|
|
|
|
|
|
|
if (key_bits != 128 && key_bits != 256) {
|
2015-06-29 05:28:17 +01:00
|
|
|
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH);
|
2014-06-20 20:00:00 +01:00
|
|
|
return 0; /* EVP_AEAD_CTX_init should catch this. */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tag_len == EVP_AEAD_DEFAULT_TAG_LENGTH) {
|
|
|
|
tag_len = EVP_AEAD_AES_GCM_TAG_LEN;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tag_len > EVP_AEAD_AES_GCM_TAG_LEN) {
|
2015-06-29 05:28:17 +01:00
|
|
|
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TAG_TOO_LARGE);
|
2014-06-20 20:00:00 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
gcm_ctx = OPENSSL_malloc(sizeof(struct aead_aes_gcm_ctx));
|
|
|
|
if (gcm_ctx == NULL) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-03-13 18:49:22 +00:00
|
|
|
gcm_ctx->ctr =
|
|
|
|
aes_ctr_set_key(&gcm_ctx->ks.ks, &gcm_ctx->gcm, NULL, key, key_len);
|
2014-06-20 20:00:00 +01:00
|
|
|
gcm_ctx->tag_len = tag_len;
|
|
|
|
ctx->aead_state = gcm_ctx;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void aead_aes_gcm_cleanup(EVP_AEAD_CTX *ctx) {
|
|
|
|
struct aead_aes_gcm_ctx *gcm_ctx = ctx->aead_state;
|
|
|
|
OPENSSL_cleanse(gcm_ctx, sizeof(struct aead_aes_gcm_ctx));
|
|
|
|
OPENSSL_free(gcm_ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int aead_aes_gcm_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
|
|
|
|
size_t *out_len, size_t max_out_len,
|
|
|
|
const uint8_t *nonce, size_t nonce_len,
|
|
|
|
const uint8_t *in, size_t in_len,
|
|
|
|
const uint8_t *ad, size_t ad_len) {
|
|
|
|
const struct aead_aes_gcm_ctx *gcm_ctx = ctx->aead_state;
|
|
|
|
GCM128_CONTEXT gcm;
|
|
|
|
|
|
|
|
if (in_len + gcm_ctx->tag_len < in_len) {
|
2015-06-29 05:28:17 +01:00
|
|
|
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
|
2014-06-20 20:00:00 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (max_out_len < in_len + gcm_ctx->tag_len) {
|
2015-06-29 05:28:17 +01:00
|
|
|
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
|
2014-06-20 20:00:00 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-09-27 07:12:01 +01:00
|
|
|
const AES_KEY *key = &gcm_ctx->ks.ks;
|
|
|
|
|
2016-12-13 06:07:13 +00:00
|
|
|
OPENSSL_memcpy(&gcm, &gcm_ctx->gcm, sizeof(gcm));
|
2015-09-27 07:12:01 +01:00
|
|
|
CRYPTO_gcm128_setiv(&gcm, key, nonce, nonce_len);
|
2014-06-20 20:00:00 +01:00
|
|
|
|
|
|
|
if (ad_len > 0 && !CRYPTO_gcm128_aad(&gcm, ad, ad_len)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gcm_ctx->ctr) {
|
2015-09-27 07:12:01 +01:00
|
|
|
if (!CRYPTO_gcm128_encrypt_ctr32(&gcm, key, in, out, in_len,
|
|
|
|
gcm_ctx->ctr)) {
|
2014-06-20 20:00:00 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else {
|
2015-09-27 07:12:01 +01:00
|
|
|
if (!CRYPTO_gcm128_encrypt(&gcm, key, in, out, in_len)) {
|
2014-06-20 20:00:00 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CRYPTO_gcm128_tag(&gcm, out + in_len, gcm_ctx->tag_len);
|
|
|
|
*out_len = in_len + gcm_ctx->tag_len;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int aead_aes_gcm_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
|
|
|
|
size_t *out_len, size_t max_out_len,
|
|
|
|
const uint8_t *nonce, size_t nonce_len,
|
|
|
|
const uint8_t *in, size_t in_len,
|
|
|
|
const uint8_t *ad, size_t ad_len) {
|
|
|
|
const struct aead_aes_gcm_ctx *gcm_ctx = ctx->aead_state;
|
|
|
|
uint8_t tag[EVP_AEAD_AES_GCM_TAG_LEN];
|
|
|
|
size_t plaintext_len;
|
|
|
|
GCM128_CONTEXT gcm;
|
|
|
|
|
|
|
|
if (in_len < gcm_ctx->tag_len) {
|
2015-06-29 05:28:17 +01:00
|
|
|
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
|
2014-06-20 20:00:00 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
plaintext_len = in_len - gcm_ctx->tag_len;
|
|
|
|
|
|
|
|
if (max_out_len < plaintext_len) {
|
2015-06-29 05:28:17 +01:00
|
|
|
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
|
2014-06-20 20:00:00 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-09-27 07:12:01 +01:00
|
|
|
const AES_KEY *key = &gcm_ctx->ks.ks;
|
|
|
|
|
2016-12-13 06:07:13 +00:00
|
|
|
OPENSSL_memcpy(&gcm, &gcm_ctx->gcm, sizeof(gcm));
|
2015-09-27 07:12:01 +01:00
|
|
|
CRYPTO_gcm128_setiv(&gcm, key, nonce, nonce_len);
|
2014-06-20 20:00:00 +01:00
|
|
|
|
|
|
|
if (!CRYPTO_gcm128_aad(&gcm, ad, ad_len)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gcm_ctx->ctr) {
|
2015-09-27 07:12:01 +01:00
|
|
|
if (!CRYPTO_gcm128_decrypt_ctr32(&gcm, key, in, out,
|
|
|
|
in_len - gcm_ctx->tag_len, gcm_ctx->ctr)) {
|
2014-06-20 20:00:00 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else {
|
2015-09-27 07:12:01 +01:00
|
|
|
if (!CRYPTO_gcm128_decrypt(&gcm, key, in, out, in_len - gcm_ctx->tag_len)) {
|
2014-06-20 20:00:00 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CRYPTO_gcm128_tag(&gcm, tag, gcm_ctx->tag_len);
|
|
|
|
if (CRYPTO_memcmp(tag, in + plaintext_len, gcm_ctx->tag_len) != 0) {
|
2015-06-29 05:28:17 +01:00
|
|
|
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
|
2014-06-20 20:00:00 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
*out_len = plaintext_len;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const EVP_AEAD aead_aes_128_gcm = {
|
|
|
|
16, /* key len */
|
|
|
|
12, /* nonce len */
|
|
|
|
EVP_AEAD_AES_GCM_TAG_LEN, /* overhead */
|
|
|
|
EVP_AEAD_AES_GCM_TAG_LEN, /* max tag length */
|
2015-02-28 08:59:33 +00:00
|
|
|
aead_aes_gcm_init,
|
|
|
|
NULL, /* init_with_direction */
|
|
|
|
aead_aes_gcm_cleanup,
|
|
|
|
aead_aes_gcm_seal,
|
|
|
|
aead_aes_gcm_open,
|
2015-11-04 02:36:10 +00:00
|
|
|
NULL, /* get_iv */
|
2014-06-20 20:00:00 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
static const EVP_AEAD aead_aes_256_gcm = {
|
|
|
|
32, /* key len */
|
|
|
|
12, /* nonce len */
|
|
|
|
EVP_AEAD_AES_GCM_TAG_LEN, /* overhead */
|
|
|
|
EVP_AEAD_AES_GCM_TAG_LEN, /* max tag length */
|
2015-02-28 08:59:33 +00:00
|
|
|
aead_aes_gcm_init,
|
|
|
|
NULL, /* init_with_direction */
|
|
|
|
aead_aes_gcm_cleanup,
|
|
|
|
aead_aes_gcm_seal,
|
|
|
|
aead_aes_gcm_open,
|
2015-11-04 02:36:10 +00:00
|
|
|
NULL, /* get_iv */
|
2014-06-20 20:00:00 +01:00
|
|
|
};
|
|
|
|
|
2014-08-20 21:24:00 +01:00
|
|
|
const EVP_AEAD *EVP_aead_aes_128_gcm(void) { return &aead_aes_128_gcm; }
|
2014-06-20 20:00:00 +01:00
|
|
|
|
2014-08-20 21:24:00 +01:00
|
|
|
const EVP_AEAD *EVP_aead_aes_256_gcm(void) { return &aead_aes_256_gcm; }
|
2014-07-25 23:40:44 +01:00
|
|
|
|
2017-04-19 21:45:09 +01:00
|
|
|
#if defined(BORINGSSL_FIPS)
|
|
|
|
#define FIPS_AES_GCM_IV_LEN 12
|
|
|
|
|
|
|
|
static int aead_aes_gcm_fips_testonly_seal(
|
|
|
|
const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len, size_t max_out_len,
|
|
|
|
const uint8_t *nonce, size_t nonce_len, const uint8_t *in, size_t in_len,
|
|
|
|
const uint8_t *ad, size_t ad_len) {
|
|
|
|
if (nonce_len != 0) {
|
|
|
|
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (max_out_len < FIPS_AES_GCM_IV_LEN) {
|
|
|
|
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t real_nonce[FIPS_AES_GCM_IV_LEN];
|
|
|
|
if (!RAND_bytes(real_nonce, sizeof(real_nonce))) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
int ret =
|
|
|
|
aead_aes_gcm_seal(ctx, out, out_len, max_out_len - FIPS_AES_GCM_IV_LEN,
|
|
|
|
real_nonce, sizeof(real_nonce), in, in_len, ad, ad_len);
|
|
|
|
if (ret) {
|
|
|
|
/* Copy the generated IV into the start of the ciphertext. */
|
|
|
|
OPENSSL_memmove(out + sizeof(real_nonce), out, *out_len);
|
|
|
|
OPENSSL_memcpy(out, real_nonce, sizeof(real_nonce));
|
|
|
|
*out_len += sizeof(real_nonce);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int aead_aes_gcm_fips_testonly_open(
|
|
|
|
const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len, size_t max_out_len,
|
|
|
|
const uint8_t *nonce, size_t nonce_len, const uint8_t *in, size_t in_len,
|
|
|
|
const uint8_t *ad, size_t ad_len) {
|
|
|
|
if (nonce_len != 0) {
|
|
|
|
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (in_len < FIPS_AES_GCM_IV_LEN) {
|
|
|
|
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Parse the generated IV from the start of the ciphertext. */
|
|
|
|
uint8_t real_nonce[FIPS_AES_GCM_IV_LEN];
|
|
|
|
OPENSSL_memcpy(real_nonce, in, sizeof(real_nonce));
|
|
|
|
|
|
|
|
/* Aliasing guarantees only allow the use of overlapping buffers when the
|
|
|
|
* input and output buffers are identical, so a new input needs to be
|
|
|
|
* allocated for the actual input ciphertext. */
|
|
|
|
size_t real_len = in_len - FIPS_AES_GCM_IV_LEN;
|
|
|
|
uint8_t *real_in = OPENSSL_malloc(real_len);
|
|
|
|
if (real_in == NULL) {
|
|
|
|
OPENSSL_PUT_ERROR(CIPHER, ERR_R_MALLOC_FAILURE);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
OPENSSL_memcpy(real_in, in + FIPS_AES_GCM_IV_LEN, real_len);
|
|
|
|
|
|
|
|
int ret =
|
|
|
|
aead_aes_gcm_open(ctx, out, out_len, max_out_len, real_nonce,
|
|
|
|
sizeof(real_nonce), real_in, real_len, ad, ad_len);
|
|
|
|
|
|
|
|
OPENSSL_free(real_in);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const EVP_AEAD aead_aes_128_gcm_fips_testonly = {
|
|
|
|
16, /* key len */
|
|
|
|
0, /* nonce len */
|
|
|
|
EVP_AEAD_AES_GCM_TAG_LEN + FIPS_AES_GCM_IV_LEN, /* overhead */
|
|
|
|
EVP_AEAD_AES_GCM_TAG_LEN, /* max tag length */
|
|
|
|
aead_aes_gcm_init,
|
|
|
|
NULL, /* init_with_direction */
|
|
|
|
aead_aes_gcm_cleanup,
|
|
|
|
aead_aes_gcm_fips_testonly_seal,
|
|
|
|
aead_aes_gcm_fips_testonly_open,
|
|
|
|
NULL, /* get_iv */
|
|
|
|
};
|
|
|
|
|
|
|
|
static const EVP_AEAD aead_aes_256_gcm_fips_testonly = {
|
|
|
|
32, /* key len */
|
|
|
|
0, /* nonce len */
|
|
|
|
EVP_AEAD_AES_GCM_TAG_LEN + FIPS_AES_GCM_IV_LEN, /* overhead */
|
|
|
|
EVP_AEAD_AES_GCM_TAG_LEN, /* max tag length */
|
|
|
|
aead_aes_gcm_init,
|
|
|
|
NULL, /* init_with_direction */
|
|
|
|
aead_aes_gcm_cleanup,
|
|
|
|
aead_aes_gcm_fips_testonly_seal,
|
|
|
|
aead_aes_gcm_fips_testonly_open,
|
|
|
|
NULL, /* get_iv */
|
|
|
|
};
|
|
|
|
|
|
|
|
const EVP_AEAD *EVP_aead_aes_128_gcm_fips_testonly(void) {
|
|
|
|
return &aead_aes_128_gcm_fips_testonly;
|
|
|
|
}
|
|
|
|
|
|
|
|
const EVP_AEAD *EVP_aead_aes_256_gcm_fips_testonly(void) {
|
|
|
|
return &aead_aes_256_gcm_fips_testonly;
|
|
|
|
}
|
|
|
|
#endif /* BORINGSSL_FIPS */
|
2014-07-25 23:40:44 +01:00
|
|
|
|
2014-08-20 19:19:54 +01:00
|
|
|
int EVP_has_aes_hardware(void) {
|
|
|
|
#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
|
|
|
|
return aesni_capable() && crypto_gcm_clmul_enabled();
|
2015-01-09 23:44:37 +00:00
|
|
|
#elif defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)
|
2015-10-16 23:46:46 +01:00
|
|
|
return hwaes_capable() && CRYPTO_is_ARMv8_PMULL_capable();
|
2014-08-20 19:19:54 +01:00
|
|
|
#else
|
|
|
|
return 0;
|
|
|
|
#endif
|
|
|
|
}
|