/* * AES implementation based on code from BearSSL (https://bearssl.org/) * by Thomas Pornin. * * * Copyright (c) 2016 Thomas Pornin * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include #include "aes-publicinputs.h" #ifdef PROFILE_HASHING #include "hal.h" extern unsigned long long hash_cycles; #endif extern void aes128_keyexp_publicinputs_asm(const uint8_t *key, uint8_t *rk); extern void aes192_keyexp_publicinputs_asm(const uint8_t *key, uint8_t *rk); extern void aes256_keyexp_publicinputs_asm(const uint8_t *key, uint8_t *rk); extern void aes128_encrypt_publicinputs_asm(const uint8_t *rk, const uint8_t *in, uint8_t *out); extern void aes192_encrypt_publicinputs_asm(const uint8_t *rk, const uint8_t *in, uint8_t *out); extern void aes256_encrypt_publicinputs_asm(const uint8_t *rk, const uint8_t *in, uint8_t *out); 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 void aes_ecb(unsigned char *out, const unsigned char *in, size_t nblocks, const uint64_t *rkeys, void (*aes_encrypt_asm)(const uint8_t *, const uint8_t *, uint8_t *)) { unsigned int i; for (i = 0; i < nblocks; ++i) { aes_encrypt_asm((uint8_t *)rkeys, in, out); in += AES_BLOCKBYTES; out += AES_BLOCKBYTES; } } static void aes_ctr(unsigned char *out, size_t outlen, const unsigned char *iv, const uint64_t *rkeys, void (*aes_encrypt_asm)(const uint8_t *, const uint8_t *, uint8_t *)) { uint32_t ivw[4] = {0}; uint8_t buf[AES_BLOCKBYTES]; size_t i; memcpy(ivw, iv, AESCTR_NONCEBYTES); while (outlen > AES_BLOCKBYTES) { aes_encrypt_asm((uint8_t *)rkeys, (uint8_t *)ivw, out); inc1_be(ivw + 3); out += AES_BLOCKBYTES; outlen -= AES_BLOCKBYTES; } if (outlen > 0) { aes_encrypt_asm((unsigned char *)rkeys, (unsigned char *)ivw, buf); for (i = 0; i < outlen; i++) { out[i] = buf[i]; } } } static void aes128_keyexp_publicinputs(aes128ctx_publicinputs *r, const unsigned char *key) { #ifdef PROFILE_HASHING uint64_t t0 = hal_get_time(); #endif memcpy((uint8_t *)r->sk_exp, key, AES128_KEYBYTES); aes128_keyexp_publicinputs_asm(key, ((uint8_t *)r->sk_exp) + AES128_KEYBYTES); #ifdef PROFILE_HASHING uint64_t t1 = hal_get_time(); hash_cycles += (t1-t0); #endif } void aes128_ecb_keyexp_publicinputs(aes128ctx_publicinputs *r, const unsigned char *key) { aes128_keyexp_publicinputs(r, key); } void aes128_ctr_keyexp_publicinputs(aes128ctx_publicinputs *r, const unsigned char *key) { aes128_keyexp_publicinputs(r, key); } static void aes192_keyexp_publicinputs(aes192ctx_publicinputs *r, const unsigned char *key) { #ifdef PROFILE_HASHING uint64_t t0 = hal_get_time(); #endif memcpy((uint8_t *)r->sk_exp, key, AES192_KEYBYTES); aes192_keyexp_publicinputs_asm(key, ((uint8_t *)r->sk_exp) + AES192_KEYBYTES); #ifdef PROFILE_HASHING uint64_t t1 = hal_get_time(); hash_cycles += (t1-t0); #endif } void aes192_ecb_keyexp_publicinputs(aes192ctx_publicinputs *r, const unsigned char *key) { aes192_keyexp_publicinputs(r, key); } void aes192_ctr_keyexp_publicinputs(aes192ctx_publicinputs *r, const unsigned char *key) { aes192_keyexp_publicinputs(r, key); } static void aes256_keyexp_publicinputs(aes256ctx_publicinputs *r, const unsigned char *key) { #ifdef PROFILE_HASHING uint64_t t0 = hal_get_time(); #endif memcpy((uint8_t *)r->sk_exp, key, AES256_KEYBYTES); aes256_keyexp_publicinputs_asm(key, ((uint8_t *)r->sk_exp) + AES256_KEYBYTES); #ifdef PROFILE_HASHING uint64_t t1 = hal_get_time(); hash_cycles += (t1-t0); #endif } void aes256_ecb_keyexp_publicinputs(aes256ctx_publicinputs *r, const unsigned char *key) { aes256_keyexp_publicinputs(r, key); } void aes256_ctr_keyexp_publicinputs(aes256ctx_publicinputs *r, const unsigned char *key) { aes256_keyexp_publicinputs(r, key); } void aes128_ecb_publicinputs(unsigned char *out, const unsigned char *in, size_t nblocks, const aes128ctx_publicinputs *ctx) { #ifdef PROFILE_HASHING uint64_t t0 = hal_get_time(); #endif aes_ecb(out, in, nblocks, ctx->sk_exp, aes128_encrypt_publicinputs_asm); #ifdef PROFILE_HASHING uint64_t t1 = hal_get_time(); hash_cycles += (t1-t0); #endif } void aes128_ctr_publicinputs(unsigned char *out, size_t outlen, const unsigned char *iv, const aes128ctx_publicinputs *ctx) { #ifdef PROFILE_HASHING uint64_t t0 = hal_get_time(); #endif aes_ctr(out, outlen, iv, ctx->sk_exp, aes128_encrypt_publicinputs_asm); #ifdef PROFILE_HASHING uint64_t t1 = hal_get_time(); hash_cycles += (t1-t0); #endif } void aes192_ecb_publicinputs(unsigned char *out, const unsigned char *in, size_t nblocks, const aes192ctx_publicinputs *ctx) { #ifdef PROFILE_HASHING uint64_t t0 = hal_get_time(); #endif aes_ecb(out, in, nblocks, ctx->sk_exp, aes192_encrypt_publicinputs_asm); #ifdef PROFILE_HASHING uint64_t t1 = hal_get_time(); hash_cycles += (t1-t0); #endif } void aes192_ctr_publicinputs(unsigned char *out, size_t outlen, const unsigned char *iv, const aes192ctx_publicinputs *ctx) { #ifdef PROFILE_HASHING uint64_t t0 = hal_get_time(); #endif aes_ctr(out, outlen, iv, ctx->sk_exp, aes192_encrypt_publicinputs_asm); #ifdef PROFILE_HASHING uint64_t t1 = hal_get_time(); hash_cycles += (t1-t0); #endif } void aes256_ecb_publicinputs(unsigned char *out, const unsigned char *in, size_t nblocks, const aes256ctx_publicinputs *ctx) { #ifdef PROFILE_HASHING uint64_t t0 = hal_get_time(); #endif aes_ecb(out, in, nblocks, ctx->sk_exp, aes256_encrypt_publicinputs_asm); #ifdef PROFILE_HASHING uint64_t t1 = hal_get_time(); hash_cycles += (t1-t0); #endif } void aes256_ctr_publicinputs(unsigned char *out, size_t outlen, const unsigned char *iv, const aes256ctx_publicinputs *ctx) { #ifdef PROFILE_HASHING uint64_t t0 = hal_get_time(); #endif aes_ctr(out, outlen, iv, ctx->sk_exp, aes256_encrypt_publicinputs_asm); #ifdef PROFILE_HASHING uint64_t t1 = hal_get_time(); hash_cycles += (t1-t0); #endif } void aes128_ctx_release_publicinputs(aes128ctx_publicinputs *r) { // no-op for mupq's basic AES operation // this is required for compatibility with code from PQClean // see https://github.com/PQClean/PQClean/pull/198 (void) r; } void aes192_ctx_release_publicinputs(aes192ctx_publicinputs *r) { // no-op for mupq's basic AES operation // this is required for compatibility with code from PQClean // see https://github.com/PQClean/PQClean/pull/198 (void) r; } void aes256_ctx_release_publicinputs(aes256ctx_publicinputs *r) { // no-op for mupq's basic AES operation // this is required for compatibility with code from PQClean // see https://github.com/PQClean/PQClean/pull/198 (void) r; }