crypto_aes.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. /**
  2. * APISUPPORT CFLAGS: LIBCRYPTO_LOW_LEVEL_AES
  3. */
  4. #include <assert.h>
  5. #include <stdint.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <openssl/aes.h>
  9. #include "cpusupport.h"
  10. #include "crypto_aes_aesni.h"
  11. #include "crypto_aes_arm.h"
  12. #include "insecure_memzero.h"
  13. #include "warnp.h"
  14. #include "crypto_aes.h"
  15. #if defined(CPUSUPPORT_X86_AESNI) || defined(CPUSUPPORT_ARM_AES)
  16. #define HWACCEL
  17. static enum {
  18. HW_SOFTWARE = 0,
  19. #if defined(CPUSUPPORT_X86_AESNI)
  20. HW_X86_AESNI,
  21. #endif
  22. #if defined(CPUSUPPORT_ARM_AES)
  23. HW_ARM_AES,
  24. #endif
  25. HW_UNSET
  26. } hwaccel = HW_UNSET;
  27. #endif
  28. /**
  29. * This represents either an AES_KEY or a struct crypto_aes_key_aesni; we
  30. * know which it is based on whether we're using AESNI code or not. As such,
  31. * it's just an opaque pointer; but declaring it as a named structure type
  32. * prevents type-mismatch bugs in upstream code.
  33. */
  34. struct crypto_aes_key;
  35. #ifdef HWACCEL
  36. static struct aes_test {
  37. const uint8_t key[32];
  38. const size_t len;
  39. const uint8_t ptext[16];
  40. const uint8_t ctext[16];
  41. } testcases[] = { {
  42. /* NIST FIPS 179, Appendix C - Example Vectors, AES-128, p. 35. */
  43. .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
  44. 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f},
  45. .len = 16,
  46. .ptext = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
  47. 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
  48. .ctext = { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30,
  49. 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a }
  50. }, {
  51. /* NIST FIPS 179, Appendix C - Example Vectors, AES-256, p. 42. */
  52. .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
  53. 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  54. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
  55. 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, },
  56. .len = 32,
  57. .ptext = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
  58. 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
  59. .ctext = { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf,
  60. 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 }
  61. }
  62. };
  63. /* Test a function against test vectors. */
  64. static int
  65. functest(int (* func)(const uint8_t *, size_t, const uint8_t[16], uint8_t[16]))
  66. {
  67. struct aes_test * knowngood;
  68. uint8_t ctext[16];
  69. size_t i;
  70. for (i = 0; i < sizeof(testcases) / sizeof(testcases[0]); i++) {
  71. knowngood = &testcases[i];
  72. /* Sanity-check. */
  73. assert((knowngood->len == 16) || (knowngood->len == 32));
  74. /* Expand the key and encrypt with the provided function. */
  75. if (func(knowngood->key, knowngood->len, knowngood->ptext,
  76. ctext))
  77. goto err0;
  78. /* Does the output match the known good value? */
  79. if (memcmp(knowngood->ctext, ctext, 16))
  80. goto err0;
  81. }
  82. /* Success! */
  83. return (0);
  84. err0:
  85. /* Failure! */
  86. return (-1);
  87. }
  88. #if defined(CPUSUPPORT_X86_AESNI)
  89. static int
  90. x86_aesni_oneshot(const uint8_t * key_unexpanded, size_t len,
  91. const uint8_t ptext[16], uint8_t ctext[16])
  92. {
  93. void * kexp_hw;
  94. /* Expand the key and encrypt with hardware intrinsics. */
  95. if ((kexp_hw = crypto_aes_key_expand_aesni(key_unexpanded, len))
  96. == NULL)
  97. goto err0;
  98. crypto_aes_encrypt_block_aesni(ptext, ctext, kexp_hw);
  99. crypto_aes_key_free_aesni(kexp_hw);
  100. /* Success! */
  101. return (0);
  102. err0:
  103. /* Failure! */
  104. return (-1);
  105. }
  106. #endif
  107. #if defined(CPUSUPPORT_ARM_AES)
  108. static int
  109. arm_aes_oneshot(const uint8_t * key_unexpanded, size_t len,
  110. const uint8_t ptext[16], uint8_t * ctext)
  111. {
  112. void * kexp_hw;
  113. if ((kexp_hw = crypto_aes_key_expand_arm(key_unexpanded, len)) == NULL)
  114. goto err0;
  115. crypto_aes_encrypt_block_arm(ptext, ctext, kexp_hw);
  116. crypto_aes_key_free_arm(kexp_hw);
  117. /* Success! */
  118. return (0);
  119. err0:
  120. /* Failure! */
  121. return (-1);
  122. }
  123. #endif
  124. static int
  125. openssl_oneshot(const uint8_t * key_unexpanded, size_t len,
  126. const uint8_t ptext[16], uint8_t * ctext)
  127. {
  128. AES_KEY kexp_actual;
  129. AES_KEY * kexp = &kexp_actual;
  130. /* Expand the key, encrypt, and clean up. */
  131. if (AES_set_encrypt_key(key_unexpanded, (int)(len * 8), kexp) != 0)
  132. goto err0;
  133. AES_encrypt(ptext, ctext, kexp);
  134. insecure_memzero(kexp, sizeof(AES_KEY));
  135. /* Success! */
  136. return (0);
  137. err0:
  138. /* Failure! */
  139. return (-1);
  140. }
  141. /* Which type of hardware acceleration should we use, if any? */
  142. static void
  143. hwaccel_init(void)
  144. {
  145. /* If we've already set hwaccel, we're finished. */
  146. if (hwaccel != HW_UNSET)
  147. return;
  148. /* Default to software. */
  149. hwaccel = HW_SOFTWARE;
  150. #if defined(CPUSUPPORT_X86_AESNI)
  151. CPUSUPPORT_VALIDATE(hwaccel, HW_X86_AESNI, cpusupport_x86_aesni(),
  152. functest(x86_aesni_oneshot));
  153. #endif
  154. #if defined(CPUSUPPORT_ARM_AES)
  155. CPUSUPPORT_VALIDATE(hwaccel, HW_ARM_AES, cpusupport_arm_aes(),
  156. functest(arm_aes_oneshot));
  157. #endif
  158. /*
  159. * If we're here, we're not using any intrinsics. Test OpenSSL; if
  160. * there's an error, print a warning and abort.
  161. */
  162. if (functest(openssl_oneshot)) {
  163. warn0("OpenSSL gives incorrect AES values.");
  164. abort();
  165. }
  166. }
  167. #endif /* HWACCEL */
  168. /**
  169. * crypto_aes_can_use_intrinsics(void):
  170. * Test whether hardware intrinsics are safe to use. Return 1 if x86 AESNI
  171. * operations are available, 2 if ARM-AES operations are available, or 0 if
  172. * none are available.
  173. */
  174. int
  175. crypto_aes_can_use_intrinsics(void)
  176. {
  177. #ifdef HWACCEL
  178. /* Ensure that we've chosen the type of hardware acceleration. */
  179. hwaccel_init();
  180. #if defined(CPUSUPPORT_X86_AESNI)
  181. if (hwaccel == HW_X86_AESNI)
  182. return (1);
  183. #endif
  184. #if defined(CPUSUPPORT_ARM_AES)
  185. if (hwaccel == HW_ARM_AES)
  186. return (2);
  187. #endif
  188. #endif /* HWACCEL */
  189. /* Software only. */
  190. return (0);
  191. }
  192. /**
  193. * crypto_aes_key_expand(key_unexpanded, len):
  194. * Expand the ${len}-byte unexpanded AES key ${key_unexpanded} into a
  195. * structure which can be passed to crypto_aes_encrypt_block(). The length
  196. * must be 16 or 32.
  197. */
  198. struct crypto_aes_key *
  199. crypto_aes_key_expand(const uint8_t * key_unexpanded, size_t len)
  200. {
  201. AES_KEY * kexp;
  202. /* Sanity-check. */
  203. assert((len == 16) || (len == 32));
  204. #ifdef HWACCEL
  205. /* Ensure that we've chosen the type of hardware acceleration. */
  206. hwaccel_init();
  207. #ifdef CPUSUPPORT_X86_AESNI
  208. if (hwaccel == HW_X86_AESNI)
  209. return (crypto_aes_key_expand_aesni(key_unexpanded, len));
  210. #endif
  211. #ifdef CPUSUPPORT_ARM_AES
  212. if (hwaccel == HW_ARM_AES)
  213. return (crypto_aes_key_expand_arm(key_unexpanded, len));
  214. #endif
  215. #endif /* HWACCEL */
  216. /* Allocate structure. */
  217. if ((kexp = malloc(sizeof(AES_KEY))) == NULL)
  218. goto err0;
  219. /* Expand the key. */
  220. if (AES_set_encrypt_key(key_unexpanded, (int)(len * 8), kexp) != 0)
  221. goto err1;
  222. /* Success! */
  223. return ((void *)kexp);
  224. err1:
  225. free(kexp);
  226. err0:
  227. /* Failure! */
  228. return (NULL);
  229. }
  230. /**
  231. * crypto_aes_encrypt_block(in, out, key):
  232. * Using the expanded AES key ${key}, encrypt the block ${in} and write the
  233. * resulting ciphertext to ${out}. ${in} and ${out} can overlap.
  234. */
  235. void
  236. crypto_aes_encrypt_block(const uint8_t in[16], uint8_t out[16],
  237. const struct crypto_aes_key * key)
  238. {
  239. #ifdef HWACCEL
  240. #ifdef CPUSUPPORT_X86_AESNI
  241. if (hwaccel == HW_X86_AESNI) {
  242. crypto_aes_encrypt_block_aesni(in, out, (const void *)key);
  243. return;
  244. }
  245. #endif
  246. #ifdef CPUSUPPORT_ARM_AES
  247. if (hwaccel == HW_ARM_AES) {
  248. crypto_aes_encrypt_block_arm(in, out, (const void *)key);
  249. return;
  250. }
  251. #endif
  252. #endif /* HWACCEL */
  253. /* Get AES to do the work. */
  254. AES_encrypt(in, out, (const void *)key);
  255. }
  256. /**
  257. * crypto_aes_key_free(key):
  258. * Free the expanded AES key ${key}.
  259. */
  260. void
  261. crypto_aes_key_free(struct crypto_aes_key * key)
  262. {
  263. #ifdef HWACCEL
  264. #ifdef CPUSUPPORT_X86_AESNI
  265. if (hwaccel == HW_X86_AESNI) {
  266. crypto_aes_key_free_aesni((void *)key);
  267. return;
  268. }
  269. #endif
  270. #ifdef CPUSUPPORT_ARM_AES
  271. if (hwaccel == HW_ARM_AES) {
  272. crypto_aes_key_free_arm((void *)key);
  273. return;
  274. }
  275. #endif
  276. #endif /* HWACCEL */
  277. /* Behave consistently with free(NULL). */
  278. if (key == NULL)
  279. return;
  280. /* Attempt to zero the expanded key. */
  281. insecure_memzero(key, sizeof(AES_KEY));
  282. /* Free the key. */
  283. free(key);
  284. }