1 /*
2  * Unit test for HW AES encryption.
3  */
4 
5 #include <lib/aes.h>
6 
7 #include <stdint.h>
8 #include <string.h>
9 #include <platform.h>
10 #include <lk/debug.h>
11 #include <lk/trace.h>
12 #include <arch/ops.h>
13 #include <lk/console_cmd.h>
14 
15 /*
16  * These sample values come from publication "FIPS-197", Appendix C.1
17  * "AES-128" See
18  * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
19  */
20 static const uint8_t plaintext[] = {
21     0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
22     0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
23 };
24 
25 static const uint8_t key[] = {
26     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
27     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
28 };
29 
30 static const uint8_t expected_ciphertext[] = {
31     0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30,
32     0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a
33 };
34 
aes_command(int argc,const console_cmd_args * argv)35 static int aes_command(int argc, const console_cmd_args *argv)
36 {
37     AES_KEY aes_key;
38     uint8_t ciphertext[AES_BLOCK_SIZE];
39 
40     TRACEF("Testing AES encryption.\n");
41     memset(ciphertext, 0, sizeof(ciphertext));
42     AES_set_encrypt_key(key, 128, &aes_key);
43     lk_bigtime_t start = current_time_hires();
44     AES_encrypt(plaintext, ciphertext, &aes_key);
45     lk_bigtime_t end = current_time_hires();
46     int elapsed = end - start;
47     TRACEF("Elapsed time: %d us for 16 bytes (%d.%03d us per byte)\n",
48            elapsed, elapsed / AES_BLOCK_SIZE,
49            ((elapsed * 1000) / AES_BLOCK_SIZE) % 1000);
50     int not_equal = memcmp(expected_ciphertext, ciphertext, AES_BLOCK_SIZE);
51     if (not_equal) {
52         TRACEF("Encryption failed.  Expected:\n");
53         hexdump8(expected_ciphertext, sizeof(expected_ciphertext));
54         TRACEF("Actual:\n");
55         hexdump8(ciphertext, sizeof(ciphertext));
56         TRACEF("FAILED AES encryption\n");
57     } else {
58         TRACEF("PASSED AES encryption\n");
59     }
60     return 0;
61 }
62 
aes_bench(int argc,const console_cmd_args * argv)63 static int aes_bench(int argc, const console_cmd_args *argv)
64 {
65     uint32_t c;
66     int i;
67     AES_KEY aes_key;
68     uint8_t ciphertext[AES_BLOCK_SIZE];
69 #define ITER 1000
70 
71     memset(ciphertext, 0, sizeof(ciphertext));
72 
73     c = arch_cycle_count();
74 
75     for (i = 0; i < ITER; i++) {
76         AES_set_encrypt_key(key, 128, &aes_key);
77     }
78 
79     c = arch_cycle_count() - c;
80     printf("%u cycles to set encryption key\n", c / ITER);
81 
82     c = arch_cycle_count();
83     for (i = 0; i < ITER; i++) {
84         AES_encrypt(plaintext, ciphertext, &aes_key);
85     }
86     c = arch_cycle_count() - c;
87 
88     printf("%u cycles to encrypt block of 16 bytes\n", c / ITER);
89 
90     return 0;
91 }
92 
93 STATIC_COMMAND_START
94 STATIC_COMMAND("aes_test", "test AES encryption", &aes_command)
95 STATIC_COMMAND("aes_bench", "bench AES encryption", &aes_bench)
96 STATIC_COMMAND_END(aes_test);
97