diff options
author | Nicolas Boichat <drinkcat@chromium.org> | 2018-07-05 16:54:46 +0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-09-21 00:50:59 -0700 |
commit | 15dd79c1a2ab3355a7d7a0197fcacff973a001a2 (patch) | |
tree | 29da6e71d014137ea52c9ff728b1ba1061119700 /third_party | |
parent | 4a237232c27c18d5367403d743d523509570e5cd (diff) | |
download | chrome-ec-15dd79c1a2ab3355a7d7a0197fcacff973a001a2.tar.gz |
aes-gcm: Adapt AES-GCM to build for EC
Update header, C code, trim unnecessary bits.
Also add a test with vectors taken from BoringSSL tests.
BRANCH=none
BUG=b:111160949
TEST=make run-aes -j
TEST=make BOARD=nocturne_fp test-aes -j
flash_fp_mcu aes.bin
runtest => pass
(C implementation speed: 909555 us for 1000 iterations)
(ASM implementation speed: 596690 us for 1000 iterations)
Change-Id: Ief54a8441d26ba44de4c3ac81e203cab7472269f
Signed-off-by: Nicolas Boichat <drinkcat@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1141446
Commit-Ready: Nicolas Norvez <norvez@chromium.org>
Reviewed-by: Nicolas Norvez <norvez@chromium.org>
Diffstat (limited to 'third_party')
-rw-r--r-- | third_party/boringssl/common/aes-gcm.c | 274 | ||||
-rw-r--r-- | third_party/boringssl/core/cortex-m/ghash.S | 17 | ||||
-rw-r--r-- | third_party/boringssl/include/aes-gcm.h | 96 |
3 files changed, 57 insertions, 330 deletions
diff --git a/third_party/boringssl/common/aes-gcm.c b/third_party/boringssl/common/aes-gcm.c index 99d0e15e83..c9fa359aac 100644 --- a/third_party/boringssl/common/aes-gcm.c +++ b/third_party/boringssl/common/aes-gcm.c @@ -46,24 +46,41 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== */ -#include <openssl/base.h> +#include "aes-gcm.h" +#include "common.h" +#include "endian.h" +#include "util.h" -#include <assert.h> -#include <string.h> +#define STRICT_ALIGNMENT 1 -#include <openssl/mem.h> -#include <openssl/cpu.h> +#define OPENSSL_memcpy memcpy +#define OPENSSL_memset memset +#define CRYPTO_memcmp safe_memcmp -#include "internal.h" -#include "../../internal.h" - -#if !defined(OPENSSL_NO_ASM) && \ - (defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \ - defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64) || \ - defined(OPENSSL_PPC64LE)) +#ifdef CORE_CORTEX_M #define GHASH_ASM +#define OPENSSL_ARM +#define __ARM_ARCH__ 7 #endif +static inline uint32_t CRYPTO_bswap4(uint32_t x) { + return __builtin_bswap32(x); +} + +static inline uint64_t CRYPTO_bswap8(uint64_t x) { + return __builtin_bswap64(x); +} + +static inline size_t load_word_le(const void *in) { + size_t v; + OPENSSL_memcpy(&v, in, sizeof(v)); + return v; +} + +static inline void store_word_le(void *out, size_t v) { + OPENSSL_memcpy(out, &v, sizeof(v)); +} + #define PACK(s) ((size_t)(s) << (sizeof(size_t) * 8 - 16)) #define REDUCE1BIT(V) \ do { \ @@ -283,13 +300,12 @@ void gcm_ghash_4bit_mmx(uint64_t Xi[2], const u128 Htable[16], const uint8_t *in #endif #elif defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64) -#include <openssl/arm_arch.h> #if __ARM_ARCH__ >= 7 #define GHASH_ASM_ARM #define GCM_FUNCREF_4BIT static int pmull_capable(void) { - return CRYPTO_is_ARMv8_PMULL_capable(); + return 0; } void gcm_init_v8(u128 Htable[16], const uint64_t Xi[2]); @@ -297,7 +313,7 @@ void gcm_gmult_v8(uint64_t Xi[2], const u128 Htable[16]); void gcm_ghash_v8(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp, size_t len); -#if defined(OPENSSL_ARM) +#if defined(OPENSSL_ARM_NEON) // 32-bit ARM also has support for doing GCM with NEON instructions. static int neon_capable(void) { return CRYPTO_is_NEON_capable(); @@ -313,14 +329,14 @@ static int neon_capable(void) { return 0; } static void gcm_init_neon(u128 Htable[16], const uint64_t Xi[2]) { - abort(); + } static void gcm_gmult_neon(uint64_t Xi[2], const u128 Htable[16]) { - abort(); + } static void gcm_ghash_neon(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp, size_t len) { - abort(); + } #endif @@ -344,11 +360,9 @@ void gcm_ghash_p8(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp, #endif #endif -void CRYPTO_ghash_init(gmult_func *out_mult, ghash_func *out_hash, - u128 *out_key, u128 out_table[16], - int *out_is_avx, - const uint8_t *gcm_key) { - *out_is_avx = 0; +static void CRYPTO_ghash_init(gmult_func *out_mult, ghash_func *out_hash, + u128 *out_key, u128 out_table[16], + const uint8_t *gcm_key) { union { uint64_t u[2]; @@ -426,11 +440,8 @@ void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx, const void *aes_key, OPENSSL_memset(gcm_key, 0, sizeof(gcm_key)); (*block)(gcm_key, gcm_key, aes_key); - int is_avx; - CRYPTO_ghash_init(&ctx->gmult, &ctx->ghash, &ctx->H, ctx->Htable, &is_avx, + CRYPTO_ghash_init(&ctx->gmult, &ctx->ghash, &ctx->H, ctx->Htable, gcm_key); - - ctx->use_aesni_gcm_crypt = (is_avx && block_is_hwaes) ? 1 : 0; } void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx, const void *key, @@ -807,215 +818,6 @@ int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx, const void *key, return 1; } -int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx, const void *key, - const uint8_t *in, uint8_t *out, size_t len, - ctr128_f stream) { - unsigned int n, ctr; - uint64_t mlen = ctx->len.u[1]; -#ifdef GCM_FUNCREF_4BIT - void (*gcm_gmult_p)(uint64_t Xi[2], const u128 Htable[16]) = ctx->gmult; -#ifdef GHASH - void (*gcm_ghash_p)(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp, - size_t len) = ctx->ghash; -#endif -#endif - - mlen += len; - if (mlen > ((UINT64_C(1) << 36) - 32) || - (sizeof(len) == 8 && mlen < len)) { - return 0; - } - ctx->len.u[1] = mlen; - - if (ctx->ares) { - // First call to encrypt finalizes GHASH(AAD) - GCM_MUL(ctx, Xi); - ctx->ares = 0; - } - - n = ctx->mres; - if (n) { - while (n && len) { - ctx->Xi.c[n] ^= *(out++) = *(in++) ^ ctx->EKi.c[n]; - --len; - n = (n + 1) % 16; - } - if (n == 0) { - GCM_MUL(ctx, Xi); - } else { - ctx->mres = n; - return 1; - } - } - -#if defined(AESNI_GCM) - if (ctx->use_aesni_gcm_crypt) { - // |aesni_gcm_encrypt| may not process all the input given to it. It may - // not process *any* of its input if it is deemed too small. - size_t bulk = aesni_gcm_encrypt(in, out, len, key, ctx->Yi.c, ctx->Xi.u); - in += bulk; - out += bulk; - len -= bulk; - } -#endif - - ctr = CRYPTO_bswap4(ctx->Yi.d[3]); - -#if defined(GHASH) - while (len >= GHASH_CHUNK) { - (*stream)(in, out, GHASH_CHUNK / 16, key, ctx->Yi.c); - ctr += GHASH_CHUNK / 16; - ctx->Yi.d[3] = CRYPTO_bswap4(ctr); - GHASH(ctx, out, GHASH_CHUNK); - out += GHASH_CHUNK; - in += GHASH_CHUNK; - len -= GHASH_CHUNK; - } -#endif - size_t i = len & kSizeTWithoutLower4Bits; - if (i != 0) { - size_t j = i / 16; - - (*stream)(in, out, j, key, ctx->Yi.c); - ctr += (unsigned int)j; - ctx->Yi.d[3] = CRYPTO_bswap4(ctr); - in += i; - len -= i; -#if defined(GHASH) - GHASH(ctx, out, i); - out += i; -#else - while (j--) { - for (i = 0; i < 16; ++i) { - ctx->Xi.c[i] ^= out[i]; - } - GCM_MUL(ctx, Xi); - out += 16; - } -#endif - } - if (len) { - (*ctx->block)(ctx->Yi.c, ctx->EKi.c, key); - ++ctr; - ctx->Yi.d[3] = CRYPTO_bswap4(ctr); - while (len--) { - ctx->Xi.c[n] ^= out[n] = in[n] ^ ctx->EKi.c[n]; - ++n; - } - } - - ctx->mres = n; - return 1; -} - -int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx, const void *key, - const uint8_t *in, uint8_t *out, size_t len, - ctr128_f stream) { - unsigned int n, ctr; - uint64_t mlen = ctx->len.u[1]; -#ifdef GCM_FUNCREF_4BIT - void (*gcm_gmult_p)(uint64_t Xi[2], const u128 Htable[16]) = ctx->gmult; -#ifdef GHASH - void (*gcm_ghash_p)(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp, - size_t len) = ctx->ghash; -#endif -#endif - - mlen += len; - if (mlen > ((UINT64_C(1) << 36) - 32) || - (sizeof(len) == 8 && mlen < len)) { - return 0; - } - ctx->len.u[1] = mlen; - - if (ctx->ares) { - // First call to decrypt finalizes GHASH(AAD) - GCM_MUL(ctx, Xi); - ctx->ares = 0; - } - - n = ctx->mres; - if (n) { - while (n && len) { - uint8_t c = *(in++); - *(out++) = c ^ ctx->EKi.c[n]; - ctx->Xi.c[n] ^= c; - --len; - n = (n + 1) % 16; - } - if (n == 0) { - GCM_MUL(ctx, Xi); - } else { - ctx->mres = n; - return 1; - } - } - -#if defined(AESNI_GCM) - if (ctx->use_aesni_gcm_crypt) { - // |aesni_gcm_decrypt| may not process all the input given to it. It may - // not process *any* of its input if it is deemed too small. - size_t bulk = aesni_gcm_decrypt(in, out, len, key, ctx->Yi.c, ctx->Xi.u); - in += bulk; - out += bulk; - len -= bulk; - } -#endif - - ctr = CRYPTO_bswap4(ctx->Yi.d[3]); - -#if defined(GHASH) - while (len >= GHASH_CHUNK) { - GHASH(ctx, in, GHASH_CHUNK); - (*stream)(in, out, GHASH_CHUNK / 16, key, ctx->Yi.c); - ctr += GHASH_CHUNK / 16; - ctx->Yi.d[3] = CRYPTO_bswap4(ctr); - out += GHASH_CHUNK; - in += GHASH_CHUNK; - len -= GHASH_CHUNK; - } -#endif - size_t i = len & kSizeTWithoutLower4Bits; - if (i != 0) { - size_t j = i / 16; - -#if defined(GHASH) - GHASH(ctx, in, i); -#else - while (j--) { - size_t k; - for (k = 0; k < 16; ++k) { - ctx->Xi.c[k] ^= in[k]; - } - GCM_MUL(ctx, Xi); - in += 16; - } - j = i / 16; - in -= i; -#endif - (*stream)(in, out, j, key, ctx->Yi.c); - ctr += (unsigned int)j; - ctx->Yi.d[3] = CRYPTO_bswap4(ctr); - out += i; - in += i; - len -= i; - } - if (len) { - (*ctx->block)(ctx->Yi.c, ctx->EKi.c, key); - ++ctr; - ctx->Yi.d[3] = CRYPTO_bswap4(ctr); - while (len--) { - uint8_t c = in[n]; - ctx->Xi.c[n] ^= c; - out[n] = c ^ ctx->EKi.c[n]; - ++n; - } - } - - ctx->mres = n; - return 1; -} - int CRYPTO_gcm128_finish(GCM128_CONTEXT *ctx, const uint8_t *tag, size_t len) { uint64_t alen = ctx->len.u[0] << 3; uint64_t clen = ctx->len.u[1] << 3; diff --git a/third_party/boringssl/core/cortex-m/ghash.S b/third_party/boringssl/core/cortex-m/ghash.S index fafcb5c23b..a1eb97b9c5 100644 --- a/third_party/boringssl/core/cortex-m/ghash.S +++ b/third_party/boringssl/core/cortex-m/ghash.S @@ -8,12 +8,7 @@ @ in the file LICENSE in the source distribution or at @ https://www.openssl.org/source/license.html -#include <openssl/arm_arch.h> - -@ Silence ARMv8 deprecated IT instruction warnings. This file is used by both -@ ARMv7 and ARMv8 processors and does not use ARMv8 instructions. (ARMv8 PMULL -@ instructions are in aesv8-armx.pl.) -.arch armv7-a +#define __ARM_ARCH__ 7 .text #if defined(__thumb2__) || defined(__clang__) @@ -111,7 +106,7 @@ gcm_ghash_4bit: #ifdef __thumb2__ it pl #endif - ldrplb r12,[r2,r3] + ldrbpl r12,[r2,r3] eor r6,r6,r7,lsl#28 eor r7,r11,r7,lsr#4 @@ -124,7 +119,7 @@ gcm_ghash_4bit: #ifdef __thumb2__ it pl #endif - ldrplb r8,[r0,r3] + ldrbpl r8,[r0,r3] eor r4,r4,r5,lsl#28 eor r5,r9,r5,lsr#4 ldrh r9,[sp,r14] @@ -180,7 +175,7 @@ gcm_ghash_4bit: #ifdef __thumb2__ it ne #endif - ldrneb r12,[r2,#15] + ldrbne r12,[r2,#15] #if __ARM_ARCH__>=7 && defined(__ARMEL__) rev r6,r6 str r6,[r0,#4] @@ -270,7 +265,7 @@ gcm_gmult_4bit: #ifdef __thumb2__ it pl #endif - ldrplb r12,[r0,r3] + ldrbpl r12,[r0,r3] eor r6,r6,r7,lsl#28 eor r7,r11,r7,lsr#4 @@ -363,7 +358,7 @@ gcm_gmult_4bit: .word 0xe12fff1e @ interoperable with Thumb ISA:-) #endif .size gcm_gmult_4bit,.-gcm_gmult_4bit -#if __ARM_MAX_ARCH__>=7 +#ifdef __ARM_NEON__ .arch armv7-a .fpu neon diff --git a/third_party/boringssl/include/aes-gcm.h b/third_party/boringssl/include/aes-gcm.h index b2941fb317..e3ef457224 100644 --- a/third_party/boringssl/include/aes-gcm.h +++ b/third_party/boringssl/include/aes-gcm.h @@ -46,46 +46,12 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== */ -#ifndef OPENSSL_HEADER_MODES_INTERNAL_H -#define OPENSSL_HEADER_MODES_INTERNAL_H +#ifndef __CROS_EC_AES_GCM_H +#define __CROS_EC_AES_GCM_H -#include <openssl/base.h> - -#include <string.h> - -#include "../../internal.h" - -#if defined(__cplusplus) -extern "C" { -#endif - - -#define STRICT_ALIGNMENT 1 -#if defined(OPENSSL_X86_64) || defined(OPENSSL_X86) || defined(OPENSSL_AARCH64) -#undef STRICT_ALIGNMENT -#define STRICT_ALIGNMENT 0 -#endif - -static inline uint32_t GETU32(const void *in) { - uint32_t v; - OPENSSL_memcpy(&v, in, sizeof(v)); - return CRYPTO_bswap4(v); -} - -static inline void PUTU32(void *out, uint32_t v) { - v = CRYPTO_bswap4(v); - OPENSSL_memcpy(out, &v, sizeof(v)); -} - -static inline size_t load_word_le(const void *in) { - size_t v; - OPENSSL_memcpy(&v, in, sizeof(v)); - return v; -} - -static inline void store_word_le(void *out, size_t v) { - OPENSSL_memcpy(out, &v, sizeof(v)); -} +#include "common.h" +#include "endian.h" +#include "util.h" // block128_f is the type of a 128-bit, block cipher. typedef void (*block128_f)(const uint8_t in[16], uint8_t out[16], @@ -125,10 +91,6 @@ struct gcm128_context { unsigned int mres, ares; block128_f block; - - // use_aesni_gcm_crypt is true if this context should use the assembly - // functions |aesni_gcm_encrypt| and |aesni_gcm_decrypt| to process data. - unsigned use_aesni_gcm_crypt:1; }; @@ -141,77 +103,45 @@ struct gcm128_context { typedef struct gcm128_context GCM128_CONTEXT; -// CRYPTO_ghash_init writes a precomputed table of powers of |gcm_key| to -// |out_table| and sets |*out_mult| and |*out_hash| to (potentially hardware -// accelerated) functions for performing operations in the GHASH field. If the -// AVX implementation was used |*out_is_avx| will be true. -void CRYPTO_ghash_init(gmult_func *out_mult, ghash_func *out_hash, - u128 *out_key, u128 out_table[16], int *out_is_avx, - const uint8_t *gcm_key); - // CRYPTO_gcm128_init initialises |ctx| to use |block| (typically AES) with // the given key. |block_is_hwaes| is one if |block| is |aes_hw_encrypt|. -OPENSSL_EXPORT void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx, const void *key, +void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx, const void *key, block128_f block, int block_is_hwaes); // CRYPTO_gcm128_setiv sets the IV (nonce) for |ctx|. The |key| must be the // same key that was passed to |CRYPTO_gcm128_init|. -OPENSSL_EXPORT void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx, const void *key, +void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx, const void *key, const uint8_t *iv, size_t iv_len); // CRYPTO_gcm128_aad sets the authenticated data for an instance of GCM. // This must be called before and data is encrypted. It returns one on success // and zero otherwise. -OPENSSL_EXPORT int CRYPTO_gcm128_aad(GCM128_CONTEXT *ctx, const uint8_t *aad, +int CRYPTO_gcm128_aad(GCM128_CONTEXT *ctx, const uint8_t *aad, size_t len); // CRYPTO_gcm128_encrypt encrypts |len| bytes from |in| to |out|. The |key| // must be the same key that was passed to |CRYPTO_gcm128_init|. It returns one // on success and zero otherwise. -OPENSSL_EXPORT int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx, const void *key, +int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx, const void *key, const uint8_t *in, uint8_t *out, size_t len); // CRYPTO_gcm128_decrypt decrypts |len| bytes from |in| to |out|. The |key| // must be the same key that was passed to |CRYPTO_gcm128_init|. It returns one // on success and zero otherwise. -OPENSSL_EXPORT int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx, const void *key, +int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx, const void *key, const uint8_t *in, uint8_t *out, size_t len); -// CRYPTO_gcm128_encrypt_ctr32 encrypts |len| bytes from |in| to |out| using -// a CTR function that only handles the bottom 32 bits of the nonce, like -// |CRYPTO_ctr128_encrypt_ctr32|. The |key| must be the same key that was -// passed to |CRYPTO_gcm128_init|. It returns one on success and zero -// otherwise. -OPENSSL_EXPORT int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx, - const void *key, - const uint8_t *in, uint8_t *out, - size_t len, ctr128_f stream); - -// CRYPTO_gcm128_decrypt_ctr32 decrypts |len| bytes from |in| to |out| using -// a CTR function that only handles the bottom 32 bits of the nonce, like -// |CRYPTO_ctr128_encrypt_ctr32|. The |key| must be the same key that was -// passed to |CRYPTO_gcm128_init|. It returns one on success and zero -// otherwise. -OPENSSL_EXPORT int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx, - const void *key, - const uint8_t *in, uint8_t *out, - size_t len, ctr128_f stream); - // CRYPTO_gcm128_finish calculates the authenticator and compares it against // |len| bytes of |tag|. It returns one on success and zero otherwise. -OPENSSL_EXPORT int CRYPTO_gcm128_finish(GCM128_CONTEXT *ctx, const uint8_t *tag, +int CRYPTO_gcm128_finish(GCM128_CONTEXT *ctx, const uint8_t *tag, size_t len); // CRYPTO_gcm128_tag calculates the authenticator and copies it into |tag|. // The minimum of |len| and 16 bytes are copied into |tag|. -OPENSSL_EXPORT void CRYPTO_gcm128_tag(GCM128_CONTEXT *ctx, uint8_t *tag, +void CRYPTO_gcm128_tag(GCM128_CONTEXT *ctx, uint8_t *tag, size_t len); -#if defined(__cplusplus) -} // extern C -#endif - -#endif // OPENSSL_HEADER_MODES_INTERNAL_H +#endif // __CROS_EC_AES_GCM_H |