aes_ige.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. /*
  2. * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the OpenSSL license (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. */
  9. #include "internal/cryptlib.h"
  10. #include <openssl/aes.h>
  11. #include "aes_locl.h"
  12. #define N_WORDS (AES_BLOCK_SIZE / sizeof(unsigned long))
  13. typedef struct {
  14. unsigned long data[N_WORDS];
  15. } aes_block_t;
  16. /* XXX: probably some better way to do this */
  17. #if defined(__i386__) || defined(__x86_64__)
  18. # define UNALIGNED_MEMOPS_ARE_FAST 1
  19. #else
  20. # define UNALIGNED_MEMOPS_ARE_FAST 0
  21. #endif
  22. #if UNALIGNED_MEMOPS_ARE_FAST
  23. # define load_block(d, s) (d) = *(const aes_block_t *)(s)
  24. # define store_block(d, s) *(aes_block_t *)(d) = (s)
  25. #else
  26. # define load_block(d, s) memcpy((d).data, (s), AES_BLOCK_SIZE)
  27. # define store_block(d, s) memcpy((d), (s).data, AES_BLOCK_SIZE)
  28. #endif
  29. /* N.B. The IV for this mode is _twice_ the block size */
  30. void AES_ige_encrypt(const unsigned char *in, unsigned char *out,
  31. size_t length, const AES_KEY *key,
  32. unsigned char *ivec, const int enc)
  33. {
  34. size_t n;
  35. size_t len = length;
  36. if (length == 0)
  37. return;
  38. OPENSSL_assert(in && out && key && ivec);
  39. OPENSSL_assert((AES_ENCRYPT == enc) || (AES_DECRYPT == enc));
  40. OPENSSL_assert((length % AES_BLOCK_SIZE) == 0);
  41. len = length / AES_BLOCK_SIZE;
  42. if (AES_ENCRYPT == enc) {
  43. if (in != out &&
  44. (UNALIGNED_MEMOPS_ARE_FAST
  45. || ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(long) ==
  46. 0)) {
  47. aes_block_t *ivp = (aes_block_t *) ivec;
  48. aes_block_t *iv2p = (aes_block_t *) (ivec + AES_BLOCK_SIZE);
  49. while (len) {
  50. aes_block_t *inp = (aes_block_t *) in;
  51. aes_block_t *outp = (aes_block_t *) out;
  52. for (n = 0; n < N_WORDS; ++n)
  53. outp->data[n] = inp->data[n] ^ ivp->data[n];
  54. AES_encrypt((unsigned char *)outp->data,
  55. (unsigned char *)outp->data, key);
  56. for (n = 0; n < N_WORDS; ++n)
  57. outp->data[n] ^= iv2p->data[n];
  58. ivp = outp;
  59. iv2p = inp;
  60. --len;
  61. in += AES_BLOCK_SIZE;
  62. out += AES_BLOCK_SIZE;
  63. }
  64. memcpy(ivec, ivp->data, AES_BLOCK_SIZE);
  65. memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE);
  66. } else {
  67. aes_block_t tmp, tmp2;
  68. aes_block_t iv;
  69. aes_block_t iv2;
  70. load_block(iv, ivec);
  71. load_block(iv2, ivec + AES_BLOCK_SIZE);
  72. while (len) {
  73. load_block(tmp, in);
  74. for (n = 0; n < N_WORDS; ++n)
  75. tmp2.data[n] = tmp.data[n] ^ iv.data[n];
  76. AES_encrypt((unsigned char *)tmp2.data,
  77. (unsigned char *)tmp2.data, key);
  78. for (n = 0; n < N_WORDS; ++n)
  79. tmp2.data[n] ^= iv2.data[n];
  80. store_block(out, tmp2);
  81. iv = tmp2;
  82. iv2 = tmp;
  83. --len;
  84. in += AES_BLOCK_SIZE;
  85. out += AES_BLOCK_SIZE;
  86. }
  87. memcpy(ivec, iv.data, AES_BLOCK_SIZE);
  88. memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE);
  89. }
  90. } else {
  91. if (in != out &&
  92. (UNALIGNED_MEMOPS_ARE_FAST
  93. || ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(long) ==
  94. 0)) {
  95. aes_block_t *ivp = (aes_block_t *) ivec;
  96. aes_block_t *iv2p = (aes_block_t *) (ivec + AES_BLOCK_SIZE);
  97. while (len) {
  98. aes_block_t tmp;
  99. aes_block_t *inp = (aes_block_t *) in;
  100. aes_block_t *outp = (aes_block_t *) out;
  101. for (n = 0; n < N_WORDS; ++n)
  102. tmp.data[n] = inp->data[n] ^ iv2p->data[n];
  103. AES_decrypt((unsigned char *)tmp.data,
  104. (unsigned char *)outp->data, key);
  105. for (n = 0; n < N_WORDS; ++n)
  106. outp->data[n] ^= ivp->data[n];
  107. ivp = inp;
  108. iv2p = outp;
  109. --len;
  110. in += AES_BLOCK_SIZE;
  111. out += AES_BLOCK_SIZE;
  112. }
  113. memcpy(ivec, ivp->data, AES_BLOCK_SIZE);
  114. memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE);
  115. } else {
  116. aes_block_t tmp, tmp2;
  117. aes_block_t iv;
  118. aes_block_t iv2;
  119. load_block(iv, ivec);
  120. load_block(iv2, ivec + AES_BLOCK_SIZE);
  121. while (len) {
  122. load_block(tmp, in);
  123. tmp2 = tmp;
  124. for (n = 0; n < N_WORDS; ++n)
  125. tmp.data[n] ^= iv2.data[n];
  126. AES_decrypt((unsigned char *)tmp.data,
  127. (unsigned char *)tmp.data, key);
  128. for (n = 0; n < N_WORDS; ++n)
  129. tmp.data[n] ^= iv.data[n];
  130. store_block(out, tmp);
  131. iv = tmp2;
  132. iv2 = tmp;
  133. --len;
  134. in += AES_BLOCK_SIZE;
  135. out += AES_BLOCK_SIZE;
  136. }
  137. memcpy(ivec, iv.data, AES_BLOCK_SIZE);
  138. memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE);
  139. }
  140. }
  141. }
  142. /*
  143. * Note that its effectively impossible to do biIGE in anything other
  144. * than a single pass, so no provision is made for chaining.
  145. */
  146. /* N.B. The IV for this mode is _four times_ the block size */
  147. void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out,
  148. size_t length, const AES_KEY *key,
  149. const AES_KEY *key2, const unsigned char *ivec,
  150. const int enc)
  151. {
  152. size_t n;
  153. size_t len = length;
  154. unsigned char tmp[AES_BLOCK_SIZE];
  155. unsigned char tmp2[AES_BLOCK_SIZE];
  156. unsigned char tmp3[AES_BLOCK_SIZE];
  157. unsigned char prev[AES_BLOCK_SIZE];
  158. const unsigned char *iv;
  159. const unsigned char *iv2;
  160. OPENSSL_assert(in && out && key && ivec);
  161. OPENSSL_assert((AES_ENCRYPT == enc) || (AES_DECRYPT == enc));
  162. OPENSSL_assert((length % AES_BLOCK_SIZE) == 0);
  163. if (AES_ENCRYPT == enc) {
  164. /*
  165. * XXX: Do a separate case for when in != out (strictly should check
  166. * for overlap, too)
  167. */
  168. /* First the forward pass */
  169. iv = ivec;
  170. iv2 = ivec + AES_BLOCK_SIZE;
  171. while (len >= AES_BLOCK_SIZE) {
  172. for (n = 0; n < AES_BLOCK_SIZE; ++n)
  173. out[n] = in[n] ^ iv[n];
  174. AES_encrypt(out, out, key);
  175. for (n = 0; n < AES_BLOCK_SIZE; ++n)
  176. out[n] ^= iv2[n];
  177. iv = out;
  178. memcpy(prev, in, AES_BLOCK_SIZE);
  179. iv2 = prev;
  180. len -= AES_BLOCK_SIZE;
  181. in += AES_BLOCK_SIZE;
  182. out += AES_BLOCK_SIZE;
  183. }
  184. /* And now backwards */
  185. iv = ivec + AES_BLOCK_SIZE * 2;
  186. iv2 = ivec + AES_BLOCK_SIZE * 3;
  187. len = length;
  188. while (len >= AES_BLOCK_SIZE) {
  189. out -= AES_BLOCK_SIZE;
  190. /*
  191. * XXX: reduce copies by alternating between buffers
  192. */
  193. memcpy(tmp, out, AES_BLOCK_SIZE);
  194. for (n = 0; n < AES_BLOCK_SIZE; ++n)
  195. out[n] ^= iv[n];
  196. /*
  197. * hexdump(stdout, "out ^ iv", out, AES_BLOCK_SIZE);
  198. */
  199. AES_encrypt(out, out, key);
  200. /*
  201. * hexdump(stdout,"enc", out, AES_BLOCK_SIZE);
  202. */
  203. /*
  204. * hexdump(stdout,"iv2", iv2, AES_BLOCK_SIZE);
  205. */
  206. for (n = 0; n < AES_BLOCK_SIZE; ++n)
  207. out[n] ^= iv2[n];
  208. /*
  209. * hexdump(stdout,"out", out, AES_BLOCK_SIZE);
  210. */
  211. iv = out;
  212. memcpy(prev, tmp, AES_BLOCK_SIZE);
  213. iv2 = prev;
  214. len -= AES_BLOCK_SIZE;
  215. }
  216. } else {
  217. /* First backwards */
  218. iv = ivec + AES_BLOCK_SIZE * 2;
  219. iv2 = ivec + AES_BLOCK_SIZE * 3;
  220. in += length;
  221. out += length;
  222. while (len >= AES_BLOCK_SIZE) {
  223. in -= AES_BLOCK_SIZE;
  224. out -= AES_BLOCK_SIZE;
  225. memcpy(tmp, in, AES_BLOCK_SIZE);
  226. memcpy(tmp2, in, AES_BLOCK_SIZE);
  227. for (n = 0; n < AES_BLOCK_SIZE; ++n)
  228. tmp[n] ^= iv2[n];
  229. AES_decrypt(tmp, out, key);
  230. for (n = 0; n < AES_BLOCK_SIZE; ++n)
  231. out[n] ^= iv[n];
  232. memcpy(tmp3, tmp2, AES_BLOCK_SIZE);
  233. iv = tmp3;
  234. iv2 = out;
  235. len -= AES_BLOCK_SIZE;
  236. }
  237. /* And now forwards */
  238. iv = ivec;
  239. iv2 = ivec + AES_BLOCK_SIZE;
  240. len = length;
  241. while (len >= AES_BLOCK_SIZE) {
  242. memcpy(tmp, out, AES_BLOCK_SIZE);
  243. memcpy(tmp2, out, AES_BLOCK_SIZE);
  244. for (n = 0; n < AES_BLOCK_SIZE; ++n)
  245. tmp[n] ^= iv2[n];
  246. AES_decrypt(tmp, out, key);
  247. for (n = 0; n < AES_BLOCK_SIZE; ++n)
  248. out[n] ^= iv[n];
  249. memcpy(tmp3, tmp2, AES_BLOCK_SIZE);
  250. iv = tmp3;
  251. iv2 = out;
  252. len -= AES_BLOCK_SIZE;
  253. in += AES_BLOCK_SIZE;
  254. out += AES_BLOCK_SIZE;
  255. }
  256. }
  257. }