6 #include <openssl/aes.h>
8 #include "cpusupport.h"
9 #include "crypto_aes_aesni.h"
10 #include "insecure_memzero.h"
13 #include "crypto_aes.h"
16 * This represents either an AES_KEY or a struct crypto_aes_key_aesni; we
17 * know which it is based on whether we're using AESNI code or not. As such,
18 * it's just an opaque pointer; but declaring it as a named structure type
19 * prevents type-mismatch bugs in upstream code.
21 struct crypto_aes_key
;
23 #ifdef CPUSUPPORT_X86_AESNI
24 /* Test whether OpenSSL and AESNI code produce the same AES ciphertext. */
26 aesnitest(uint8_t ptext
[16], uint8_t * key
, size_t len
)
30 uint8_t ctext_openssl
[16];
31 uint8_t ctext_aesni
[16];
34 assert((len
== 16) || (len
== 32));
37 AES_set_encrypt_key(key
, (int)(len
* 8), &kexp_openssl
);
38 if ((kexp_aesni
= crypto_aes_key_expand_aesni(key
, len
)) == NULL
)
41 /* Encrypt the block. */
42 AES_encrypt(ptext
, ctext_openssl
, &kexp_openssl
);
43 crypto_aes_encrypt_block_aesni(ptext
, ctext_aesni
, kexp_aesni
);
45 /* Free the AESNI expanded key. */
46 crypto_aes_key_free_aesni(kexp_aesni
);
48 /* Do the outputs match? */
49 return (memcmp(ctext_openssl
, ctext_aesni
, 16));
56 /* Should we use AESNI? */
60 static int aesnigood
= -1;
65 /* If we haven't decided which code to use yet, decide now. */
66 while (aesnigood
== -1) {
67 /* Default to OpenSSL. */
70 /* If the CPU doesn't claim to support AESNI, stop here. */
71 if (!cpusupport_x86_aesni())
74 /* Test cases: key is 0x00010203..., ptext is 0x00112233... */
75 for (i
= 0; i
< 16; i
++)
76 ptext
[i
] = (0x11 * i
) & 0xff;
77 for (i
= 0; i
< 32; i
++)
80 /* Test that AESNI and OpenSSL produce the same results. */
81 if (aesnitest(ptext
, key
, 16) || aesnitest(ptext
, key
, 32)) {
82 warn0("Disabling AESNI due to failed self-test");
86 /* AESNI works; use it. */
92 #endif /* CPUSUPPORT_X86_AESNI */
95 * crypto_aes_key_expand(key, len):
96 * Expand the ${len}-byte AES key ${key} into a structure which can be passed
97 * to crypto_aes_encrypt_block. The length must be 16 or 32.
99 struct crypto_aes_key
*
100 crypto_aes_key_expand(const uint8_t * key
, size_t len
)
105 assert((len
== 16) || (len
== 32));
107 #ifdef CPUSUPPORT_X86_AESNI
108 /* Use AESNI if we can. */
110 return (crypto_aes_key_expand_aesni(key
, len
));
113 /* Allocate structure. */
114 if ((kexp
= malloc(sizeof(AES_KEY
))) == NULL
)
117 /* Expand the key. */
118 AES_set_encrypt_key(key
, (int)(len
* 8), kexp
);
121 return ((void *)kexp
);
129 * crypto_aes_encrypt_block(in, out, key):
130 * Using the expanded AES key ${key}, encrypt the block ${in} and write the
131 * resulting ciphertext to ${out}.
134 crypto_aes_encrypt_block(const uint8_t * in
, uint8_t * out
,
135 const struct crypto_aes_key
* key
)
138 #ifdef CPUSUPPORT_X86_AESNI
140 crypto_aes_encrypt_block_aesni(in
, out
, (const void *)key
);
145 /* Get AES to do the work. */
146 AES_encrypt(in
, out
, (const void *)key
);
150 * crypto_aes_key_free(key):
151 * Free the expanded AES key ${key}.
154 crypto_aes_key_free(struct crypto_aes_key
* key
)
157 #ifdef CPUSUPPORT_X86_AESNI
159 crypto_aes_key_free_aesni((void *)key
);
164 /* Behave consistently with free(NULL). */
168 /* Attempt to zero the expanded key. */
169 insecure_memzero(key
, sizeof(AES_KEY
));
This page took 0.027129 seconds and 4 git commands to generate.