aes_modes.c 30 KB

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