crypto_aes.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. #include <assert.h>
  2. #include <stdint.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <openssl/aes.h>
  6. #include "cpusupport.h"
  7. #include "crypto_aes_aesni.h"
  8. #include "insecure_memzero.h"
  9. #include "warnp.h"
  10. #include "crypto_aes.h"
  11. /**
  12. * This represents either an AES_KEY or a struct crypto_aes_key_aesni; we
  13. * know which it is based on whether we're using AESNI code or not. As such,
  14. * it's just an opaque pointer; but declaring it as a named structure type
  15. * prevents type-mismatch bugs in upstream code.
  16. */
  17. struct crypto_aes_key;
  18. #ifdef CPUSUPPORT_X86_AESNI
  19. /* Test whether OpenSSL and AESNI code produce the same AES ciphertext. */
  20. static int
  21. aesnitest(uint8_t ptext[16], uint8_t * key, size_t len)
  22. {
  23. AES_KEY kexp_openssl;
  24. void * kexp_aesni;
  25. uint8_t ctext_openssl[16];
  26. uint8_t ctext_aesni[16];
  27. /* Sanity-check. */
  28. assert((len == 16) || (len == 32));
  29. /* Expand the key. */
  30. AES_set_encrypt_key(key, (int)(len * 8), &kexp_openssl);
  31. if ((kexp_aesni = crypto_aes_key_expand_aesni(key, len)) == NULL)
  32. goto err0;
  33. /* Encrypt the block. */
  34. AES_encrypt(ptext, ctext_openssl, &kexp_openssl);
  35. crypto_aes_encrypt_block_aesni(ptext, ctext_aesni, kexp_aesni);
  36. /* Free the AESNI expanded key. */
  37. crypto_aes_key_free_aesni(kexp_aesni);
  38. /* Do the outputs match? */
  39. return (memcmp(ctext_openssl, ctext_aesni, 16));
  40. err0:
  41. /* Failure! */
  42. return (-1);
  43. }
  44. /* Should we use AESNI? */
  45. static int
  46. useaesni(void)
  47. {
  48. static int aesnigood = -1;
  49. uint8_t key[32];
  50. uint8_t ptext[16];
  51. size_t i;
  52. /* If we haven't decided which code to use yet, decide now. */
  53. while (aesnigood == -1) {
  54. /* Default to OpenSSL. */
  55. aesnigood = 0;
  56. /* If the CPU doesn't claim to support AESNI, stop here. */
  57. if (!cpusupport_x86_aesni())
  58. break;
  59. /* Test cases: key is 0x00010203..., ptext is 0x00112233... */
  60. for (i = 0; i < 16; i++)
  61. ptext[i] = (0x11 * i) & 0xff;
  62. for (i = 0; i < 32; i++)
  63. key[i] = i & 0xff;
  64. /* Test that AESNI and OpenSSL produce the same results. */
  65. if (aesnitest(ptext, key, 16) || aesnitest(ptext, key, 32)) {
  66. warn0("Disabling AESNI due to failed self-test");
  67. break;
  68. }
  69. /* AESNI works; use it. */
  70. aesnigood = 1;
  71. }
  72. return (aesnigood);
  73. }
  74. #endif /* CPUSUPPORT_X86_AESNI */
  75. /**
  76. * crypto_aes_key_expand(key, len):
  77. * Expand the ${len}-byte AES key ${key} into a structure which can be passed
  78. * to crypto_aes_encrypt_block. The length must be 16 or 32.
  79. */
  80. struct crypto_aes_key *
  81. crypto_aes_key_expand(const uint8_t * key, size_t len)
  82. {
  83. AES_KEY * kexp;
  84. /* Sanity-check. */
  85. assert((len == 16) || (len == 32));
  86. #ifdef CPUSUPPORT_X86_AESNI
  87. /* Use AESNI if we can. */
  88. if (useaesni())
  89. return (crypto_aes_key_expand_aesni(key, len));
  90. #endif
  91. /* Allocate structure. */
  92. if ((kexp = malloc(sizeof(AES_KEY))) == NULL)
  93. goto err0;
  94. /* Expand the key. */
  95. AES_set_encrypt_key(key, (int)(len * 8), kexp);
  96. /* Success! */
  97. return ((void *)kexp);
  98. err0:
  99. /* Failure! */
  100. return (NULL);
  101. }
  102. /**
  103. * crypto_aes_encrypt_block(in, out, key):
  104. * Using the expanded AES key ${key}, encrypt the block ${in} and write the
  105. * resulting ciphertext to ${out}.
  106. */
  107. void
  108. crypto_aes_encrypt_block(const uint8_t * in, uint8_t * out,
  109. const struct crypto_aes_key * key)
  110. {
  111. #ifdef CPUSUPPORT_X86_AESNI
  112. if (useaesni()) {
  113. crypto_aes_encrypt_block_aesni(in, out, (const void *)key);
  114. return;
  115. }
  116. #endif
  117. /* Get AES to do the work. */
  118. AES_encrypt(in, out, (const void *)key);
  119. }
  120. /**
  121. * crypto_aes_key_free(key):
  122. * Free the expanded AES key ${key}.
  123. */
  124. void
  125. crypto_aes_key_free(struct crypto_aes_key * key)
  126. {
  127. #ifdef CPUSUPPORT_X86_AESNI
  128. if (useaesni()) {
  129. crypto_aes_key_free_aesni((void *)key);
  130. return;
  131. }
  132. #endif
  133. /* Behave consistently with free(NULL). */
  134. if (key == NULL)
  135. return;
  136. /* Attempt to zero the expanded key. */
  137. insecure_memzero(key, sizeof(AES_KEY));
  138. /* Free the key. */
  139. free(key);
  140. }