summaryrefslogtreecommitdiff
path: root/core/lib/libtomcrypt/src/ciphers/aes_armv8a_ce.c
diff options
context:
space:
mode:
Diffstat (limited to 'core/lib/libtomcrypt/src/ciphers/aes_armv8a_ce.c')
-rw-r--r--core/lib/libtomcrypt/src/ciphers/aes_armv8a_ce.c393
1 files changed, 393 insertions, 0 deletions
diff --git a/core/lib/libtomcrypt/src/ciphers/aes_armv8a_ce.c b/core/lib/libtomcrypt/src/ciphers/aes_armv8a_ce.c
new file mode 100644
index 0000000..dc2a6f0
--- /dev/null
+++ b/core/lib/libtomcrypt/src/ciphers/aes_armv8a_ce.c
@@ -0,0 +1,393 @@
+/*
+ * Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ * Copyright (c) 2001-2007, Tom St Denis
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS 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 COPYRIGHT HOLDER OR 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.
+ */
+
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+/*
+ * AES cipher for ARMv8 with Crypto Extensions
+ *
+ * Copyright (C) 2013 Linaro Ltd <ard.biesheuvel@linaro.org>
+ */
+
+#include "tomcrypt.h"
+#include "tomcrypt_arm_neon.h"
+
+typedef unsigned int u32;
+typedef unsigned char u8;
+
+/* Prototypes for assembly functions */
+uint32_t ce_aes_sub(uint32_t in);
+void ce_aes_invert(void *dst, void *src);
+void ce_aes_ecb_encrypt(u8 out[], u8 const in[], u8 const rk[], int rounds,
+ int blocks, int first);
+void ce_aes_ecb_decrypt(u8 out[], u8 const in[], u8 const rk[], int rounds,
+ int blocks, int first);
+void ce_aes_cbc_encrypt(u8 out[], u8 const in[], u8 const rk[], int rounds,
+ int blocks, u8 iv[], int first);
+void ce_aes_cbc_decrypt(u8 out[], u8 const in[], u8 const rk[], int rounds,
+ int blocks, u8 iv[], int first);
+void ce_aes_ctr_encrypt(u8 out[], u8 const in[], u8 const rk[], int rounds,
+ int blocks, u8 ctr[], int first);
+void ce_aes_xts_encrypt(u8 out[], u8 const in[], u8 const rk1[], int rounds,
+ int blocks, u8 const rk2[], u8 iv[]);
+void ce_aes_xts_decrypt(u8 out[], u8 const in[], u8 const rk1[], int rounds,
+ int blocks, u8 const rk2[], u8 iv[]);
+
+
+struct aes_block {
+ u8 b[16];
+};
+
+static inline u32 ror32(u32 val, u32 shift)
+{
+ return (val >> shift) | (val << (32 - shift));
+}
+
+int rijndael_setup(const unsigned char *key, int keylen, int num_rounds,
+ symmetric_key *skey)
+{
+ /* The AES key schedule round constants */
+ static u8 const rcon[] = {
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36,
+ };
+ u32 kwords = keylen / sizeof(u32);
+ struct aes_block *key_enc, *key_dec;
+ struct tomcrypt_arm_neon_state state;
+ unsigned int i, j;
+ void *p;
+
+ LTC_ARGCHK(key);
+ LTC_ARGCHK(skey);
+
+ if (keylen != 16 && keylen != 24 && keylen != 32)
+ return CRYPT_INVALID_KEYSIZE;
+
+ if (num_rounds != 0 && num_rounds != (10 + ((keylen/8)-2)*2))
+ return CRYPT_INVALID_ROUNDS;
+
+ num_rounds = 10 + ((keylen/8)-2)*2;
+ skey->rijndael.Nr = num_rounds;
+
+ memcpy(skey->rijndael.eK, key, keylen);
+
+ tomcrypt_arm_neon_enable(&state);
+
+ for (i = 0; i < sizeof(rcon); i++) {
+ u32 *rki;
+ u32 *rko;
+
+ p = skey->rijndael.eK;
+ rki = (u32 *)p + (i * kwords);
+ rko = rki + kwords;
+
+ rko[0] = ror32(ce_aes_sub(rki[kwords - 1]), 8)
+ ^ rcon[i] ^ rki[0];
+ rko[1] = rko[0] ^ rki[1];
+ rko[2] = rko[1] ^ rki[2];
+ rko[3] = rko[2] ^ rki[3];
+
+ if (keylen == 24) {
+ if (i >= 7)
+ break;
+ rko[4] = rko[3] ^ rki[4];
+ rko[5] = rko[4] ^ rki[5];
+ } else if (keylen == 32) {
+ if (i >= 6)
+ break;
+ rko[4] = ce_aes_sub(rko[3]) ^ rki[4];
+ rko[5] = rko[4] ^ rki[5];
+ rko[6] = rko[5] ^ rki[6];
+ rko[7] = rko[6] ^ rki[7];
+ }
+ }
+
+ /*
+ * Generate the decryption keys for the Equivalent Inverse Cipher.
+ * This involves reversing the order of the round keys, and applying
+ * the Inverse Mix Columns transformation on all but the first and
+ * the last one.
+ */
+ p = skey->rijndael.eK;
+ key_enc = (struct aes_block *)p;
+ p = skey->rijndael.dK;
+ key_dec = (struct aes_block *)p;
+ j = num_rounds;
+
+ key_dec[0] = key_enc[j];
+ for (i = 1, j--; j > 0; i++, j--)
+ ce_aes_invert(key_dec + i, key_enc + j);
+ key_dec[i] = key_enc[0];
+
+ tomcrypt_arm_neon_disable(&state);
+
+ return CRYPT_OK;
+}
+
+void rijndael_done(symmetric_key *skey)
+{
+}
+
+int rijndael_keysize(int *keysize)
+{
+ LTC_ARGCHK(keysize);
+
+ if (*keysize < 16)
+ return CRYPT_INVALID_KEYSIZE;
+ else if (*keysize < 24)
+ *keysize = 16;
+ else if (*keysize < 32)
+ *keysize = 24;
+ else
+ *keysize = 32;
+
+ return CRYPT_OK;
+}
+
+static int aes_ecb_encrypt_nblocks(const unsigned char *pt, unsigned char *ct,
+ unsigned long blocks, symmetric_key *skey)
+{
+ struct tomcrypt_arm_neon_state state;
+ u8 *rk;
+ int Nr;
+
+ LTC_ARGCHK(pt);
+ LTC_ARGCHK(ct);
+ LTC_ARGCHK(skey);
+
+ Nr = skey->rijndael.Nr;
+ rk = (u8 *)skey->rijndael.eK;
+
+ tomcrypt_arm_neon_enable(&state);
+ ce_aes_ecb_encrypt(ct, pt, rk, Nr, blocks, 1);
+ tomcrypt_arm_neon_disable(&state);
+
+ return CRYPT_OK;
+}
+
+static int aes_ecb_decrypt_nblocks(const unsigned char *ct, unsigned char *pt,
+ unsigned long blocks, symmetric_key *skey)
+{
+ struct tomcrypt_arm_neon_state state;
+ u8 *rk;
+ int Nr;
+
+ LTC_ARGCHK(pt);
+ LTC_ARGCHK(ct);
+ LTC_ARGCHK(skey);
+
+ Nr = skey->rijndael.Nr;
+ rk = (u8 *)skey->rijndael.dK;
+
+ tomcrypt_arm_neon_enable(&state);
+ ce_aes_ecb_decrypt(pt, ct, rk, Nr, blocks, 1);
+ tomcrypt_arm_neon_disable(&state);
+
+ return CRYPT_OK;
+}
+
+int rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct,
+ symmetric_key *skey)
+{
+ return aes_ecb_encrypt_nblocks(pt, ct, 1, skey);
+}
+
+int rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt,
+ symmetric_key *skey)
+{
+ return aes_ecb_decrypt_nblocks(ct, pt, 1, skey);
+}
+
+static int aes_cbc_encrypt_nblocks(const unsigned char *pt, unsigned char *ct,
+ unsigned long blocks, unsigned char *IV,
+ symmetric_key *skey)
+{
+ struct tomcrypt_arm_neon_state state;
+ u8 *rk;
+ int Nr;
+
+ LTC_ARGCHK(pt);
+ LTC_ARGCHK(ct);
+ LTC_ARGCHK(IV);
+ LTC_ARGCHK(skey);
+
+ Nr = skey->rijndael.Nr;
+ rk = (u8 *)skey->rijndael.eK;
+
+ tomcrypt_arm_neon_enable(&state);
+ ce_aes_cbc_encrypt(ct, pt, rk, Nr, blocks, IV, 1);
+ tomcrypt_arm_neon_disable(&state);
+
+ return CRYPT_OK;
+}
+
+static int aes_cbc_decrypt_nblocks(const unsigned char *ct, unsigned char *pt,
+ unsigned long blocks, unsigned char *IV,
+ symmetric_key *skey)
+{
+ struct tomcrypt_arm_neon_state state;
+ u8 *rk;
+ int Nr;
+
+ LTC_ARGCHK(pt);
+ LTC_ARGCHK(ct);
+ LTC_ARGCHK(IV);
+ LTC_ARGCHK(skey);
+
+ Nr = skey->rijndael.Nr;
+ rk = (u8 *)skey->rijndael.dK;
+
+ tomcrypt_arm_neon_enable(&state);
+ ce_aes_cbc_decrypt(pt, ct, rk, Nr, blocks, IV, 1);
+ tomcrypt_arm_neon_disable(&state);
+
+ return CRYPT_OK;
+}
+
+/* Increment 128-bit counter */
+static void increment_ctr(unsigned char *val)
+{
+ int i;
+
+ for (i = 15; i >= 0; i--) {
+ val[i] = (val[i] + 1) & 0xff;
+ if (val[i])
+ break;
+ }
+}
+
+static int aes_ctr_encrypt_nblocks(const unsigned char *pt, unsigned char *ct,
+ unsigned long blocks, unsigned char *IV,
+ int mode, symmetric_key *skey)
+{
+ struct tomcrypt_arm_neon_state state;
+ u8 *rk;
+ int Nr;
+
+ LTC_ARGCHK(pt);
+ LTC_ARGCHK(ct);
+ LTC_ARGCHK(IV);
+ LTC_ARGCHK(skey);
+
+ if (mode == CTR_COUNTER_LITTLE_ENDIAN) {
+ /* Accelerated algorithm supports big endian only */
+ return CRYPT_ERROR;
+ }
+
+ Nr = skey->rijndael.Nr;
+ rk = (u8 *)skey->rijndael.eK;
+
+ increment_ctr(IV);
+ tomcrypt_arm_neon_enable(&state);
+ ce_aes_ctr_encrypt(ct, pt, rk, Nr, blocks, IV, 1);
+ tomcrypt_arm_neon_disable(&state);
+
+ return CRYPT_OK;
+}
+
+static int aes_xts_encrypt_nblocks(const unsigned char *pt, unsigned char *ct,
+ unsigned long blocks, unsigned char *tweak,
+ symmetric_key *skey1, symmetric_key *skey2)
+{
+ struct tomcrypt_arm_neon_state state;
+ u8 *rk1, *rk2;
+ int Nr;
+
+ LTC_ARGCHK(pt);
+ LTC_ARGCHK(ct);
+ LTC_ARGCHK(tweak);
+ LTC_ARGCHK(skey1);
+ LTC_ARGCHK(skey2);
+ LTC_ARGCHK(skey1->rijndael.Nr == skey2->rijndael.Nr);
+
+ Nr = skey1->rijndael.Nr;
+ rk1 = (u8 *)skey1->rijndael.eK;
+ rk2 = (u8 *)skey2->rijndael.eK;
+
+ tomcrypt_arm_neon_enable(&state);
+ ce_aes_xts_encrypt(ct, pt, rk1, Nr, blocks, rk2, tweak);
+ tomcrypt_arm_neon_disable(&state);
+
+ return CRYPT_OK;
+}
+
+static int aes_xts_decrypt_nblocks(const unsigned char *ct, unsigned char *pt,
+ unsigned long blocks, unsigned char *tweak,
+ symmetric_key *skey1, symmetric_key *skey2)
+{
+ struct tomcrypt_arm_neon_state state;
+ u8 *rk1, *rk2;
+ int Nr;
+
+ LTC_ARGCHK(pt);
+ LTC_ARGCHK(ct);
+ LTC_ARGCHK(tweak);
+ LTC_ARGCHK(skey1);
+ LTC_ARGCHK(skey2);
+ LTC_ARGCHK(skey1->rijndael.Nr == skey2->rijndael.Nr);
+
+ Nr = skey1->rijndael.Nr;
+ rk1 = (u8 *)skey1->rijndael.dK;
+ rk2 = (u8 *)skey2->rijndael.eK;
+
+ tomcrypt_arm_neon_enable(&state);
+ ce_aes_xts_decrypt(pt, ct, rk1, Nr, blocks, rk2, tweak);
+ tomcrypt_arm_neon_disable(&state);
+
+ return CRYPT_OK;
+}
+
+const struct ltc_cipher_descriptor aes_desc = {
+ .name = "aes",
+ .ID = 6,
+ .min_key_length = 16,
+ .max_key_length = 32,
+ .block_length = 16,
+ .default_rounds = 10,
+ .setup = rijndael_setup,
+ .ecb_encrypt = rijndael_ecb_encrypt,
+ .ecb_decrypt = rijndael_ecb_decrypt,
+ .done = rijndael_done,
+ .keysize = rijndael_keysize,
+ .accel_ecb_encrypt = aes_ecb_encrypt_nblocks,
+ .accel_ecb_decrypt = aes_ecb_decrypt_nblocks,
+ .accel_cbc_encrypt = aes_cbc_encrypt_nblocks,
+ .accel_cbc_decrypt = aes_cbc_decrypt_nblocks,
+ .accel_ctr_encrypt = aes_ctr_encrypt_nblocks,
+ .accel_xts_encrypt = aes_xts_encrypt_nblocks,
+ .accel_xts_decrypt = aes_xts_decrypt_nblocks,
+};