// SPDX-License-Identifier: Apache-2.0 or CC0-1.0 #include #include #include "aes.h" #ifdef PROFILE_HASHING #include "hal.h" extern unsigned long long hash_cycles; #endif extern void aes128_keyschedule_ffs(uint32_t* rkeys, const uint8_t* key); extern void aes256_keyschedule_ffs(uint32_t* rkeys, const uint8_t* key); extern void aes256_encrypt_ffs(uint8_t* ctext, uint8_t* ctext_bis, const uint8_t* ptext, const uint8_t* ptext_bis, const uint32_t* rkey); extern void aes128_encrypt_ffs(uint8_t* ctext, uint8_t* ctext_bis, const uint8_t* ptext, const uint8_t* ptext_bis, const uint32_t* rkey); static inline uint32_t br_swap32(uint32_t x) { x = ((x & (uint32_t)0x00FF00FF) << 8) | ((x >> 8) & (uint32_t)0x00FF00FF); return (x << 16) | (x >> 16); } static inline void inc1_be(uint32_t *x) { uint32_t t = br_swap32(*x) + 1; *x = br_swap32(t); } static inline void inc2_be(uint32_t *x) { uint32_t t = br_swap32(*x) + 2; *x = br_swap32(t); } void aes128_ecb_keyexp(aes128ctx *r, const unsigned char *key){ #ifdef PROFILE_HASHING uint64_t t0 = hal_get_time(); #endif aes128_keyschedule_ffs(r->sk_exp, key); #ifdef PROFILE_HASHING uint64_t t1 = hal_get_time(); hash_cycles += (t1-t0); #endif } void aes128_ecb(unsigned char *out, const unsigned char *in, size_t nblocks, const aes128ctx *ctx){ #ifdef PROFILE_HASHING uint64_t t0 = hal_get_time(); #endif uint8_t buf0[AES_BLOCKBYTES], buf1[AES_BLOCKBYTES]; while(nblocks > 0){ if(nblocks >= 2){ aes128_encrypt_ffs(out, out+AES_BLOCKBYTES, in, in+AES_BLOCKBYTES, ctx->sk_exp); out += AES_BLOCKBYTES*2; in += AES_BLOCKBYTES*2; nblocks -= 2; } else { aes128_encrypt_ffs(out, buf0, in, buf1, ctx->sk_exp); nblocks--; } } #ifdef PROFILE_HASHING uint64_t t1 = hal_get_time(); hash_cycles += (t1-t0); #endif } void aes128_ctr_keyexp(aes128ctx *r, const unsigned char *key){ #ifdef PROFILE_HASHING uint64_t t0 = hal_get_time(); #endif aes128_keyschedule_ffs(r->sk_exp, key); #ifdef PROFILE_HASHING uint64_t t1 = hal_get_time(); hash_cycles += (t1-t0); #endif } void aes128_ctr(unsigned char *out, size_t outlen, const unsigned char *iv, const aes128ctx *ctx){ #ifdef PROFILE_HASHING uint64_t t0 = hal_get_time(); #endif uint32_t ivw1[4] = {0}; uint32_t ivw2[4] = {0}; uint8_t buf1[AES_BLOCKBYTES]; uint8_t buf2[AES_BLOCKBYTES]; size_t i; memcpy(ivw1, iv, AESCTR_NONCEBYTES); memcpy(ivw2, iv, AESCTR_NONCEBYTES); inc1_be(ivw2 + 3); while (outlen > 2*AES_BLOCKBYTES) { aes128_encrypt_ffs(out, out+16, (uint8_t *)ivw1, (uint8_t *)ivw2, ctx->sk_exp); inc2_be(ivw1 + 3); inc2_be(ivw2 + 3); out += AES_BLOCKBYTES*2; outlen -= AES_BLOCKBYTES*2; } if (outlen >= AES_BLOCKBYTES) { aes128_encrypt_ffs(out, buf2, (uint8_t *)ivw1, (uint8_t *)ivw2, ctx->sk_exp); out += AES_BLOCKBYTES; outlen -= AES_BLOCKBYTES; for (i = 0; i < outlen; i++) { out[i] = buf2[i]; } } else if (outlen > 0) { aes128_encrypt_ffs(buf1, buf2, (uint8_t *)ivw1, (uint8_t *)ivw2, ctx->sk_exp); for (i = 0; i < outlen; i++) { out[i] = buf1[i]; } } #ifdef PROFILE_HASHING uint64_t t1 = hal_get_time(); hash_cycles += (t1-t0); #endif } void aes128_ctx_release(aes128ctx *r){ (void) r; } void aes256_ecb_keyexp(aes256ctx *r, const unsigned char *key){ #ifdef PROFILE_HASHING uint64_t t0 = hal_get_time(); #endif aes256_keyschedule_ffs(r->sk_exp, key); #ifdef PROFILE_HASHING uint64_t t1 = hal_get_time(); hash_cycles += (t1-t0); #endif } void aes256_ecb(unsigned char *out, const unsigned char *in, size_t nblocks, const aes256ctx *ctx){ #ifdef PROFILE_HASHING uint64_t t0 = hal_get_time(); #endif uint8_t buf0[AES_BLOCKBYTES], buf1[AES_BLOCKBYTES]; while(nblocks > 0){ if(nblocks >= 2){ aes256_encrypt_ffs(out, out+AES_BLOCKBYTES, in, in+AES_BLOCKBYTES, ctx->sk_exp); out += 2*AES_BLOCKBYTES; in += 2*AES_BLOCKBYTES; nblocks -= 2; } else { aes256_encrypt_ffs(out, buf0, in, buf1, ctx->sk_exp); nblocks--; } } #ifdef PROFILE_HASHING uint64_t t1 = hal_get_time(); hash_cycles += (t1-t0); #endif } void aes256_ctr_keyexp(aes256ctx *r, const unsigned char *key){ #ifdef PROFILE_HASHING uint64_t t0 = hal_get_time(); #endif aes256_keyschedule_ffs(r->sk_exp, key); #ifdef PROFILE_HASHING uint64_t t1 = hal_get_time(); hash_cycles += (t1-t0); #endif } void aes256_ctr(unsigned char *out, size_t outlen, const unsigned char *iv, const aes256ctx *ctx){ #ifdef PROFILE_HASHING uint64_t t0 = hal_get_time(); #endif uint32_t ivw1[4] = {0}; uint32_t ivw2[4] = {0}; uint8_t buf1[AES_BLOCKBYTES]; uint8_t buf2[AES_BLOCKBYTES]; size_t i; memcpy(ivw1, iv, AESCTR_NONCEBYTES); memcpy(ivw2, iv, AESCTR_NONCEBYTES); inc1_be(ivw2 + 3); while (outlen > 2*AES_BLOCKBYTES) { aes256_encrypt_ffs(out, out+AES_BLOCKBYTES, (uint8_t *)ivw1, (uint8_t *)ivw2, ctx->sk_exp); inc2_be(ivw1 + 3); inc2_be(ivw2 + 3); out += AES_BLOCKBYTES*2; outlen -= AES_BLOCKBYTES*2; } if (outlen >= AES_BLOCKBYTES) { aes256_encrypt_ffs(out, buf2, (uint8_t *)ivw1, (uint8_t *)ivw2, ctx->sk_exp); out += AES_BLOCKBYTES; outlen -= AES_BLOCKBYTES; for (i = 0; i < outlen; i++) { out[i] = buf2[i]; } } else if (outlen > 0) { aes256_encrypt_ffs(buf1, buf2, (uint8_t *)ivw1, (uint8_t *)ivw2, ctx->sk_exp); for (i = 0; i < outlen; i++) { out[i] = buf1[i]; } } #ifdef PROFILE_HASHING uint64_t t1 = hal_get_time(); hash_cycles += (t1-t0); #endif } void aes256_ctx_release(aes256ctx *r){ (void) r; }