aes_modes.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932
  1. /*
  2. ---------------------------------------------------------------------------
  3. Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved.
  4. The redistribution and use of this software (with or without changes)
  5. is allowed without the payment of fees or royalties provided that:
  6. source code distributions include the above copyright notice, this
  7. list of conditions and the following disclaimer;
  8. binary distributions include the above copyright notice, this list
  9. of conditions and the following disclaimer in their documentation.
  10. This software is provided 'as is' with no explicit or implied warranties
  11. in respect of its operation, including, but not limited to, correctness
  12. and fitness for purpose.
  13. ---------------------------------------------------------------------------
  14. Issue Date: 20/12/2007
  15. These subroutines implement multiple block AES modes for ECB, CBC, CFB,
  16. OFB and CTR encryption, The code provides support for the VIA Advanced
  17. Cryptography Engine (ACE).
  18. NOTE: In the following subroutines, the AES contexts (ctx) must be
  19. 16 byte aligned if VIA ACE is being used
  20. */
  21. #include <string.h>
  22. #include <assert.h>
  23. #include <stdint.h>
  24. #include "aesopt.h"
  25. #if defined(AES_MODES)
  26. #if defined(__cplusplus)
  27. extern "C" {
  28. #endif
  29. #if defined(_MSC_VER) && (_MSC_VER > 800)
  30. #pragma intrinsic(memcpy)
  31. #endif
  32. #define BFR_BLOCKS 8
  33. /* These values are used to detect long word alignment in order to */
  34. /* speed up some buffer operations. This facility may not work on */
  35. /* some machines so this define can be commented out if necessary */
  36. #define FAST_BUFFER_OPERATIONS
  37. #define lp32(x) ((uint32_t*)(x))
  38. #if defined(USE_VIA_ACE_IF_PRESENT)
  39. #include "aes_via_ace.h"
  40. #pragma pack(16)
  41. aligned_array(unsigned long, enc_gen_table, 12, 16) = NEH_ENC_GEN_DATA;
  42. aligned_array(unsigned long, enc_load_table, 12, 16) = NEH_ENC_LOAD_DATA;
  43. aligned_array(unsigned long, enc_hybrid_table, 12, 16) = NEH_ENC_HYBRID_DATA;
  44. aligned_array(unsigned long, dec_gen_table, 12, 16) = NEH_DEC_GEN_DATA;
  45. aligned_array(unsigned long, dec_load_table, 12, 16) = NEH_DEC_LOAD_DATA;
  46. aligned_array(unsigned long, dec_hybrid_table, 12, 16) = NEH_DEC_HYBRID_DATA;
  47. /* NOTE: These control word macros must only be used after */
  48. /* a key has been set up because they depend on key size */
  49. /* See the VIA ACE documentation for key type information */
  50. /* and aes_via_ace.h for non-default NEH_KEY_TYPE values */
  51. #ifndef NEH_KEY_TYPE
  52. #define NEH_KEY_TYPE NEH_HYBRID
  53. #endif
  54. #if NEH_KEY_TYPE == NEH_LOAD
  55. #define kd_adr(c) ((uint8_t*)(c)->ks)
  56. #elif NEH_KEY_TYPE == NEH_GENERATE
  57. #define kd_adr(c) ((uint8_t*)(c)->ks + (c)->inf.b[0])
  58. #elif NEH_KEY_TYPE == NEH_HYBRID
  59. #define kd_adr(c) ((uint8_t*)(c)->ks + ((c)->inf.b[0] == 160 ? 160 : 0))
  60. #else
  61. #error no key type defined for VIA ACE
  62. #endif
  63. #else
  64. #define aligned_array(type, name, no, stride) type name[no]
  65. #define aligned_auto(type, name, no, stride) type name[no]
  66. #endif
  67. #if defined(_MSC_VER) && _MSC_VER > 1200
  68. #define via_cwd(cwd, ty, dir, len) unsigned long* cwd = (dir##_##ty##_table + ((len - 128) >> 4))
  69. #else
  70. #define via_cwd(cwd, ty, dir, len) \
  71. aligned_auto(unsigned long, cwd, 4, 16); \
  72. cwd[1] = cwd[2] = cwd[3] = 0; \
  73. cwd[0] = neh_##dir##_##ty##_key(len)
  74. #endif
  75. /* test the code for detecting and setting pointer alignment */
  76. AES_RETURN aes_test_alignment_detection(unsigned int n) /* 4 <= n <= 16 */
  77. {
  78. uint8_t p[16];
  79. uint32_t i = 0, count_eq = 0, count_neq = 0;
  80. if(n < 4 || n > 16) return EXIT_FAILURE;
  81. for(i = 0; i < n; ++i) {
  82. uint8_t *qf = ALIGN_FLOOR(p + i, n), *qh = ALIGN_CEIL(p + i, n);
  83. if(qh == qf)
  84. ++count_eq;
  85. else if(qh == qf + n)
  86. ++count_neq;
  87. else
  88. return EXIT_FAILURE;
  89. }
  90. return (count_eq != 1 || count_neq != n - 1 ? EXIT_FAILURE : EXIT_SUCCESS);
  91. }
  92. AES_RETURN aes_mode_reset(aes_encrypt_ctx ctx[1]) {
  93. ctx->inf.b[2] = 0;
  94. return EXIT_SUCCESS;
  95. }
  96. AES_RETURN aes_ecb_encrypt(
  97. const unsigned char* ibuf,
  98. unsigned char* obuf,
  99. int len,
  100. const aes_encrypt_ctx ctx[1]) {
  101. int nb = len >> AES_BLOCK_SIZE_P2;
  102. if(len & (AES_BLOCK_SIZE - 1)) return EXIT_FAILURE;
  103. #if defined(USE_VIA_ACE_IF_PRESENT)
  104. if(ctx->inf.b[1] == 0xff) {
  105. uint8_t* ksp = (uint8_t*)(ctx->ks);
  106. via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);
  107. if(ALIGN_OFFSET(ctx, 16)) return EXIT_FAILURE;
  108. if(!ALIGN_OFFSET(ibuf, 16) && !ALIGN_OFFSET(obuf, 16)) {
  109. via_ecb_op5(ksp, cwd, ibuf, obuf, nb);
  110. } else {
  111. aligned_auto(uint8_t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
  112. uint8_t *ip = NULL, *op = NULL;
  113. while(nb) {
  114. int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb);
  115. ip = (ALIGN_OFFSET(ibuf, 16) ? buf : ibuf);
  116. op = (ALIGN_OFFSET(obuf, 16) ? buf : obuf);
  117. if(ip != ibuf) memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
  118. via_ecb_op5(ksp, cwd, ip, op, m);
  119. if(op != obuf) memcpy(obuf, buf, m * AES_BLOCK_SIZE);
  120. ibuf += m * AES_BLOCK_SIZE;
  121. obuf += m * AES_BLOCK_SIZE;
  122. nb -= m;
  123. }
  124. }
  125. return EXIT_SUCCESS;
  126. }
  127. #endif
  128. #if !defined(ASSUME_VIA_ACE_PRESENT)
  129. while(nb--) {
  130. if(aes_encrypt(ibuf, obuf, ctx) != EXIT_SUCCESS) return EXIT_FAILURE;
  131. ibuf += AES_BLOCK_SIZE;
  132. obuf += AES_BLOCK_SIZE;
  133. }
  134. #endif
  135. return EXIT_SUCCESS;
  136. }
  137. AES_RETURN aes_ecb_decrypt(
  138. const unsigned char* ibuf,
  139. unsigned char* obuf,
  140. int len,
  141. const aes_decrypt_ctx ctx[1]) {
  142. int nb = len >> AES_BLOCK_SIZE_P2;
  143. if(len & (AES_BLOCK_SIZE - 1)) return EXIT_FAILURE;
  144. #if defined(USE_VIA_ACE_IF_PRESENT)
  145. if(ctx->inf.b[1] == 0xff) {
  146. uint8_t* ksp = kd_adr(ctx);
  147. via_cwd(cwd, hybrid, dec, 2 * ctx->inf.b[0] - 192);
  148. if(ALIGN_OFFSET(ctx, 16)) return EXIT_FAILURE;
  149. if(!ALIGN_OFFSET(ibuf, 16) && !ALIGN_OFFSET(obuf, 16)) {
  150. via_ecb_op5(ksp, cwd, ibuf, obuf, nb);
  151. } else {
  152. aligned_auto(uint8_t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
  153. uint8_t *ip = NULL, *op = NULL;
  154. while(nb) {
  155. int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb);
  156. ip = (ALIGN_OFFSET(ibuf, 16) ? buf : ibuf);
  157. op = (ALIGN_OFFSET(obuf, 16) ? buf : obuf);
  158. if(ip != ibuf) memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
  159. via_ecb_op5(ksp, cwd, ip, op, m);
  160. if(op != obuf) memcpy(obuf, buf, m * AES_BLOCK_SIZE);
  161. ibuf += m * AES_BLOCK_SIZE;
  162. obuf += m * AES_BLOCK_SIZE;
  163. nb -= m;
  164. }
  165. }
  166. return EXIT_SUCCESS;
  167. }
  168. #endif
  169. #if !defined(ASSUME_VIA_ACE_PRESENT)
  170. while(nb--) {
  171. if(aes_decrypt(ibuf, obuf, ctx) != EXIT_SUCCESS) return EXIT_FAILURE;
  172. ibuf += AES_BLOCK_SIZE;
  173. obuf += AES_BLOCK_SIZE;
  174. }
  175. #endif
  176. return EXIT_SUCCESS;
  177. }
  178. AES_RETURN aes_cbc_encrypt(
  179. const unsigned char* ibuf,
  180. unsigned char* obuf,
  181. int len,
  182. unsigned char* iv,
  183. const aes_encrypt_ctx ctx[1]) {
  184. int nb = len >> AES_BLOCK_SIZE_P2;
  185. if(len & (AES_BLOCK_SIZE - 1)) return EXIT_FAILURE;
  186. #if defined(USE_VIA_ACE_IF_PRESENT)
  187. if(ctx->inf.b[1] == 0xff) {
  188. uint8_t *ksp = (uint8_t*)(ctx->ks), *ivp = iv;
  189. aligned_auto(uint8_t, liv, AES_BLOCK_SIZE, 16);
  190. via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);
  191. if(ALIGN_OFFSET(ctx, 16)) return EXIT_FAILURE;
  192. if(ALIGN_OFFSET(iv, 16)) /* ensure an aligned iv */
  193. {
  194. ivp = liv;
  195. memcpy(liv, iv, AES_BLOCK_SIZE);
  196. }
  197. if(!ALIGN_OFFSET(ibuf, 16) && !ALIGN_OFFSET(obuf, 16) && !ALIGN_OFFSET(iv, 16)) {
  198. via_cbc_op7(ksp, cwd, ibuf, obuf, nb, ivp, ivp);
  199. } else {
  200. aligned_auto(uint8_t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
  201. uint8_t *ip = NULL, *op = NULL;
  202. while(nb) {
  203. int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb);
  204. ip = (ALIGN_OFFSET(ibuf, 16) ? buf : ibuf);
  205. op = (ALIGN_OFFSET(obuf, 16) ? buf : obuf);
  206. if(ip != ibuf) memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
  207. via_cbc_op7(ksp, cwd, ip, op, m, ivp, ivp);
  208. if(op != obuf) memcpy(obuf, buf, m * AES_BLOCK_SIZE);
  209. ibuf += m * AES_BLOCK_SIZE;
  210. obuf += m * AES_BLOCK_SIZE;
  211. nb -= m;
  212. }
  213. }
  214. if(iv != ivp) memcpy(iv, ivp, AES_BLOCK_SIZE);
  215. return EXIT_SUCCESS;
  216. }
  217. #endif
  218. #if !defined(ASSUME_VIA_ACE_PRESENT)
  219. #ifdef FAST_BUFFER_OPERATIONS
  220. if(!ALIGN_OFFSET(ibuf, 4) && !ALIGN_OFFSET(iv, 4))
  221. while(nb--) {
  222. lp32(iv)[0] ^= lp32(ibuf)[0];
  223. lp32(iv)[1] ^= lp32(ibuf)[1];
  224. lp32(iv)[2] ^= lp32(ibuf)[2];
  225. lp32(iv)[3] ^= lp32(ibuf)[3];
  226. if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) return EXIT_FAILURE;
  227. memcpy(obuf, iv, AES_BLOCK_SIZE);
  228. ibuf += AES_BLOCK_SIZE;
  229. obuf += AES_BLOCK_SIZE;
  230. }
  231. else
  232. #endif
  233. while(nb--) {
  234. iv[0] ^= ibuf[0];
  235. iv[1] ^= ibuf[1];
  236. iv[2] ^= ibuf[2];
  237. iv[3] ^= ibuf[3];
  238. iv[4] ^= ibuf[4];
  239. iv[5] ^= ibuf[5];
  240. iv[6] ^= ibuf[6];
  241. iv[7] ^= ibuf[7];
  242. iv[8] ^= ibuf[8];
  243. iv[9] ^= ibuf[9];
  244. iv[10] ^= ibuf[10];
  245. iv[11] ^= ibuf[11];
  246. iv[12] ^= ibuf[12];
  247. iv[13] ^= ibuf[13];
  248. iv[14] ^= ibuf[14];
  249. iv[15] ^= ibuf[15];
  250. if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) return EXIT_FAILURE;
  251. memcpy(obuf, iv, AES_BLOCK_SIZE);
  252. ibuf += AES_BLOCK_SIZE;
  253. obuf += AES_BLOCK_SIZE;
  254. }
  255. #endif
  256. return EXIT_SUCCESS;
  257. }
  258. AES_RETURN aes_cbc_decrypt(
  259. const unsigned char* ibuf,
  260. unsigned char* obuf,
  261. int len,
  262. unsigned char* iv,
  263. const aes_decrypt_ctx ctx[1]) {
  264. unsigned char tmp[AES_BLOCK_SIZE];
  265. int nb = len >> AES_BLOCK_SIZE_P2;
  266. if(len & (AES_BLOCK_SIZE - 1)) return EXIT_FAILURE;
  267. #if defined(USE_VIA_ACE_IF_PRESENT)
  268. if(ctx->inf.b[1] == 0xff) {
  269. uint8_t *ksp = kd_adr(ctx), *ivp = iv;
  270. aligned_auto(uint8_t, liv, AES_BLOCK_SIZE, 16);
  271. via_cwd(cwd, hybrid, dec, 2 * ctx->inf.b[0] - 192);
  272. if(ALIGN_OFFSET(ctx, 16)) return EXIT_FAILURE;
  273. if(ALIGN_OFFSET(iv, 16)) /* ensure an aligned iv */
  274. {
  275. ivp = liv;
  276. memcpy(liv, iv, AES_BLOCK_SIZE);
  277. }
  278. if(!ALIGN_OFFSET(ibuf, 16) && !ALIGN_OFFSET(obuf, 16) && !ALIGN_OFFSET(iv, 16)) {
  279. via_cbc_op6(ksp, cwd, ibuf, obuf, nb, ivp);
  280. } else {
  281. aligned_auto(uint8_t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
  282. uint8_t *ip = NULL, *op = NULL;
  283. while(nb) {
  284. int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb);
  285. ip = (ALIGN_OFFSET(ibuf, 16) ? buf : ibuf);
  286. op = (ALIGN_OFFSET(obuf, 16) ? buf : obuf);
  287. if(ip != ibuf) memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
  288. via_cbc_op6(ksp, cwd, ip, op, m, ivp);
  289. if(op != obuf) memcpy(obuf, buf, m * AES_BLOCK_SIZE);
  290. ibuf += m * AES_BLOCK_SIZE;
  291. obuf += m * AES_BLOCK_SIZE;
  292. nb -= m;
  293. }
  294. }
  295. if(iv != ivp) memcpy(iv, ivp, AES_BLOCK_SIZE);
  296. return EXIT_SUCCESS;
  297. }
  298. #endif
  299. #if !defined(ASSUME_VIA_ACE_PRESENT)
  300. #ifdef FAST_BUFFER_OPERATIONS
  301. if(!ALIGN_OFFSET(obuf, 4) && !ALIGN_OFFSET(iv, 4))
  302. while(nb--) {
  303. memcpy(tmp, ibuf, AES_BLOCK_SIZE);
  304. if(aes_decrypt(ibuf, obuf, ctx) != EXIT_SUCCESS) return EXIT_FAILURE;
  305. lp32(obuf)[0] ^= lp32(iv)[0];
  306. lp32(obuf)[1] ^= lp32(iv)[1];
  307. lp32(obuf)[2] ^= lp32(iv)[2];
  308. lp32(obuf)[3] ^= lp32(iv)[3];
  309. memcpy(iv, tmp, AES_BLOCK_SIZE);
  310. ibuf += AES_BLOCK_SIZE;
  311. obuf += AES_BLOCK_SIZE;
  312. }
  313. else
  314. #endif
  315. while(nb--) {
  316. memcpy(tmp, ibuf, AES_BLOCK_SIZE);
  317. if(aes_decrypt(ibuf, obuf, ctx) != EXIT_SUCCESS) return EXIT_FAILURE;
  318. obuf[0] ^= iv[0];
  319. obuf[1] ^= iv[1];
  320. obuf[2] ^= iv[2];
  321. obuf[3] ^= iv[3];
  322. obuf[4] ^= iv[4];
  323. obuf[5] ^= iv[5];
  324. obuf[6] ^= iv[6];
  325. obuf[7] ^= iv[7];
  326. obuf[8] ^= iv[8];
  327. obuf[9] ^= iv[9];
  328. obuf[10] ^= iv[10];
  329. obuf[11] ^= iv[11];
  330. obuf[12] ^= iv[12];
  331. obuf[13] ^= iv[13];
  332. obuf[14] ^= iv[14];
  333. obuf[15] ^= iv[15];
  334. memcpy(iv, tmp, AES_BLOCK_SIZE);
  335. ibuf += AES_BLOCK_SIZE;
  336. obuf += AES_BLOCK_SIZE;
  337. }
  338. #endif
  339. return EXIT_SUCCESS;
  340. }
  341. AES_RETURN aes_cfb_encrypt(
  342. const unsigned char* ibuf,
  343. unsigned char* obuf,
  344. int len,
  345. unsigned char* iv,
  346. aes_encrypt_ctx ctx[1]) {
  347. int cnt = 0, b_pos = (int)ctx->inf.b[2], nb;
  348. if(b_pos) /* complete any partial block */
  349. {
  350. while(b_pos < AES_BLOCK_SIZE && cnt < len) {
  351. *obuf++ = (iv[b_pos++] ^= *ibuf++);
  352. cnt++;
  353. }
  354. b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
  355. }
  356. if((nb = (len - cnt) >> AES_BLOCK_SIZE_P2) != 0) /* process whole blocks */
  357. {
  358. #if defined(USE_VIA_ACE_IF_PRESENT)
  359. if(ctx->inf.b[1] == 0xff) {
  360. int m;
  361. uint8_t *ksp = (uint8_t*)(ctx->ks), *ivp = iv;
  362. aligned_auto(uint8_t, liv, AES_BLOCK_SIZE, 16);
  363. via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);
  364. if(ALIGN_OFFSET(ctx, 16)) return EXIT_FAILURE;
  365. if(ALIGN_OFFSET(iv, 16)) /* ensure an aligned iv */
  366. {
  367. ivp = liv;
  368. memcpy(liv, iv, AES_BLOCK_SIZE);
  369. }
  370. if(!ALIGN_OFFSET(ibuf, 16) && !ALIGN_OFFSET(obuf, 16)) {
  371. via_cfb_op7(ksp, cwd, ibuf, obuf, nb, ivp, ivp);
  372. ibuf += nb * AES_BLOCK_SIZE;
  373. obuf += nb * AES_BLOCK_SIZE;
  374. cnt += nb * AES_BLOCK_SIZE;
  375. } else /* input, output or both are unaligned */
  376. {
  377. aligned_auto(uint8_t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
  378. uint8_t *ip = NULL, *op = NULL;
  379. while(nb) {
  380. m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb), nb -= m;
  381. ip = (ALIGN_OFFSET(ibuf, 16) ? buf : ibuf);
  382. op = (ALIGN_OFFSET(obuf, 16) ? buf : obuf);
  383. if(ip != ibuf) memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
  384. via_cfb_op7(ksp, cwd, ip, op, m, ivp, ivp);
  385. if(op != obuf) memcpy(obuf, buf, m * AES_BLOCK_SIZE);
  386. ibuf += m * AES_BLOCK_SIZE;
  387. obuf += m * AES_BLOCK_SIZE;
  388. cnt += m * AES_BLOCK_SIZE;
  389. }
  390. }
  391. if(ivp != iv) memcpy(iv, ivp, AES_BLOCK_SIZE);
  392. }
  393. #else
  394. #ifdef FAST_BUFFER_OPERATIONS
  395. if(!ALIGN_OFFSET(ibuf, 4) && !ALIGN_OFFSET(obuf, 4) && !ALIGN_OFFSET(iv, 4))
  396. while(cnt + AES_BLOCK_SIZE <= len) {
  397. assert(b_pos == 0);
  398. if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) return EXIT_FAILURE;
  399. lp32(obuf)[0] = lp32(iv)[0] ^= lp32(ibuf)[0];
  400. lp32(obuf)[1] = lp32(iv)[1] ^= lp32(ibuf)[1];
  401. lp32(obuf)[2] = lp32(iv)[2] ^= lp32(ibuf)[2];
  402. lp32(obuf)[3] = lp32(iv)[3] ^= lp32(ibuf)[3];
  403. ibuf += AES_BLOCK_SIZE;
  404. obuf += AES_BLOCK_SIZE;
  405. cnt += AES_BLOCK_SIZE;
  406. }
  407. else
  408. #endif
  409. while(cnt + AES_BLOCK_SIZE <= len) {
  410. assert(b_pos == 0);
  411. if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) return EXIT_FAILURE;
  412. obuf[0] = iv[0] ^= ibuf[0];
  413. obuf[1] = iv[1] ^= ibuf[1];
  414. obuf[2] = iv[2] ^= ibuf[2];
  415. obuf[3] = iv[3] ^= ibuf[3];
  416. obuf[4] = iv[4] ^= ibuf[4];
  417. obuf[5] = iv[5] ^= ibuf[5];
  418. obuf[6] = iv[6] ^= ibuf[6];
  419. obuf[7] = iv[7] ^= ibuf[7];
  420. obuf[8] = iv[8] ^= ibuf[8];
  421. obuf[9] = iv[9] ^= ibuf[9];
  422. obuf[10] = iv[10] ^= ibuf[10];
  423. obuf[11] = iv[11] ^= ibuf[11];
  424. obuf[12] = iv[12] ^= ibuf[12];
  425. obuf[13] = iv[13] ^= ibuf[13];
  426. obuf[14] = iv[14] ^= ibuf[14];
  427. obuf[15] = iv[15] ^= ibuf[15];
  428. ibuf += AES_BLOCK_SIZE;
  429. obuf += AES_BLOCK_SIZE;
  430. cnt += AES_BLOCK_SIZE;
  431. }
  432. #endif
  433. }
  434. while(cnt < len) {
  435. if(!b_pos && aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) return EXIT_FAILURE;
  436. while(cnt < len && b_pos < AES_BLOCK_SIZE) {
  437. *obuf++ = (iv[b_pos++] ^= *ibuf++);
  438. cnt++;
  439. }
  440. b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
  441. }
  442. ctx->inf.b[2] = (uint8_t)b_pos;
  443. return EXIT_SUCCESS;
  444. }
  445. AES_RETURN aes_cfb_decrypt(
  446. const unsigned char* ibuf,
  447. unsigned char* obuf,
  448. int len,
  449. unsigned char* iv,
  450. aes_encrypt_ctx ctx[1]) {
  451. int cnt = 0, b_pos = (int)ctx->inf.b[2], nb;
  452. if(b_pos) /* complete any partial block */
  453. {
  454. uint8_t t;
  455. while(b_pos < AES_BLOCK_SIZE && cnt < len) {
  456. t = *ibuf++;
  457. *obuf++ = t ^ iv[b_pos];
  458. iv[b_pos++] = t;
  459. cnt++;
  460. }
  461. b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
  462. }
  463. if((nb = (len - cnt) >> AES_BLOCK_SIZE_P2) != 0) /* process whole blocks */
  464. {
  465. #if defined(USE_VIA_ACE_IF_PRESENT)
  466. if(ctx->inf.b[1] == 0xff) {
  467. int m;
  468. uint8_t *ksp = (uint8_t*)(ctx->ks), *ivp = iv;
  469. aligned_auto(uint8_t, liv, AES_BLOCK_SIZE, 16);
  470. via_cwd(cwd, hybrid, dec, 2 * ctx->inf.b[0] - 192);
  471. if(ALIGN_OFFSET(ctx, 16)) return EXIT_FAILURE;
  472. if(ALIGN_OFFSET(iv, 16)) /* ensure an aligned iv */
  473. {
  474. ivp = liv;
  475. memcpy(liv, iv, AES_BLOCK_SIZE);
  476. }
  477. if(!ALIGN_OFFSET(ibuf, 16) && !ALIGN_OFFSET(obuf, 16)) {
  478. via_cfb_op6(ksp, cwd, ibuf, obuf, nb, ivp);
  479. ibuf += nb * AES_BLOCK_SIZE;
  480. obuf += nb * AES_BLOCK_SIZE;
  481. cnt += nb * AES_BLOCK_SIZE;
  482. } else /* input, output or both are unaligned */
  483. {
  484. aligned_auto(uint8_t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
  485. uint8_t *ip = NULL, *op = NULL;
  486. while(nb) {
  487. m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb), nb -= m;
  488. ip = (ALIGN_OFFSET(ibuf, 16) ? buf : ibuf);
  489. op = (ALIGN_OFFSET(obuf, 16) ? buf : obuf);
  490. if(ip != ibuf) /* input buffer is not aligned */
  491. memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
  492. via_cfb_op6(ksp, cwd, ip, op, m, ivp);
  493. if(op != obuf) /* output buffer is not aligned */
  494. memcpy(obuf, buf, m * AES_BLOCK_SIZE);
  495. ibuf += m * AES_BLOCK_SIZE;
  496. obuf += m * AES_BLOCK_SIZE;
  497. cnt += m * AES_BLOCK_SIZE;
  498. }
  499. }
  500. if(ivp != iv) memcpy(iv, ivp, AES_BLOCK_SIZE);
  501. }
  502. #else
  503. #ifdef FAST_BUFFER_OPERATIONS
  504. if(!ALIGN_OFFSET(ibuf, 4) && !ALIGN_OFFSET(obuf, 4) && !ALIGN_OFFSET(iv, 4))
  505. while(cnt + AES_BLOCK_SIZE <= len) {
  506. uint32_t t;
  507. assert(b_pos == 0);
  508. if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) return EXIT_FAILURE;
  509. t = lp32(ibuf)[0], lp32(obuf)[0] = t ^ lp32(iv)[0], lp32(iv)[0] = t;
  510. t = lp32(ibuf)[1], lp32(obuf)[1] = t ^ lp32(iv)[1], lp32(iv)[1] = t;
  511. t = lp32(ibuf)[2], lp32(obuf)[2] = t ^ lp32(iv)[2], lp32(iv)[2] = t;
  512. t = lp32(ibuf)[3], lp32(obuf)[3] = t ^ lp32(iv)[3], lp32(iv)[3] = t;
  513. ibuf += AES_BLOCK_SIZE;
  514. obuf += AES_BLOCK_SIZE;
  515. cnt += AES_BLOCK_SIZE;
  516. }
  517. else
  518. #endif
  519. while(cnt + AES_BLOCK_SIZE <= len) {
  520. uint8_t t;
  521. assert(b_pos == 0);
  522. if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) return EXIT_FAILURE;
  523. t = ibuf[0], obuf[0] = t ^ iv[0], iv[0] = t;
  524. t = ibuf[1], obuf[1] = t ^ iv[1], iv[1] = t;
  525. t = ibuf[2], obuf[2] = t ^ iv[2], iv[2] = t;
  526. t = ibuf[3], obuf[3] = t ^ iv[3], iv[3] = t;
  527. t = ibuf[4], obuf[4] = t ^ iv[4], iv[4] = t;
  528. t = ibuf[5], obuf[5] = t ^ iv[5], iv[5] = t;
  529. t = ibuf[6], obuf[6] = t ^ iv[6], iv[6] = t;
  530. t = ibuf[7], obuf[7] = t ^ iv[7], iv[7] = t;
  531. t = ibuf[8], obuf[8] = t ^ iv[8], iv[8] = t;
  532. t = ibuf[9], obuf[9] = t ^ iv[9], iv[9] = t;
  533. t = ibuf[10], obuf[10] = t ^ iv[10], iv[10] = t;
  534. t = ibuf[11], obuf[11] = t ^ iv[11], iv[11] = t;
  535. t = ibuf[12], obuf[12] = t ^ iv[12], iv[12] = t;
  536. t = ibuf[13], obuf[13] = t ^ iv[13], iv[13] = t;
  537. t = ibuf[14], obuf[14] = t ^ iv[14], iv[14] = t;
  538. t = ibuf[15], obuf[15] = t ^ iv[15], iv[15] = t;
  539. ibuf += AES_BLOCK_SIZE;
  540. obuf += AES_BLOCK_SIZE;
  541. cnt += AES_BLOCK_SIZE;
  542. }
  543. #endif
  544. }
  545. while(cnt < len) {
  546. uint8_t t;
  547. if(!b_pos && aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) return EXIT_FAILURE;
  548. while(cnt < len && b_pos < AES_BLOCK_SIZE) {
  549. t = *ibuf++;
  550. *obuf++ = t ^ iv[b_pos];
  551. iv[b_pos++] = t;
  552. cnt++;
  553. }
  554. b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
  555. }
  556. ctx->inf.b[2] = (uint8_t)b_pos;
  557. return EXIT_SUCCESS;
  558. }
  559. AES_RETURN aes_ofb_crypt(
  560. const unsigned char* ibuf,
  561. unsigned char* obuf,
  562. int len,
  563. unsigned char* iv,
  564. aes_encrypt_ctx ctx[1]) {
  565. int cnt = 0, b_pos = (int)ctx->inf.b[2], nb;
  566. if(b_pos) /* complete any partial block */
  567. {
  568. while(b_pos < AES_BLOCK_SIZE && cnt < len) {
  569. *obuf++ = iv[b_pos++] ^ *ibuf++;
  570. cnt++;
  571. }
  572. b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
  573. }
  574. if((nb = (len - cnt) >> AES_BLOCK_SIZE_P2) != 0) /* process whole blocks */
  575. {
  576. #if defined(USE_VIA_ACE_IF_PRESENT)
  577. if(ctx->inf.b[1] == 0xff) {
  578. int m;
  579. uint8_t *ksp = (uint8_t*)(ctx->ks), *ivp = iv;
  580. aligned_auto(uint8_t, liv, AES_BLOCK_SIZE, 16);
  581. via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);
  582. if(ALIGN_OFFSET(ctx, 16)) return EXIT_FAILURE;
  583. if(ALIGN_OFFSET(iv, 16)) /* ensure an aligned iv */
  584. {
  585. ivp = liv;
  586. memcpy(liv, iv, AES_BLOCK_SIZE);
  587. }
  588. if(!ALIGN_OFFSET(ibuf, 16) && !ALIGN_OFFSET(obuf, 16)) {
  589. via_ofb_op6(ksp, cwd, ibuf, obuf, nb, ivp);
  590. ibuf += nb * AES_BLOCK_SIZE;
  591. obuf += nb * AES_BLOCK_SIZE;
  592. cnt += nb * AES_BLOCK_SIZE;
  593. } else /* input, output or both are unaligned */
  594. {
  595. aligned_auto(uint8_t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
  596. uint8_t *ip = NULL, *op = NULL;
  597. while(nb) {
  598. m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb), nb -= m;
  599. ip = (ALIGN_OFFSET(ibuf, 16) ? buf : ibuf);
  600. op = (ALIGN_OFFSET(obuf, 16) ? buf : obuf);
  601. if(ip != ibuf) memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
  602. via_ofb_op6(ksp, cwd, ip, op, m, ivp);
  603. if(op != obuf) memcpy(obuf, buf, m * AES_BLOCK_SIZE);
  604. ibuf += m * AES_BLOCK_SIZE;
  605. obuf += m * AES_BLOCK_SIZE;
  606. cnt += m * AES_BLOCK_SIZE;
  607. }
  608. }
  609. if(ivp != iv) memcpy(iv, ivp, AES_BLOCK_SIZE);
  610. }
  611. #else
  612. #ifdef FAST_BUFFER_OPERATIONS
  613. if(!ALIGN_OFFSET(ibuf, 4) && !ALIGN_OFFSET(obuf, 4) && !ALIGN_OFFSET(iv, 4))
  614. while(cnt + AES_BLOCK_SIZE <= len) {
  615. assert(b_pos == 0);
  616. if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) return EXIT_FAILURE;
  617. lp32(obuf)[0] = lp32(iv)[0] ^ lp32(ibuf)[0];
  618. lp32(obuf)[1] = lp32(iv)[1] ^ lp32(ibuf)[1];
  619. lp32(obuf)[2] = lp32(iv)[2] ^ lp32(ibuf)[2];
  620. lp32(obuf)[3] = lp32(iv)[3] ^ lp32(ibuf)[3];
  621. ibuf += AES_BLOCK_SIZE;
  622. obuf += AES_BLOCK_SIZE;
  623. cnt += AES_BLOCK_SIZE;
  624. }
  625. else
  626. #endif
  627. while(cnt + AES_BLOCK_SIZE <= len) {
  628. assert(b_pos == 0);
  629. if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) return EXIT_FAILURE;
  630. obuf[0] = iv[0] ^ ibuf[0];
  631. obuf[1] = iv[1] ^ ibuf[1];
  632. obuf[2] = iv[2] ^ ibuf[2];
  633. obuf[3] = iv[3] ^ ibuf[3];
  634. obuf[4] = iv[4] ^ ibuf[4];
  635. obuf[5] = iv[5] ^ ibuf[5];
  636. obuf[6] = iv[6] ^ ibuf[6];
  637. obuf[7] = iv[7] ^ ibuf[7];
  638. obuf[8] = iv[8] ^ ibuf[8];
  639. obuf[9] = iv[9] ^ ibuf[9];
  640. obuf[10] = iv[10] ^ ibuf[10];
  641. obuf[11] = iv[11] ^ ibuf[11];
  642. obuf[12] = iv[12] ^ ibuf[12];
  643. obuf[13] = iv[13] ^ ibuf[13];
  644. obuf[14] = iv[14] ^ ibuf[14];
  645. obuf[15] = iv[15] ^ ibuf[15];
  646. ibuf += AES_BLOCK_SIZE;
  647. obuf += AES_BLOCK_SIZE;
  648. cnt += AES_BLOCK_SIZE;
  649. }
  650. #endif
  651. }
  652. while(cnt < len) {
  653. if(!b_pos && aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) return EXIT_FAILURE;
  654. while(cnt < len && b_pos < AES_BLOCK_SIZE) {
  655. *obuf++ = iv[b_pos++] ^ *ibuf++;
  656. cnt++;
  657. }
  658. b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
  659. }
  660. ctx->inf.b[2] = (uint8_t)b_pos;
  661. return EXIT_SUCCESS;
  662. }
  663. #define BFR_LENGTH (BFR_BLOCKS * AES_BLOCK_SIZE)
  664. AES_RETURN aes_ctr_crypt(
  665. const unsigned char* ibuf,
  666. unsigned char* obuf,
  667. int len,
  668. unsigned char* cbuf,
  669. cbuf_inc ctr_inc,
  670. aes_encrypt_ctx ctx[1]) {
  671. unsigned char* ip;
  672. int i = 0, blen = 0, b_pos = (int)(ctx->inf.b[2]);
  673. #if defined(USE_VIA_ACE_IF_PRESENT)
  674. aligned_auto(uint8_t, buf, BFR_LENGTH, 16);
  675. if(ctx->inf.b[1] == 0xff && ALIGN_OFFSET(ctx, 16)) return EXIT_FAILURE;
  676. #else
  677. uint8_t buf[BFR_LENGTH] = {0};
  678. #endif
  679. if(b_pos) {
  680. memcpy(buf, cbuf, AES_BLOCK_SIZE);
  681. if(aes_ecb_encrypt(buf, buf, AES_BLOCK_SIZE, ctx) != EXIT_SUCCESS) return EXIT_FAILURE;
  682. while(b_pos < AES_BLOCK_SIZE && len) {
  683. *obuf++ = *ibuf++ ^ buf[b_pos++];
  684. --len;
  685. }
  686. if(len) ctr_inc(cbuf), b_pos = 0;
  687. }
  688. while(len) {
  689. blen = (len > BFR_LENGTH ? BFR_LENGTH : len), len -= blen;
  690. for(i = 0, ip = buf; i < (blen >> AES_BLOCK_SIZE_P2); ++i) {
  691. memcpy(ip, cbuf, AES_BLOCK_SIZE);
  692. ctr_inc(cbuf);
  693. ip += AES_BLOCK_SIZE;
  694. }
  695. if(blen & (AES_BLOCK_SIZE - 1)) memcpy(ip, cbuf, AES_BLOCK_SIZE), i++;
  696. #if defined(USE_VIA_ACE_IF_PRESENT)
  697. if(ctx->inf.b[1] == 0xff) {
  698. via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);
  699. via_ecb_op5((ctx->ks), cwd, buf, buf, i);
  700. } else
  701. #endif
  702. if(aes_ecb_encrypt(buf, buf, i * AES_BLOCK_SIZE, ctx) != EXIT_SUCCESS)
  703. return EXIT_FAILURE;
  704. i = 0;
  705. ip = buf;
  706. #ifdef FAST_BUFFER_OPERATIONS
  707. if(!ALIGN_OFFSET(ibuf, 4) && !ALIGN_OFFSET(obuf, 4) && !ALIGN_OFFSET(ip, 4))
  708. while(i + AES_BLOCK_SIZE <= blen) {
  709. lp32(obuf)[0] = lp32(ibuf)[0] ^ lp32(ip)[0];
  710. lp32(obuf)[1] = lp32(ibuf)[1] ^ lp32(ip)[1];
  711. lp32(obuf)[2] = lp32(ibuf)[2] ^ lp32(ip)[2];
  712. lp32(obuf)[3] = lp32(ibuf)[3] ^ lp32(ip)[3];
  713. i += AES_BLOCK_SIZE;
  714. ip += AES_BLOCK_SIZE;
  715. ibuf += AES_BLOCK_SIZE;
  716. obuf += AES_BLOCK_SIZE;
  717. }
  718. else
  719. #endif
  720. while(i + AES_BLOCK_SIZE <= blen) {
  721. obuf[0] = ibuf[0] ^ ip[0];
  722. obuf[1] = ibuf[1] ^ ip[1];
  723. obuf[2] = ibuf[2] ^ ip[2];
  724. obuf[3] = ibuf[3] ^ ip[3];
  725. obuf[4] = ibuf[4] ^ ip[4];
  726. obuf[5] = ibuf[5] ^ ip[5];
  727. obuf[6] = ibuf[6] ^ ip[6];
  728. obuf[7] = ibuf[7] ^ ip[7];
  729. obuf[8] = ibuf[8] ^ ip[8];
  730. obuf[9] = ibuf[9] ^ ip[9];
  731. obuf[10] = ibuf[10] ^ ip[10];
  732. obuf[11] = ibuf[11] ^ ip[11];
  733. obuf[12] = ibuf[12] ^ ip[12];
  734. obuf[13] = ibuf[13] ^ ip[13];
  735. obuf[14] = ibuf[14] ^ ip[14];
  736. obuf[15] = ibuf[15] ^ ip[15];
  737. i += AES_BLOCK_SIZE;
  738. ip += AES_BLOCK_SIZE;
  739. ibuf += AES_BLOCK_SIZE;
  740. obuf += AES_BLOCK_SIZE;
  741. }
  742. while(i++ < blen) *obuf++ = *ibuf++ ^ ip[b_pos++];
  743. }
  744. ctx->inf.b[2] = (uint8_t)b_pos;
  745. return EXIT_SUCCESS;
  746. }
  747. void aes_ctr_cbuf_inc(unsigned char* cbuf) {
  748. int i = AES_BLOCK_SIZE - 1;
  749. while(i >= 0) {
  750. cbuf[i]++;
  751. if(cbuf[i]) return; // if there was no overflow
  752. i--;
  753. }
  754. }
  755. #if defined(__cplusplus)
  756. }
  757. #endif
  758. #endif