echo.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. /* echo.c */
  2. /*
  3. This file is part of the ARM-Crypto-Lib.
  4. Copyright (C) 2006-2010 Daniel Otte (daniel.otte@rub.de)
  5. This program is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 3 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include <crypto/echo.h>
  17. #include <crypto/gf256mul.h>
  18. #include <crypto/memxor.h>
  19. #include <crypto/aes_enc_round.h>
  20. #include <stdint.h>
  21. #include <string.h>
  22. #ifdef DEBUG
  23. #undef DEBUG
  24. #endif
  25. #define DEBUG 0
  26. #if DEBUG
  27. #define DEBUG_DEPTH 2
  28. #include <crypto/cli.h>
  29. #endif
  30. #define INDEX(c,r) ((c)*16*4+(r)*16)
  31. #define GF256MUL_1(a) (a)
  32. #define GF256MUL_2(a) (gf256mul(2, (a), 0x1b))
  33. #define GF256MUL_3(a) (gf256mul(3, (a), 0x1b))
  34. static void mixcol(uint8_t* s){
  35. uint8_t t, tmp[4];
  36. tmp[0] = *(s+16*0);
  37. tmp[1] = *(s+16*1);
  38. tmp[2] = *(s+16*2);
  39. tmp[3] = *(s+16*3);
  40. t = tmp[0] ^ tmp[1] ^ tmp[2] ^ tmp[3];
  41. *(s+16*0) =
  42. GF256MUL_2(tmp[0]^tmp[1])
  43. ^ tmp[0]
  44. ^ t;
  45. *(s+16*1) =
  46. GF256MUL_2(tmp[1]^tmp[2])
  47. ^ tmp[1]
  48. ^ t;
  49. *(s+16*2) =
  50. GF256MUL_2(tmp[2]^tmp[3])
  51. ^ tmp[2]
  52. ^ t;
  53. *(s+16*3) =
  54. GF256MUL_2(tmp[3]^tmp[0])
  55. ^ tmp[3]
  56. ^ t;
  57. }
  58. #if DEBUG
  59. static void dump_state(void* s){
  60. uint8_t row, col;
  61. for(col=0; col<4; col++){
  62. for(row=0; row<4; row++){
  63. cli_putstr("\r\nrow ");
  64. cli_putc('0'+row);
  65. cli_putstr(", col ");
  66. cli_putc('0'+col);
  67. cli_putstr(": ");
  68. cli_hexdump((uint8_t*)s+col*16*4+row*16, 4);
  69. cli_putc(' ');
  70. cli_hexdump((uint8_t*)s+col*16*4+row*16+ 4, 4);
  71. cli_putc(' ');
  72. cli_hexdump((uint8_t*)s+col*16*4+row*16+ 8, 4);
  73. cli_putc(' ');
  74. cli_hexdump((uint8_t*)s+col*16*4+row*16+12, 4);
  75. }
  76. }
  77. }
  78. #endif
  79. static void echo_compress(uint8_t* s, uint8_t iterations, uint64_t* c, void* salt){
  80. uint8_t i, j;
  81. union {
  82. uint8_t v8[16];
  83. uint64_t v64[2];
  84. } k;
  85. #if DEBUG
  86. uint8_t round=0;
  87. #endif
  88. memcpy(k.v8, c, 8);
  89. memset(k.v8+8, 0, 8);
  90. do{
  91. /* BIG.SubWords */
  92. #if DEBUG
  93. cli_putstr("\r\n === ROUND ");
  94. cli_putc('0'+round);
  95. cli_putstr(" ===");
  96. if(round<DEBUG_DEPTH){
  97. dump_state(s);
  98. }
  99. #endif
  100. for(i=0; i<16; ++i){
  101. aes_enc_round((aes_cipher_state_t*)(s+16*i), (aes_roundkey_t*)k.v8);
  102. aes_enc_round((aes_cipher_state_t*)(s+16*i), (aes_roundkey_t*)salt);
  103. k.v64[0] += 1;
  104. }
  105. #if DEBUG
  106. if(round<DEBUG_DEPTH){
  107. cli_putstr("\r\nAfter SubWords");
  108. dump_state(s);
  109. }
  110. #endif
  111. /* BIG.ShiftRows */
  112. uint8_t t[16];
  113. /* "Row" 1 */
  114. memcpy(t, s+INDEX(0, 1), 16);
  115. memcpy(s+INDEX(0, 1), s+INDEX(1, 1), 16);
  116. memcpy(s+INDEX(1, 1), s+INDEX(2, 1), 16);
  117. memcpy(s+INDEX(2, 1), s+INDEX(3, 1), 16);
  118. memcpy(s+INDEX(3, 1), t, 16);
  119. /* "Row" 2 */
  120. memcpy(t, s+INDEX(0, 2), 16);
  121. memcpy(s+INDEX(0, 2), s+INDEX(2, 2), 16);
  122. memcpy(s+INDEX(2, 2), t, 16);
  123. memcpy(t, s+INDEX(1, 2), 16);
  124. memcpy(s+INDEX(1, 2), s+INDEX(3, 2), 16);
  125. memcpy(s+INDEX(3, 2), t, 16);
  126. /* "Row" 3 */
  127. memcpy(t, s+INDEX(0, 3), 16);
  128. memcpy(s+INDEX(0, 3), s+INDEX(3, 3), 16);
  129. memcpy(s+INDEX(3, 3), s+INDEX(2, 3), 16);
  130. memcpy(s+INDEX(2, 3), s+INDEX(1, 3), 16);
  131. memcpy(s+INDEX(1, 3), t, 16);
  132. #if DEBUG
  133. if(round<DEBUG_DEPTH){
  134. cli_putstr("\r\nAfter ShiftRows");
  135. dump_state(s);
  136. }
  137. #endif
  138. /* BIG.MixColumns */
  139. for(i=0; i<4; i+=1){
  140. for(j=0; j<16; ++j){
  141. mixcol(s+i*64+j);
  142. }
  143. }
  144. #if DEBUG
  145. if(round<DEBUG_DEPTH){
  146. cli_putstr("\r\nAfter MixColumns");
  147. dump_state(s);
  148. }
  149. round++;
  150. #endif
  151. }while(--iterations);
  152. }
  153. /******************************************************************************/
  154. static void compress512(void* v, void* m, uint64_t* c, void* salt){
  155. uint8_t s[16*16];
  156. uint8_t i;
  157. memcpy(s, v, 16*4); /* load v into state */
  158. memcpy(s+16*4, m, 16*12); /* load m into state */
  159. echo_compress(s, 8, c, salt);
  160. /* BIG.Final */
  161. for(i=0; i<3; ++i){
  162. memxor(v, (uint8_t*)m+4*16*i, 4*16);
  163. }
  164. for(i=0; i<4; ++i){
  165. memxor(v, s+4*16*i, 4*16);
  166. }
  167. }
  168. static void compress1024(void* v, void* m, uint64_t* c, void* salt){
  169. uint8_t s[16*16];
  170. memcpy(s, v, 16*8); /* load v into state */
  171. memcpy(s+16*8, m, 16*8); /* load m into state */
  172. echo_compress(s, 10, c, salt);
  173. /* BIG.Final */
  174. memxor(v, m, 16*8);
  175. memxor(v, s, 16*8);
  176. memxor(v, s+16*8, 16*8);
  177. }
  178. /******************************************************************************/
  179. void echo_small_nextBlock(echo_small_ctx_t* ctx, void* block){
  180. ctx->counter += ECHO_SMALL_BLOCKSIZE;
  181. compress512(ctx->v, block, &(ctx->counter), ctx->salt);
  182. }
  183. void echo_small_lastBlock(echo_small_ctx_t* ctx, void* block, uint16_t length_b){
  184. while(length_b>=ECHO_SMALL_BLOCKSIZE){
  185. echo_small_nextBlock(ctx, block);
  186. block = (uint8_t*)block + ECHO_SMALL_BLOCKSIZE_B;
  187. length_b -= ECHO_SMALL_BLOCKSIZE;
  188. }
  189. uint8_t buffer[ECHO_SMALL_BLOCKSIZE_B];
  190. uint64_t total_len;
  191. memset(buffer, 0, ECHO_SMALL_BLOCKSIZE_B);
  192. memcpy(buffer, block, (length_b+7)/8);
  193. buffer[length_b/8] |= 0x80 >> (length_b&7);
  194. total_len = (ctx->counter += length_b);
  195. if(length_b>=ECHO_SMALL_BLOCKSIZE-144){
  196. compress512(ctx->v, buffer, &total_len, ctx->salt);
  197. memset(buffer, 0, ECHO_SMALL_BLOCKSIZE_B);
  198. ctx->counter = 0;
  199. }
  200. if(length_b==0){
  201. ctx->counter = 0;
  202. }
  203. memcpy(buffer+ECHO_SMALL_BLOCKSIZE_B-18, &(ctx->id), 2);
  204. memcpy(buffer+ECHO_SMALL_BLOCKSIZE_B-16, &total_len, 8);
  205. compress512(ctx->v, buffer, &(ctx->counter), ctx->salt);
  206. }
  207. /******************************************************************************/
  208. void echo_large_nextBlock(echo_large_ctx_t* ctx, void* block){
  209. ctx->counter += ECHO_LARGE_BLOCKSIZE;
  210. compress1024(ctx->v, block, &(ctx->counter), ctx->salt);
  211. }
  212. void echo_large_lastBlock(echo_large_ctx_t* ctx, void* block, uint16_t length_b){
  213. while(length_b>=ECHO_LARGE_BLOCKSIZE){
  214. echo_large_nextBlock(ctx, block);
  215. block = (uint8_t*)block + ECHO_LARGE_BLOCKSIZE_B;
  216. length_b -= ECHO_LARGE_BLOCKSIZE;
  217. }
  218. uint8_t buffer[ECHO_LARGE_BLOCKSIZE_B];
  219. uint64_t total_len;
  220. memset(buffer, 0, ECHO_LARGE_BLOCKSIZE_B);
  221. memcpy(buffer, block, (length_b+7)/8);
  222. buffer[length_b/8] |= 0x80 >> (length_b&7);
  223. total_len = (ctx->counter += length_b);
  224. if(length_b>=ECHO_LARGE_BLOCKSIZE-144){
  225. compress1024(ctx->v, buffer, &total_len, ctx->salt);
  226. memset(buffer, 0, ECHO_LARGE_BLOCKSIZE_B);
  227. ctx->counter = 0;
  228. }
  229. if(length_b==0){
  230. ctx->counter = 0;
  231. }
  232. memcpy(buffer+ECHO_LARGE_BLOCKSIZE_B-18, &(ctx->id), 2);
  233. memcpy(buffer+ECHO_LARGE_BLOCKSIZE_B-16, &total_len, 8);
  234. compress1024(ctx->v, buffer, &(ctx->counter), ctx->salt);
  235. }
  236. /******************************************************************************/
  237. void echo_ctx2hash(void* dest, uint16_t length_b, echo_small_ctx_t* ctx){
  238. memcpy(dest, ctx->v, (length_b+7)/8);
  239. }
  240. void echo224_ctx2hash(void* dest, echo_small_ctx_t* ctx){
  241. memcpy(dest, ctx->v, 224/8);
  242. }
  243. void echo256_ctx2hash(void* dest, echo_small_ctx_t* ctx){
  244. memcpy(dest, ctx->v, 256/8);
  245. }
  246. /******************************************************************************/
  247. void echo384_ctx2hash(void* dest, echo_large_ctx_t* ctx){
  248. memcpy(dest, ctx->v, 384/8);
  249. }
  250. void echo512_ctx2hash(void* dest, echo_large_ctx_t* ctx){
  251. memcpy(dest, ctx->v, 512/8);
  252. }
  253. /******************************************************************************/
  254. void echo224_init(echo_small_ctx_t* ctx){
  255. memset(ctx->v, 0, 4*16);
  256. ctx->counter = 0;
  257. memset(ctx->salt, 0, 16);
  258. ctx->id = 0x00E0;
  259. ctx->v[0+16*0] = 0xE0;
  260. ctx->v[0+16*1] = 0xE0;
  261. ctx->v[0+16*2] = 0xE0;
  262. ctx->v[0+16*3] = 0xE0;
  263. }
  264. void echo256_init(echo_small_ctx_t* ctx){
  265. memset(ctx->v, 0, 4*16);
  266. ctx->counter = 0;
  267. memset(ctx->salt, 0, 16);
  268. ctx->id = 0x0100;
  269. ctx->v[1+16*0] = 0x01;
  270. ctx->v[1+16*1] = 0x01;
  271. ctx->v[1+16*2] = 0x01;
  272. ctx->v[1+16*3] = 0x01;
  273. }
  274. /******************************************************************************/
  275. void echo384_init(echo_large_ctx_t* ctx){
  276. uint8_t i;
  277. memset(ctx->v, 0, 8*16);
  278. ctx->counter = 0;
  279. memset(ctx->salt, 0, 16);
  280. ctx->id = 0x0180;
  281. for(i=0; i<8; ++i){
  282. ctx->v[0+16*i] = 0x80;
  283. ctx->v[1+16*i] = 0x01;
  284. }
  285. }
  286. void echo512_init(echo_large_ctx_t* ctx){
  287. uint8_t i;
  288. memset(ctx->v, 0, 8*16);
  289. ctx->counter = 0;
  290. memset(ctx->salt, 0, 16);
  291. ctx->id = 0x0200;
  292. for(i=0; i<8; ++i){
  293. ctx->v[1+16*i] = 0x02;
  294. }
  295. }
  296. /******************************************************************************/