├── COPYING ├── README.md ├── ctaes.h ├── bench.c ├── test.c └── ctaes.c /COPYING: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Pieter Wuille 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ctaes 2 | ===== 3 | 4 | Simple C module for constant-time AES encryption and decryption. 5 | 6 | Features: 7 | * Simple, pure C code without any dependencies. 8 | * No tables or data-dependent branches whatsoever, but using bit sliced approach from https://eprint.iacr.org/2009/129.pdf. 9 | * Very small object code: slightly over 4k of executable code when compiled with -Os. 10 | * Slower than implementations based on precomputed tables or specialized instructions, but can do ~15 MB/s on modern CPUs. 11 | 12 | Performance 13 | ----------- 14 | 15 | Compiled with GCC 5.3.1 with -O3, on an Intel(R) Core(TM) i7-4800MQ CPU, numbers in CPU cycles: 16 | 17 | | Algorithm | Key schedule | Encryption per byte | Decryption per byte | 18 | | --------- | ------------:| -------------------:| -------------------:| 19 | | AES-128 | 2.8k | 154 | 161 | 20 | | AES-192 | 3.1k | 169 | 181 | 21 | | AES-256 | 4.0k | 191 | 203 | 22 | 23 | Build steps 24 | ----------- 25 | 26 | Object code: 27 | 28 | $ gcc -O3 ctaes.c -c -o ctaes.o 29 | 30 | Tests: 31 | 32 | $ gcc -O3 ctaes.c test.c -o test 33 | 34 | Benchmark: 35 | 36 | $ gcc -O3 ctaes.c bench.c -o bench 37 | 38 | Review 39 | ------ 40 | 41 | Results of a formal review of the code can be found in http://bitcoin.sipa.be/ctaes/review.zip 42 | -------------------------------------------------------------------------------- /ctaes.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * Copyright (c) 2016 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://opensource.org/licenses/mit-license.php. * 5 | **********************************************************************/ 6 | 7 | #ifndef CTAES_H 8 | #define CTAES_H 9 | 10 | #include 11 | #include 12 | 13 | typedef struct { 14 | uint16_t slice[8]; 15 | } AES_state; 16 | 17 | typedef struct { 18 | AES_state rk[11]; 19 | } AES128_ctx; 20 | 21 | typedef struct { 22 | AES_state rk[13]; 23 | } AES192_ctx; 24 | 25 | typedef struct { 26 | AES_state rk[15]; 27 | } AES256_ctx; 28 | 29 | typedef struct { 30 | AES128_ctx ctx; 31 | uint8_t iv[16]; /* iv is updated after each use */ 32 | } AES128_CBC_ctx; 33 | 34 | typedef struct { 35 | AES192_ctx ctx; 36 | uint8_t iv[16]; /* iv is updated after each use */ 37 | } AES192_CBC_ctx; 38 | 39 | typedef struct { 40 | AES256_ctx ctx; 41 | uint8_t iv[16]; /* iv is updated after each use */ 42 | } AES256_CBC_ctx; 43 | 44 | void AES128_init(AES128_ctx* ctx, const unsigned char* key16); 45 | void AES128_encrypt(const AES128_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16); 46 | void AES128_decrypt(const AES128_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16); 47 | 48 | void AES192_init(AES192_ctx* ctx, const unsigned char* key24); 49 | void AES192_encrypt(const AES192_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16); 50 | void AES192_decrypt(const AES192_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16); 51 | 52 | void AES256_init(AES256_ctx* ctx, const unsigned char* key32); 53 | void AES256_encrypt(const AES256_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16); 54 | void AES256_decrypt(const AES256_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16); 55 | 56 | void AES128_CBC_init(AES128_CBC_ctx* ctx, const unsigned char* key16, const uint8_t* iv); 57 | void AES128_CBC_encrypt(AES128_CBC_ctx* ctx, size_t blocks, unsigned char* encrypted, const unsigned char* plain); 58 | void AES128_CBC_decrypt(AES128_CBC_ctx* ctx, size_t blocks, unsigned char* plain, const unsigned char *encrypted); 59 | 60 | void AES192_CBC_init(AES192_CBC_ctx* ctx, const unsigned char* key16, const uint8_t* iv); 61 | void AES192_CBC_encrypt(AES192_CBC_ctx* ctx, size_t blocks, unsigned char* encrypted, const unsigned char* plain); 62 | void AES192_CBC_decrypt(AES192_CBC_ctx* ctx, size_t blocks, unsigned char* plain, const unsigned char *encrypted); 63 | 64 | void AES256_CBC_init(AES256_CBC_ctx* ctx, const unsigned char* key16, const uint8_t* iv); 65 | void AES256_CBC_encrypt(AES256_CBC_ctx* ctx, size_t blocks, unsigned char* encrypted, const unsigned char* plain); 66 | void AES256_CBC_decrypt(AES256_CBC_ctx* ctx, size_t blocks, unsigned char* plain, const unsigned char *encrypted); 67 | 68 | #endif /* CTAES_H */ 69 | -------------------------------------------------------------------------------- /bench.c: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * Copyright (c) 2016 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://opensource.org/licenses/mit-license.php. * 5 | **********************************************************************/ 6 | #include 7 | #include 8 | #include "sys/time.h" 9 | 10 | #include "ctaes.h" 11 | 12 | static double gettimedouble(void) { 13 | struct timeval tv; 14 | gettimeofday(&tv, NULL); 15 | return tv.tv_usec * 0.000001 + tv.tv_sec; 16 | } 17 | 18 | static void print_number(double x) { 19 | double y = x; 20 | int c = 0; 21 | if (y < 0.0) { 22 | y = -y; 23 | } 24 | while (0.0 < y && y < 100.0) { 25 | y *= 10.0; 26 | c++; 27 | } 28 | printf("%.*f", c, x); 29 | } 30 | 31 | static void run_benchmark(char *name, void (*benchmark)(void*), void (*setup)(void*), void (*teardown)(void*), void* data, int count, int iter) { 32 | int i; 33 | double min = HUGE_VAL; 34 | double sum = 0.0; 35 | double max = 0.0; 36 | for (i = 0; i < count; i++) { 37 | double begin, total; 38 | if (setup != NULL) { 39 | setup(data); 40 | } 41 | begin = gettimedouble(); 42 | benchmark(data); 43 | total = gettimedouble() - begin; 44 | if (teardown != NULL) { 45 | teardown(data); 46 | } 47 | if (total < min) { 48 | min = total; 49 | } 50 | if (total > max) { 51 | max = total; 52 | } 53 | sum += total; 54 | } 55 | printf("%s: min ", name); 56 | print_number(min * 1000000000.0 / iter); 57 | printf("ns / avg "); 58 | print_number((sum / count) * 1000000000.0 / iter); 59 | printf("ns / max "); 60 | print_number(max * 1000000000.0 / iter); 61 | printf("ns\n"); 62 | } 63 | 64 | static void bench_AES128_init(void* data) { 65 | AES128_ctx* ctx = (AES128_ctx*)data; 66 | int i; 67 | for (i = 0; i < 50000; i++) { 68 | AES128_init(ctx, (unsigned char*)ctx); 69 | } 70 | } 71 | 72 | static void bench_AES128_encrypt_setup(void* data) { 73 | AES128_ctx* ctx = (AES128_ctx*)data; 74 | static const unsigned char key[16] = {0}; 75 | AES128_init(ctx, key); 76 | } 77 | 78 | static void bench_AES128_encrypt(void* data) { 79 | const AES128_ctx* ctx = (const AES128_ctx*)data; 80 | unsigned char scratch[16] = {0}; 81 | int i; 82 | for (i = 0; i < 4000000 / 16; i++) { 83 | AES128_encrypt(ctx, 1, scratch, scratch); 84 | } 85 | } 86 | 87 | static void bench_AES128_decrypt(void* data) { 88 | const AES128_ctx* ctx = (const AES128_ctx*)data; 89 | unsigned char scratch[16] = {0}; 90 | int i; 91 | for (i = 0; i < 4000000 / 16; i++) { 92 | AES128_decrypt(ctx, 1, scratch, scratch); 93 | } 94 | } 95 | 96 | static void bench_AES192_init(void* data) { 97 | AES192_ctx* ctx = (AES192_ctx*)data; 98 | int i; 99 | for (i = 0; i < 50000; i++) { 100 | AES192_init(ctx, (unsigned char*)ctx); 101 | } 102 | } 103 | 104 | static void bench_AES192_encrypt_setup(void* data) { 105 | AES192_ctx* ctx = (AES192_ctx*)data; 106 | static const unsigned char key[24] = {0}; 107 | AES192_init(ctx, key); 108 | } 109 | 110 | static void bench_AES192_encrypt(void* data) { 111 | const AES192_ctx* ctx = (const AES192_ctx*)data; 112 | unsigned char scratch[16] = {0}; 113 | int i; 114 | for (i = 0; i < 4000000 / 16; i++) { 115 | AES192_encrypt(ctx, 1, scratch, scratch); 116 | } 117 | } 118 | 119 | static void bench_AES192_decrypt(void* data) { 120 | const AES192_ctx* ctx = (const AES192_ctx*)data; 121 | unsigned char scratch[16] = {0}; 122 | int i; 123 | for (i = 0; i < 4000000 / 16; i++) { 124 | AES192_decrypt(ctx, 1, scratch, scratch); 125 | } 126 | } 127 | 128 | static void bench_AES256_init(void* data) { 129 | AES256_ctx* ctx = (AES256_ctx*)data; 130 | int i; 131 | for (i = 0; i < 50000; i++) { 132 | AES256_init(ctx, (unsigned char*)ctx); 133 | } 134 | } 135 | 136 | 137 | static void bench_AES256_encrypt_setup(void* data) { 138 | AES256_ctx* ctx = (AES256_ctx*)data; 139 | static const unsigned char key[32] = {0}; 140 | AES256_init(ctx, key); 141 | } 142 | 143 | static void bench_AES256_encrypt(void* data) { 144 | const AES256_ctx* ctx = (const AES256_ctx*)data; 145 | unsigned char scratch[16] = {0}; 146 | int i; 147 | for (i = 0; i < 4000000 / 16; i++) { 148 | AES256_encrypt(ctx, 1, scratch, scratch); 149 | } 150 | } 151 | 152 | static void bench_AES256_decrypt(void* data) { 153 | const AES256_ctx* ctx = (const AES256_ctx*)data; 154 | unsigned char scratch[16] = {0}; 155 | int i; 156 | for (i = 0; i < 4000000 / 16; i++) { 157 | AES256_decrypt(ctx, 1, scratch, scratch); 158 | } 159 | } 160 | 161 | int main(void) { 162 | AES128_ctx ctx128; 163 | AES192_ctx ctx192; 164 | AES256_ctx ctx256; 165 | run_benchmark("aes128_init", bench_AES128_init, NULL, NULL, &ctx128, 20, 50000); 166 | run_benchmark("aes128_encrypt_byte", bench_AES128_encrypt, bench_AES128_encrypt_setup, NULL, &ctx128, 20, 4000000); 167 | run_benchmark("aes128_decrypt_byte", bench_AES128_decrypt, bench_AES128_encrypt_setup, NULL, &ctx128, 20, 4000000); 168 | run_benchmark("aes192_init", bench_AES192_init, NULL, NULL, &ctx192, 20, 50000); 169 | run_benchmark("aes192_encrypt_byte", bench_AES192_encrypt, bench_AES192_encrypt_setup, NULL, &ctx192, 20, 4000000); 170 | run_benchmark("aes192_decrypt_byte", bench_AES192_decrypt, bench_AES192_encrypt_setup, NULL, &ctx192, 20, 4000000); 171 | run_benchmark("aes256_init", bench_AES256_init, NULL, NULL, &ctx256, 20, 50000); 172 | run_benchmark("aes256_encrypt_byte", bench_AES256_encrypt, bench_AES256_encrypt_setup, NULL, &ctx256, 20, 4000000); 173 | run_benchmark("aes256_decrypt_byte", bench_AES256_decrypt, bench_AES256_encrypt_setup, NULL, &ctx256, 20, 4000000); 174 | return 0; 175 | } 176 | -------------------------------------------------------------------------------- /test.c: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * Copyright (c) 2016 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://opensource.org/licenses/mit-license.php. * 5 | **********************************************************************/ 6 | 7 | #include "ctaes.h" 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | typedef struct { 14 | int keysize; 15 | const char* key; 16 | const char* plain; 17 | const char* cipher; 18 | } ctaes_test; 19 | 20 | typedef struct { 21 | int keysize; 22 | const char* key; 23 | const char* iv; 24 | int nblocks; 25 | const char* plain; 26 | const char* cipher; 27 | } ctaes_cbc_test; 28 | 29 | static const ctaes_test ctaes_tests[] = { 30 | /* AES test vectors from FIPS 197. */ 31 | {128, "000102030405060708090a0b0c0d0e0f", "00112233445566778899aabbccddeeff", "69c4e0d86a7b0430d8cdb78070b4c55a"}, 32 | {192, "000102030405060708090a0b0c0d0e0f1011121314151617", "00112233445566778899aabbccddeeff", "dda97ca4864cdfe06eaf70a0ec0d7191"}, 33 | {256, "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "00112233445566778899aabbccddeeff", "8ea2b7ca516745bfeafc49904b496089"}, 34 | 35 | /* AES-ECB test vectors from NIST sp800-38a. */ 36 | {128, "2b7e151628aed2a6abf7158809cf4f3c", "6bc1bee22e409f96e93d7e117393172a", "3ad77bb40d7a3660a89ecaf32466ef97"}, 37 | {128, "2b7e151628aed2a6abf7158809cf4f3c", "ae2d8a571e03ac9c9eb76fac45af8e51", "f5d3d58503b9699de785895a96fdbaaf"}, 38 | {128, "2b7e151628aed2a6abf7158809cf4f3c", "30c81c46a35ce411e5fbc1191a0a52ef", "43b1cd7f598ece23881b00e3ed030688"}, 39 | {128, "2b7e151628aed2a6abf7158809cf4f3c", "f69f2445df4f9b17ad2b417be66c3710", "7b0c785e27e8ad3f8223207104725dd4"}, 40 | {192, "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", "6bc1bee22e409f96e93d7e117393172a", "bd334f1d6e45f25ff712a214571fa5cc"}, 41 | {192, "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", "ae2d8a571e03ac9c9eb76fac45af8e51", "974104846d0ad3ad7734ecb3ecee4eef"}, 42 | {192, "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", "30c81c46a35ce411e5fbc1191a0a52ef", "ef7afd2270e2e60adce0ba2face6444e"}, 43 | {192, "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", "f69f2445df4f9b17ad2b417be66c3710", "9a4b41ba738d6c72fb16691603c18e0e"}, 44 | {256, "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "6bc1bee22e409f96e93d7e117393172a", "f3eed1bdb5d2a03c064b5a7e3db181f8"}, 45 | {256, "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "ae2d8a571e03ac9c9eb76fac45af8e51", "591ccb10d410ed26dc5ba74a31362870"}, 46 | {256, "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "30c81c46a35ce411e5fbc1191a0a52ef", "b6ed21b99ca6f4f9f153e7b1beafed1d"}, 47 | {256, "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "f69f2445df4f9b17ad2b417be66c3710", "23304b7a39f9f3ff067d8d8f9e24ecc7"} 48 | }; 49 | 50 | static const ctaes_cbc_test ctaes_cbc_tests[] = { 51 | /* AES-CBC test vectors from NIST sp800-38a. */ 52 | { 53 | 128, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090a0b0c0d0e0f", 4, 54 | "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710", 55 | "7649abac8119b246cee98e9b12e9197d5086cb9b507219ee95db113a917678b273bed6b8e3c1743b7116e69e222295163ff1caa1681fac09120eca307586e1a7" 56 | }, 57 | { 58 | 192, "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", "000102030405060708090a0b0c0d0e0f", 4, 59 | "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710", 60 | "4f021db243bc633d7178183a9fa071e8b4d9ada9ad7dedf4e5e738763f69145a571b242012fb7ae07fa9baac3df102e008b0e27988598881d920a9e64f5615cd" 61 | }, 62 | { 63 | 256, "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "000102030405060708090a0b0c0d0e0f", 4, 64 | "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710", 65 | "f58c4c04d6e5f1ba779eabfb5f7bfbd69cfc4e967edb808d679f777bc6702c7d39f23369a9d9bacfa530e26304231461b2eb05e2c39be9fcda6c19078c6a9d1b" 66 | } 67 | }; 68 | 69 | static void from_hex(unsigned char* data, int len, const char* hex) { 70 | int p; 71 | for (p = 0; p < len; p++) { 72 | int v = 0; 73 | int n; 74 | for (n = 0; n < 2; n++) { 75 | assert((*hex >= '0' && *hex <= '9') || (*hex >= 'a' && *hex <= 'f')); 76 | if (*hex >= '0' && *hex <= '9') { 77 | v |= (*hex - '0') << (4 * (1 - n)); 78 | } else { 79 | v |= (*hex - 'a' + 10) << (4 * (1 - n)); 80 | } 81 | hex++; 82 | } 83 | *(data++) = v; 84 | } 85 | assert(*hex == 0); 86 | } 87 | 88 | int main(void) { 89 | int i; 90 | int fail = 0; 91 | for (i = 0; i < sizeof(ctaes_tests) / sizeof(ctaes_tests[0]); i++) { 92 | unsigned char key[32], plain[16], cipher[16], ciphered[16], deciphered[16]; 93 | const ctaes_test* test = &ctaes_tests[i]; 94 | assert(test->keysize == 128 || test->keysize == 192 || test->keysize == 256); 95 | from_hex(plain, 16, test->plain); 96 | from_hex(cipher, 16, test->cipher); 97 | switch (test->keysize) { 98 | case 128: { 99 | AES128_ctx ctx; 100 | from_hex(key, 16, test->key); 101 | AES128_init(&ctx, key); 102 | AES128_encrypt(&ctx, 1, ciphered, plain); 103 | AES128_decrypt(&ctx, 1, deciphered, cipher); 104 | break; 105 | } 106 | case 192: { 107 | AES192_ctx ctx; 108 | from_hex(key, 24, test->key); 109 | AES192_init(&ctx, key); 110 | AES192_encrypt(&ctx, 1, ciphered, plain); 111 | AES192_decrypt(&ctx, 1, deciphered, cipher); 112 | break; 113 | } 114 | case 256: { 115 | AES256_ctx ctx; 116 | from_hex(key, 32, test->key); 117 | AES256_init(&ctx, key); 118 | AES256_encrypt(&ctx, 1, ciphered, plain); 119 | AES256_decrypt(&ctx, 1, deciphered, cipher); 120 | break; 121 | } 122 | } 123 | if (memcmp(cipher, ciphered, 16)) { 124 | fprintf(stderr, "E(key=\"%s\", plain=\"%s\") != \"%s\"\n", test->key, test->plain, test->cipher); 125 | fail++; 126 | } 127 | if (memcmp(plain, deciphered, 16)) { 128 | fprintf(stderr, "D(key=\"%s\", cipher=\"%s\") != \"%s\"\n", test->key, test->cipher, test->plain); 129 | fail++; 130 | } 131 | } 132 | for (i = 0; i < sizeof(ctaes_cbc_tests) / sizeof(ctaes_cbc_tests[0]); i++) { 133 | const ctaes_cbc_test* test = &ctaes_cbc_tests[i]; 134 | unsigned char key[32], iv[16], plain[4 * 16], cipher[4 * 16], ciphered[4 * 16], deciphered[4 * 16]; 135 | assert(test->keysize == 128 || test->keysize == 192 || test->keysize == 256); 136 | assert(test->nblocks == 4); 137 | from_hex(iv, 16, test->iv); 138 | from_hex(plain, test->nblocks * 16, test->plain); 139 | from_hex(cipher, test->nblocks * 16, test->cipher); 140 | switch (test->keysize) { 141 | case 128: { 142 | AES128_CBC_ctx ctx; 143 | from_hex(key, 16, test->key); 144 | AES128_CBC_init(&ctx, key, iv); 145 | AES128_CBC_encrypt(&ctx, test->nblocks, ciphered, plain); 146 | AES128_CBC_init(&ctx, key, iv); 147 | AES128_CBC_decrypt(&ctx, test->nblocks, deciphered, cipher); 148 | break; 149 | } 150 | case 192: { 151 | AES192_CBC_ctx ctx; 152 | from_hex(key, 24, test->key); 153 | AES192_CBC_init(&ctx, key, iv); 154 | AES192_CBC_encrypt(&ctx, test->nblocks, ciphered, plain); 155 | AES192_CBC_init(&ctx, key, iv); 156 | AES192_CBC_decrypt(&ctx, test->nblocks, deciphered, cipher); 157 | break; 158 | } 159 | case 256: { 160 | AES256_CBC_ctx ctx; 161 | from_hex(key, 32, test->key); 162 | AES256_CBC_init(&ctx, key, iv); 163 | AES256_CBC_encrypt(&ctx, test->nblocks, ciphered, plain); 164 | AES256_CBC_init(&ctx, key, iv); 165 | AES256_CBC_decrypt(&ctx, test->nblocks, deciphered, cipher); 166 | break; 167 | } 168 | } 169 | if (memcmp(cipher, ciphered, test->nblocks * 16)) { 170 | fprintf(stderr, "E(key=\"%s\", plain=\"%s\") != \"%s\"\n", test->key, test->plain, test->cipher); 171 | fail++; 172 | } 173 | if (memcmp(plain, deciphered, test->nblocks * 16)) { 174 | fprintf(stderr, "D(key=\"%s\", cipher=\"%s\") != \"%s\"\n", test->key, test->cipher, test->plain); 175 | fail++; 176 | } 177 | } 178 | if (fail == 0) { 179 | fprintf(stderr, "All tests successful\n"); 180 | } else { 181 | fprintf(stderr, "%i tests failed\n", fail); 182 | } 183 | return (fail != 0); 184 | } 185 | -------------------------------------------------------------------------------- /ctaes.c: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * Copyright (c) 2016 Pieter Wuille * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file COPYING or https://opensource.org/licenses/mit-license.php. * 5 | **********************************************************************/ 6 | 7 | /* Constant time, unoptimized, concise, plain C, AES implementation 8 | * Based On: 9 | * Emilia Kasper and Peter Schwabe, Faster and Timing-Attack Resistant AES-GCM 10 | * https://www.iacr.org/archive/ches2009/57470001/57470001.pdf 11 | * But using 8 16-bit integers representing a single AES state rather than 8 128-bit 12 | * integers representing 8 AES states. 13 | */ 14 | 15 | #include "ctaes.h" 16 | 17 | #include 18 | 19 | /* Slice variable slice_i contains the i'th bit of the 16 state variables in this order: 20 | * 0 1 2 3 21 | * 4 5 6 7 22 | * 8 9 10 11 23 | * 12 13 14 15 24 | */ 25 | 26 | /** Convert a byte to sliced form, storing it corresponding to given row and column in s */ 27 | static void LoadByte(AES_state* s, unsigned char byte, int r, int c) { 28 | int i; 29 | for (i = 0; i < 8; i++) { 30 | s->slice[i] |= (uint16_t)(byte & 1) << (r * 4 + c); 31 | byte >>= 1; 32 | } 33 | } 34 | 35 | /** Load 16 bytes of data into 8 sliced integers */ 36 | static void LoadBytes(AES_state *s, const unsigned char* data16) { 37 | int c; 38 | for (c = 0; c < 4; c++) { 39 | int r; 40 | for (r = 0; r < 4; r++) { 41 | LoadByte(s, *(data16++), r, c); 42 | } 43 | } 44 | } 45 | 46 | /** Convert 8 sliced integers into 16 bytes of data */ 47 | static void SaveBytes(unsigned char* data16, const AES_state *s) { 48 | int c; 49 | for (c = 0; c < 4; c++) { 50 | int r; 51 | for (r = 0; r < 4; r++) { 52 | int b; 53 | uint8_t v = 0; 54 | for (b = 0; b < 8; b++) { 55 | v |= ((s->slice[b] >> (r * 4 + c)) & 1) << b; 56 | } 57 | *(data16++) = v; 58 | } 59 | } 60 | } 61 | 62 | /* S-box implementation based on the gate logic from: 63 | * Joan Boyar and Rene Peralta, A depth-16 circuit for the AES S-box. 64 | * https://eprint.iacr.org/2011/332.pdf 65 | */ 66 | static void SubBytes(AES_state *s, int inv) { 67 | /* Load the bit slices */ 68 | uint16_t U0 = s->slice[7], U1 = s->slice[6], U2 = s->slice[5], U3 = s->slice[4]; 69 | uint16_t U4 = s->slice[3], U5 = s->slice[2], U6 = s->slice[1], U7 = s->slice[0]; 70 | 71 | uint16_t T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16; 72 | uint16_t T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, D; 73 | uint16_t M1, M6, M11, M13, M15, M20, M21, M22, M23, M25, M37, M38, M39, M40; 74 | uint16_t M41, M42, M43, M44, M45, M46, M47, M48, M49, M50, M51, M52, M53, M54; 75 | uint16_t M55, M56, M57, M58, M59, M60, M61, M62, M63; 76 | 77 | if (inv) { 78 | uint16_t R5, R13, R17, R18, R19; 79 | /* Undo linear postprocessing */ 80 | T23 = U0 ^ U3; 81 | T22 = ~(U1 ^ U3); 82 | T2 = ~(U0 ^ U1); 83 | T1 = U3 ^ U4; 84 | T24 = ~(U4 ^ U7); 85 | R5 = U6 ^ U7; 86 | T8 = ~(U1 ^ T23); 87 | T19 = T22 ^ R5; 88 | T9 = ~(U7 ^ T1); 89 | T10 = T2 ^ T24; 90 | T13 = T2 ^ R5; 91 | T3 = T1 ^ R5; 92 | T25 = ~(U2 ^ T1); 93 | R13 = U1 ^ U6; 94 | T17 = ~(U2 ^ T19); 95 | T20 = T24 ^ R13; 96 | T4 = U4 ^ T8; 97 | R17 = ~(U2 ^ U5); 98 | R18 = ~(U5 ^ U6); 99 | R19 = ~(U2 ^ U4); 100 | D = U0 ^ R17; 101 | T6 = T22 ^ R17; 102 | T16 = R13 ^ R19; 103 | T27 = T1 ^ R18; 104 | T15 = T10 ^ T27; 105 | T14 = T10 ^ R18; 106 | T26 = T3 ^ T16; 107 | } else { 108 | /* Linear preprocessing. */ 109 | T1 = U0 ^ U3; 110 | T2 = U0 ^ U5; 111 | T3 = U0 ^ U6; 112 | T4 = U3 ^ U5; 113 | T5 = U4 ^ U6; 114 | T6 = T1 ^ T5; 115 | T7 = U1 ^ U2; 116 | T8 = U7 ^ T6; 117 | T9 = U7 ^ T7; 118 | T10 = T6 ^ T7; 119 | T11 = U1 ^ U5; 120 | T12 = U2 ^ U5; 121 | T13 = T3 ^ T4; 122 | T14 = T6 ^ T11; 123 | T15 = T5 ^ T11; 124 | T16 = T5 ^ T12; 125 | T17 = T9 ^ T16; 126 | T18 = U3 ^ U7; 127 | T19 = T7 ^ T18; 128 | T20 = T1 ^ T19; 129 | T21 = U6 ^ U7; 130 | T22 = T7 ^ T21; 131 | T23 = T2 ^ T22; 132 | T24 = T2 ^ T10; 133 | T25 = T20 ^ T17; 134 | T26 = T3 ^ T16; 135 | T27 = T1 ^ T12; 136 | D = U7; 137 | } 138 | 139 | /* Non-linear transformation (shared between the forward and backward case) */ 140 | M1 = T13 & T6; 141 | M6 = T3 & T16; 142 | M11 = T1 & T15; 143 | M13 = (T4 & T27) ^ M11; 144 | M15 = (T2 & T10) ^ M11; 145 | M20 = T14 ^ M1 ^ (T23 & T8) ^ M13; 146 | M21 = (T19 & D) ^ M1 ^ T24 ^ M15; 147 | M22 = T26 ^ M6 ^ (T22 & T9) ^ M13; 148 | M23 = (T20 & T17) ^ M6 ^ M15 ^ T25; 149 | M25 = M22 & M20; 150 | M37 = M21 ^ ((M20 ^ M21) & (M23 ^ M25)); 151 | M38 = M20 ^ M25 ^ (M21 | (M20 & M23)); 152 | M39 = M23 ^ ((M22 ^ M23) & (M21 ^ M25)); 153 | M40 = M22 ^ M25 ^ (M23 | (M21 & M22)); 154 | M41 = M38 ^ M40; 155 | M42 = M37 ^ M39; 156 | M43 = M37 ^ M38; 157 | M44 = M39 ^ M40; 158 | M45 = M42 ^ M41; 159 | M46 = M44 & T6; 160 | M47 = M40 & T8; 161 | M48 = M39 & D; 162 | M49 = M43 & T16; 163 | M50 = M38 & T9; 164 | M51 = M37 & T17; 165 | M52 = M42 & T15; 166 | M53 = M45 & T27; 167 | M54 = M41 & T10; 168 | M55 = M44 & T13; 169 | M56 = M40 & T23; 170 | M57 = M39 & T19; 171 | M58 = M43 & T3; 172 | M59 = M38 & T22; 173 | M60 = M37 & T20; 174 | M61 = M42 & T1; 175 | M62 = M45 & T4; 176 | M63 = M41 & T2; 177 | 178 | if (inv){ 179 | /* Undo linear preprocessing */ 180 | uint16_t P0 = M52 ^ M61; 181 | uint16_t P1 = M58 ^ M59; 182 | uint16_t P2 = M54 ^ M62; 183 | uint16_t P3 = M47 ^ M50; 184 | uint16_t P4 = M48 ^ M56; 185 | uint16_t P5 = M46 ^ M51; 186 | uint16_t P6 = M49 ^ M60; 187 | uint16_t P7 = P0 ^ P1; 188 | uint16_t P8 = M50 ^ M53; 189 | uint16_t P9 = M55 ^ M63; 190 | uint16_t P10 = M57 ^ P4; 191 | uint16_t P11 = P0 ^ P3; 192 | uint16_t P12 = M46 ^ M48; 193 | uint16_t P13 = M49 ^ M51; 194 | uint16_t P14 = M49 ^ M62; 195 | uint16_t P15 = M54 ^ M59; 196 | uint16_t P16 = M57 ^ M61; 197 | uint16_t P17 = M58 ^ P2; 198 | uint16_t P18 = M63 ^ P5; 199 | uint16_t P19 = P2 ^ P3; 200 | uint16_t P20 = P4 ^ P6; 201 | uint16_t P22 = P2 ^ P7; 202 | uint16_t P23 = P7 ^ P8; 203 | uint16_t P24 = P5 ^ P7; 204 | uint16_t P25 = P6 ^ P10; 205 | uint16_t P26 = P9 ^ P11; 206 | uint16_t P27 = P10 ^ P18; 207 | uint16_t P28 = P11 ^ P25; 208 | uint16_t P29 = P15 ^ P20; 209 | s->slice[7] = P13 ^ P22; 210 | s->slice[6] = P26 ^ P29; 211 | s->slice[5] = P17 ^ P28; 212 | s->slice[4] = P12 ^ P22; 213 | s->slice[3] = P23 ^ P27; 214 | s->slice[2] = P19 ^ P24; 215 | s->slice[1] = P14 ^ P23; 216 | s->slice[0] = P9 ^ P16; 217 | } else { 218 | /* Linear postprocessing */ 219 | uint16_t L0 = M61 ^ M62; 220 | uint16_t L1 = M50 ^ M56; 221 | uint16_t L2 = M46 ^ M48; 222 | uint16_t L3 = M47 ^ M55; 223 | uint16_t L4 = M54 ^ M58; 224 | uint16_t L5 = M49 ^ M61; 225 | uint16_t L6 = M62 ^ L5; 226 | uint16_t L7 = M46 ^ L3; 227 | uint16_t L8 = M51 ^ M59; 228 | uint16_t L9 = M52 ^ M53; 229 | uint16_t L10 = M53 ^ L4; 230 | uint16_t L11 = M60 ^ L2; 231 | uint16_t L12 = M48 ^ M51; 232 | uint16_t L13 = M50 ^ L0; 233 | uint16_t L14 = M52 ^ M61; 234 | uint16_t L15 = M55 ^ L1; 235 | uint16_t L16 = M56 ^ L0; 236 | uint16_t L17 = M57 ^ L1; 237 | uint16_t L18 = M58 ^ L8; 238 | uint16_t L19 = M63 ^ L4; 239 | uint16_t L20 = L0 ^ L1; 240 | uint16_t L21 = L1 ^ L7; 241 | uint16_t L22 = L3 ^ L12; 242 | uint16_t L23 = L18 ^ L2; 243 | uint16_t L24 = L15 ^ L9; 244 | uint16_t L25 = L6 ^ L10; 245 | uint16_t L26 = L7 ^ L9; 246 | uint16_t L27 = L8 ^ L10; 247 | uint16_t L28 = L11 ^ L14; 248 | uint16_t L29 = L11 ^ L17; 249 | s->slice[7] = L6 ^ L24; 250 | s->slice[6] = ~(L16 ^ L26); 251 | s->slice[5] = ~(L19 ^ L28); 252 | s->slice[4] = L6 ^ L21; 253 | s->slice[3] = L20 ^ L22; 254 | s->slice[2] = L25 ^ L29; 255 | s->slice[1] = ~(L13 ^ L27); 256 | s->slice[0] = ~(L6 ^ L23); 257 | } 258 | } 259 | 260 | #define BIT_RANGE(from,to) ((uint16_t)((1 << ((to) - (from))) - 1) << (from)) 261 | 262 | #define BIT_RANGE_LEFT(x,from,to,shift) (((x) & BIT_RANGE((from), (to))) << (shift)) 263 | #define BIT_RANGE_RIGHT(x,from,to,shift) (((x) & BIT_RANGE((from), (to))) >> (shift)) 264 | 265 | static void ShiftRows(AES_state* s) { 266 | int i; 267 | for (i = 0; i < 8; i++) { 268 | uint16_t v = s->slice[i]; 269 | s->slice[i] = 270 | (v & BIT_RANGE(0, 4)) | 271 | BIT_RANGE_LEFT(v, 4, 5, 3) | BIT_RANGE_RIGHT(v, 5, 8, 1) | 272 | BIT_RANGE_LEFT(v, 8, 10, 2) | BIT_RANGE_RIGHT(v, 10, 12, 2) | 273 | BIT_RANGE_LEFT(v, 12, 15, 1) | BIT_RANGE_RIGHT(v, 15, 16, 3); 274 | } 275 | } 276 | 277 | static void InvShiftRows(AES_state* s) { 278 | int i; 279 | for (i = 0; i < 8; i++) { 280 | uint16_t v = s->slice[i]; 281 | s->slice[i] = 282 | (v & BIT_RANGE(0, 4)) | 283 | BIT_RANGE_LEFT(v, 4, 7, 1) | BIT_RANGE_RIGHT(v, 7, 8, 3) | 284 | BIT_RANGE_LEFT(v, 8, 10, 2) | BIT_RANGE_RIGHT(v, 10, 12, 2) | 285 | BIT_RANGE_LEFT(v, 12, 13, 3) | BIT_RANGE_RIGHT(v, 13, 16, 1); 286 | } 287 | } 288 | 289 | #define ROT(x,b) (((x) >> ((b) * 4)) | ((x) << ((4-(b)) * 4))) 290 | 291 | static void MixColumns(AES_state* s, int inv) { 292 | /* The MixColumns transform treats the bytes of the columns of the state as 293 | * coefficients of a 3rd degree polynomial over GF(2^8) and multiplies them 294 | * by the fixed polynomial a(x) = {03}x^3 + {01}x^2 + {01}x + {02}, modulo 295 | * x^4 + {01}. 296 | * 297 | * In the inverse transform, we multiply by the inverse of a(x), 298 | * a^-1(x) = {0b}x^3 + {0d}x^2 + {09}x + {0e}. This is equal to 299 | * a(x) * ({04}x^2 + {05}), so we can reuse the forward transform's code 300 | * (found in OpenSSL's bsaes-x86_64.pl, attributed to Jussi Kivilinna) 301 | * 302 | * In the bitsliced representation, a multiplication of every column by x 303 | * mod x^4 + 1 is simply a right rotation. 304 | */ 305 | 306 | /* Shared for both directions is a multiplication by a(x), which can be 307 | * rewritten as (x^3 + x^2 + x) + {02}*(x^3 + {01}). 308 | * 309 | * First compute s into the s? variables, (x^3 + {01}) * s into the s?_01 310 | * variables and (x^3 + x^2 + x)*s into the s?_123 variables. 311 | */ 312 | uint16_t s0 = s->slice[0], s1 = s->slice[1], s2 = s->slice[2], s3 = s->slice[3]; 313 | uint16_t s4 = s->slice[4], s5 = s->slice[5], s6 = s->slice[6], s7 = s->slice[7]; 314 | uint16_t s0_01 = s0 ^ ROT(s0, 1), s0_123 = ROT(s0_01, 1) ^ ROT(s0, 3); 315 | uint16_t s1_01 = s1 ^ ROT(s1, 1), s1_123 = ROT(s1_01, 1) ^ ROT(s1, 3); 316 | uint16_t s2_01 = s2 ^ ROT(s2, 1), s2_123 = ROT(s2_01, 1) ^ ROT(s2, 3); 317 | uint16_t s3_01 = s3 ^ ROT(s3, 1), s3_123 = ROT(s3_01, 1) ^ ROT(s3, 3); 318 | uint16_t s4_01 = s4 ^ ROT(s4, 1), s4_123 = ROT(s4_01, 1) ^ ROT(s4, 3); 319 | uint16_t s5_01 = s5 ^ ROT(s5, 1), s5_123 = ROT(s5_01, 1) ^ ROT(s5, 3); 320 | uint16_t s6_01 = s6 ^ ROT(s6, 1), s6_123 = ROT(s6_01, 1) ^ ROT(s6, 3); 321 | uint16_t s7_01 = s7 ^ ROT(s7, 1), s7_123 = ROT(s7_01, 1) ^ ROT(s7, 3); 322 | /* Now compute s = s?_123 + {02} * s?_01. */ 323 | s->slice[0] = s7_01 ^ s0_123; 324 | s->slice[1] = s7_01 ^ s0_01 ^ s1_123; 325 | s->slice[2] = s1_01 ^ s2_123; 326 | s->slice[3] = s7_01 ^ s2_01 ^ s3_123; 327 | s->slice[4] = s7_01 ^ s3_01 ^ s4_123; 328 | s->slice[5] = s4_01 ^ s5_123; 329 | s->slice[6] = s5_01 ^ s6_123; 330 | s->slice[7] = s6_01 ^ s7_123; 331 | if (inv) { 332 | /* In the reverse direction, we further need to multiply by 333 | * {04}x^2 + {05}, which can be written as {04} * (x^2 + {01}) + {01}. 334 | * 335 | * First compute (x^2 + {01}) * s into the t?_02 variables: */ 336 | uint16_t t0_02 = s->slice[0] ^ ROT(s->slice[0], 2); 337 | uint16_t t1_02 = s->slice[1] ^ ROT(s->slice[1], 2); 338 | uint16_t t2_02 = s->slice[2] ^ ROT(s->slice[2], 2); 339 | uint16_t t3_02 = s->slice[3] ^ ROT(s->slice[3], 2); 340 | uint16_t t4_02 = s->slice[4] ^ ROT(s->slice[4], 2); 341 | uint16_t t5_02 = s->slice[5] ^ ROT(s->slice[5], 2); 342 | uint16_t t6_02 = s->slice[6] ^ ROT(s->slice[6], 2); 343 | uint16_t t7_02 = s->slice[7] ^ ROT(s->slice[7], 2); 344 | /* And then update s += {04} * t?_02 */ 345 | s->slice[0] ^= t6_02; 346 | s->slice[1] ^= t6_02 ^ t7_02; 347 | s->slice[2] ^= t0_02 ^ t7_02; 348 | s->slice[3] ^= t1_02 ^ t6_02; 349 | s->slice[4] ^= t2_02 ^ t6_02 ^ t7_02; 350 | s->slice[5] ^= t3_02 ^ t7_02; 351 | s->slice[6] ^= t4_02; 352 | s->slice[7] ^= t5_02; 353 | } 354 | } 355 | 356 | static void AddRoundKey(AES_state* s, const AES_state* round) { 357 | int b; 358 | for (b = 0; b < 8; b++) { 359 | s->slice[b] ^= round->slice[b]; 360 | } 361 | } 362 | 363 | /** column_0(s) = column_c(a) */ 364 | static void GetOneColumn(AES_state* s, const AES_state* a, int c) { 365 | int b; 366 | for (b = 0; b < 8; b++) { 367 | s->slice[b] = (a->slice[b] >> c) & 0x1111; 368 | } 369 | } 370 | 371 | /** column_c1(r) |= (column_0(s) ^= column_c2(a)) */ 372 | static void KeySetupColumnMix(AES_state* s, AES_state* r, const AES_state* a, int c1, int c2) { 373 | int b; 374 | for (b = 0; b < 8; b++) { 375 | r->slice[b] |= ((s->slice[b] ^= ((a->slice[b] >> c2) & 0x1111)) & 0x1111) << c1; 376 | } 377 | } 378 | 379 | /** Rotate the rows in s one position upwards, and xor in r */ 380 | static void KeySetupTransform(AES_state* s, const AES_state* r) { 381 | int b; 382 | for (b = 0; b < 8; b++) { 383 | s->slice[b] = ((s->slice[b] >> 4) | (s->slice[b] << 12)) ^ r->slice[b]; 384 | } 385 | } 386 | 387 | /* Multiply the cells in s by x, as polynomials over GF(2) mod x^8 + x^4 + x^3 + x + 1 */ 388 | static void MultX(AES_state* s) { 389 | uint16_t top = s->slice[7]; 390 | s->slice[7] = s->slice[6]; 391 | s->slice[6] = s->slice[5]; 392 | s->slice[5] = s->slice[4]; 393 | s->slice[4] = s->slice[3] ^ top; 394 | s->slice[3] = s->slice[2] ^ top; 395 | s->slice[2] = s->slice[1]; 396 | s->slice[1] = s->slice[0] ^ top; 397 | s->slice[0] = top; 398 | } 399 | 400 | /** Expand the cipher key into the key schedule. 401 | * 402 | * state must be a pointer to an array of size nrounds + 1. 403 | * key must be a pointer to 4 * nkeywords bytes. 404 | * 405 | * AES128 uses nkeywords = 4, nrounds = 10 406 | * AES192 uses nkeywords = 6, nrounds = 12 407 | * AES256 uses nkeywords = 8, nrounds = 14 408 | */ 409 | static void AES_setup(AES_state* rounds, const uint8_t* key, int nkeywords, int nrounds) 410 | { 411 | int i; 412 | 413 | /* The one-byte round constant */ 414 | AES_state rcon = {{1,0,0,0,0,0,0,0}}; 415 | /* The number of the word being generated, modulo nkeywords */ 416 | int pos = 0; 417 | /* The column representing the word currently being processed */ 418 | AES_state column; 419 | 420 | for (i = 0; i < nrounds + 1; i++) { 421 | int b; 422 | for (b = 0; b < 8; b++) { 423 | rounds[i].slice[b] = 0; 424 | } 425 | } 426 | 427 | /* The first nkeywords round columns are just taken from the key directly. */ 428 | for (i = 0; i < nkeywords; i++) { 429 | int r; 430 | for (r = 0; r < 4; r++) { 431 | LoadByte(&rounds[i >> 2], *(key++), r, i & 3); 432 | } 433 | } 434 | 435 | GetOneColumn(&column, &rounds[(nkeywords - 1) >> 2], (nkeywords - 1) & 3); 436 | 437 | for (i = nkeywords; i < 4 * (nrounds + 1); i++) { 438 | /* Transform column */ 439 | if (pos == 0) { 440 | SubBytes(&column, 0); 441 | KeySetupTransform(&column, &rcon); 442 | MultX(&rcon); 443 | } else if (nkeywords > 6 && pos == 4) { 444 | SubBytes(&column, 0); 445 | } 446 | if (++pos == nkeywords) pos = 0; 447 | KeySetupColumnMix(&column, &rounds[i >> 2], &rounds[(i - nkeywords) >> 2], i & 3, (i - nkeywords) & 3); 448 | } 449 | } 450 | 451 | static void AES_encrypt(const AES_state* rounds, int nrounds, unsigned char* cipher16, const unsigned char* plain16) { 452 | AES_state s = {{0}}; 453 | int round; 454 | 455 | LoadBytes(&s, plain16); 456 | AddRoundKey(&s, rounds++); 457 | 458 | for (round = 1; round < nrounds; round++) { 459 | SubBytes(&s, 0); 460 | ShiftRows(&s); 461 | MixColumns(&s, 0); 462 | AddRoundKey(&s, rounds++); 463 | } 464 | 465 | SubBytes(&s, 0); 466 | ShiftRows(&s); 467 | AddRoundKey(&s, rounds); 468 | 469 | SaveBytes(cipher16, &s); 470 | } 471 | 472 | static void AES_decrypt(const AES_state* rounds, int nrounds, unsigned char* plain16, const unsigned char* cipher16) { 473 | /* Most AES decryption implementations use the alternate scheme 474 | * (the Equivalent Inverse Cipher), which allows for more code reuse between 475 | * the encryption and decryption code, but requires separate setup for both. 476 | */ 477 | AES_state s = {{0}}; 478 | int round; 479 | 480 | rounds += nrounds; 481 | 482 | LoadBytes(&s, cipher16); 483 | AddRoundKey(&s, rounds--); 484 | 485 | for (round = 1; round < nrounds; round++) { 486 | InvShiftRows(&s); 487 | SubBytes(&s, 1); 488 | AddRoundKey(&s, rounds--); 489 | MixColumns(&s, 1); 490 | } 491 | 492 | InvShiftRows(&s); 493 | SubBytes(&s, 1); 494 | AddRoundKey(&s, rounds); 495 | 496 | SaveBytes(plain16, &s); 497 | } 498 | 499 | void AES128_init(AES128_ctx* ctx, const unsigned char* key16) { 500 | AES_setup(ctx->rk, key16, 4, 10); 501 | } 502 | 503 | void AES128_encrypt(const AES128_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16) { 504 | while (blocks--) { 505 | AES_encrypt(ctx->rk, 10, cipher16, plain16); 506 | cipher16 += 16; 507 | plain16 += 16; 508 | } 509 | } 510 | 511 | void AES128_decrypt(const AES128_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16) { 512 | while (blocks--) { 513 | AES_decrypt(ctx->rk, 10, plain16, cipher16); 514 | cipher16 += 16; 515 | plain16 += 16; 516 | } 517 | } 518 | 519 | void AES192_init(AES192_ctx* ctx, const unsigned char* key24) { 520 | AES_setup(ctx->rk, key24, 6, 12); 521 | } 522 | 523 | void AES192_encrypt(const AES192_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16) { 524 | while (blocks--) { 525 | AES_encrypt(ctx->rk, 12, cipher16, plain16); 526 | cipher16 += 16; 527 | plain16 += 16; 528 | } 529 | 530 | } 531 | 532 | void AES192_decrypt(const AES192_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16) { 533 | while (blocks--) { 534 | AES_decrypt(ctx->rk, 12, plain16, cipher16); 535 | cipher16 += 16; 536 | plain16 += 16; 537 | } 538 | } 539 | 540 | void AES256_init(AES256_ctx* ctx, const unsigned char* key32) { 541 | AES_setup(ctx->rk, key32, 8, 14); 542 | } 543 | 544 | void AES256_encrypt(const AES256_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16) { 545 | while (blocks--) { 546 | AES_encrypt(ctx->rk, 14, cipher16, plain16); 547 | cipher16 += 16; 548 | plain16 += 16; 549 | } 550 | } 551 | 552 | void AES256_decrypt(const AES256_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16) { 553 | while (blocks--) { 554 | AES_decrypt(ctx->rk, 14, plain16, cipher16); 555 | cipher16 += 16; 556 | plain16 += 16; 557 | } 558 | } 559 | 560 | static void Xor128(uint8_t* buf1, const uint8_t* buf2) { 561 | size_t i; 562 | for (i = 0; i < 16; i++) { 563 | buf1[i] ^= buf2[i]; 564 | } 565 | } 566 | 567 | static void AESCBC_encrypt(const AES_state* rounds, uint8_t* iv, int nk, size_t blocks, unsigned char* encrypted, const unsigned char* plain) { 568 | size_t i; 569 | unsigned char buf[16]; 570 | 571 | for (i = 0; i < blocks; i++) { 572 | memcpy(buf, plain, 16); 573 | Xor128(buf, iv); 574 | AES_encrypt(rounds, nk, encrypted, buf); 575 | memcpy(iv, encrypted, 16); 576 | plain += 16; 577 | encrypted += 16; 578 | } 579 | } 580 | 581 | static void AESCBC_decrypt(const AES_state* rounds, uint8_t* iv, int nk, size_t blocks, unsigned char* plain, const unsigned char* encrypted) { 582 | size_t i; 583 | uint8_t next_iv[16]; 584 | 585 | for (i = 0; i < blocks; i++) { 586 | memcpy(next_iv, encrypted, 16); 587 | AES_decrypt(rounds, nk, plain, encrypted); 588 | Xor128(plain, iv); 589 | memcpy(iv, next_iv, 16); 590 | plain += 16; 591 | encrypted += 16; 592 | } 593 | } 594 | 595 | void AES128_CBC_init(AES128_CBC_ctx* ctx, const unsigned char* key16, const uint8_t* iv) { 596 | AES128_init(&(ctx->ctx), key16); 597 | memcpy(ctx->iv, iv, 16); 598 | } 599 | 600 | void AES192_CBC_init(AES192_CBC_ctx* ctx, const unsigned char* key16, const uint8_t* iv) { 601 | AES192_init(&(ctx->ctx), key16); 602 | memcpy(ctx->iv, iv, 16); 603 | } 604 | 605 | void AES256_CBC_init(AES256_CBC_ctx* ctx, const unsigned char* key16, const uint8_t* iv) { 606 | AES256_init(&(ctx->ctx), key16); 607 | memcpy(ctx->iv, iv, 16); 608 | } 609 | 610 | void AES128_CBC_encrypt(AES128_CBC_ctx* ctx, size_t blocks, unsigned char* encrypted, const unsigned char* plain) { 611 | AESCBC_encrypt(ctx->ctx.rk, ctx->iv, 10, blocks, encrypted, plain); 612 | } 613 | 614 | void AES128_CBC_decrypt(AES128_CBC_ctx* ctx, size_t blocks, unsigned char* plain, const unsigned char *encrypted) { 615 | AESCBC_decrypt(ctx->ctx.rk, ctx->iv, 10, blocks, plain, encrypted); 616 | } 617 | 618 | void AES192_CBC_encrypt(AES192_CBC_ctx* ctx, size_t blocks, unsigned char* encrypted, const unsigned char* plain) { 619 | AESCBC_encrypt(ctx->ctx.rk, ctx->iv, 12, blocks, encrypted, plain); 620 | } 621 | 622 | void AES192_CBC_decrypt(AES192_CBC_ctx* ctx, size_t blocks, unsigned char* plain, const unsigned char *encrypted) { 623 | AESCBC_decrypt(ctx->ctx.rk, ctx->iv, 12, blocks, plain, encrypted); 624 | } 625 | 626 | void AES256_CBC_encrypt(AES256_CBC_ctx* ctx, size_t blocks, unsigned char* encrypted, const unsigned char* plain) { 627 | AESCBC_encrypt(ctx->ctx.rk, ctx->iv, 14, blocks, encrypted, plain); 628 | } 629 | 630 | void AES256_CBC_decrypt(AES256_CBC_ctx* ctx, size_t blocks, unsigned char* plain, const unsigned char *encrypted) { 631 | AESCBC_decrypt(ctx->ctx.rk, ctx->iv, 14, blocks, plain, encrypted); 632 | } 633 | --------------------------------------------------------------------------------