rabbit_c.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. /* rabbit_c.c */
  2. /*
  3. This file is part of the ARM-Crypto-Lib.
  4. Copyright (C) 2006-2011 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 <string.h>
  17. #include <stdint.h>
  18. #include <crypto/rabbit.h>
  19. #ifndef ESTREAM
  20. #define ESTREAM 0
  21. #endif
  22. /*
  23. void dump_ctx(rabbit_ctx_t* ctx){
  24. uint8_t i=0;
  25. cli_putstr_P(PSTR("\r\n --- ctx dump ---\r\n b = "));
  26. cli_hexdump_byte(ctx->carry);
  27. do{
  28. if((i&3)==0){
  29. cli_putstr_P(PSTR("\r\n"));
  30. }
  31. cli_putstr_P(PSTR(" X"));
  32. cli_hexdump_byte(i);
  33. cli_putstr_P(PSTR(" = 0x"));
  34. cli_hexdump_rev(&(ctx->x[i]), 4);
  35. }while(++i<8);
  36. i=0;
  37. do{
  38. if((i&3)==0){
  39. cli_putstr_P(PSTR("\r\n"));
  40. }
  41. cli_putstr_P(PSTR(" C"));
  42. cli_hexdump_byte(i);
  43. cli_putstr_P(PSTR(" = 0x"));
  44. cli_hexdump_rev(&(ctx->c[i]), 4);
  45. }while(++i<8);
  46. }
  47. */
  48. static
  49. const uint32_t c_const[8] = {
  50. 0x4D34D34D, 0xD34D34D3,
  51. 0x34D34D34, 0x4D34D34D,
  52. 0xD34D34D3, 0x34D34D34,
  53. 0x4D34D34D, 0xD34D34D3
  54. };
  55. static
  56. void gen_g(uint32_t* dest, rabbit_ctx_t* ctx){
  57. uint8_t i=0;
  58. uint64_t a;
  59. uint32_t t, *x, *c;
  60. x = ctx->x;
  61. c = ctx->c;
  62. do{
  63. t = *x++ + *c++;
  64. a = ((uint64_t)t)*((uint64_t)t);
  65. dest[i] = (uint32_t)(a^(a>>32));
  66. }while(++i<8);
  67. }
  68. static
  69. void update_c(rabbit_ctx_t* ctx){
  70. uint8_t i=0;
  71. uint64_t a;
  72. uint32_t *c;
  73. const uint32_t *con;
  74. c = ctx->c;
  75. con = c_const;
  76. a = ctx->carry;
  77. do{
  78. a += *c;
  79. a += *con++;
  80. *c++ = (uint32_t)a;
  81. a >>= 32;
  82. }while(++i<8);
  83. ctx->carry = a?1:0;
  84. }
  85. #define ROT16(a) (((a)<<16) | ((a)>>16))
  86. #define ROT8(a) (((a)<< 8) | ((a)>>24))
  87. static
  88. void step(rabbit_ctx_t* ctx){
  89. uint32_t g[8];
  90. uint8_t i=0;
  91. update_c(ctx);
  92. gen_g(g, ctx);
  93. memcpy(ctx->x, g, 8*4);
  94. do{
  95. ctx->x[i] += ROT16(g[(i+8-1)%8]) + ROT16(g[(i+8-2)%8]);
  96. ++i;
  97. ctx->x[i] += ROT8(g[(i+8-1)%8]) + g[(i+8-2)%8];
  98. }while(++i<8);
  99. }
  100. static
  101. void keysetup(rabbit_ctx_t* ctx, const void* key){
  102. uint16_t *x, *c;
  103. uint8_t i=0;
  104. x = (uint16_t*)(ctx->x);
  105. c = (uint16_t*)(ctx->c);
  106. ctx->carry = 0;
  107. do{
  108. *x++ = ((uint16_t*)key)[i];
  109. *x++ = ((uint16_t*)key)[(i+1)%8];
  110. *c++ = ((uint16_t*)key)[(i+5)%8];
  111. *c++ = ((uint16_t*)key)[(i+4)%8];
  112. ++i;
  113. *x++ = ((uint16_t*)key)[(i+4)%8];
  114. *x++ = ((uint16_t*)key)[(i+5)%8];
  115. *c++ = ((uint16_t*)key)[(i+1)%8];
  116. *c++ = ((uint16_t*)key)[i];
  117. }while(++i<8);
  118. i=0;
  119. do{
  120. step(ctx);
  121. }while(++i<4);
  122. i=0;
  123. do{
  124. ctx->c[i] ^= ctx->x[(i+4)%8];
  125. }while(++i<8);
  126. }
  127. static
  128. void ivsetup(rabbit_ctx_t* ctx, const void* iv){
  129. uint8_t i;
  130. uint32_t t;
  131. union __attribute__((packed)){
  132. uint8_t v8[8];
  133. uint16_t v16[4];
  134. uint32_t v32[2];
  135. }t_iv;
  136. i=0;
  137. #if ESTREAM
  138. memcpy(t_iv.v8, iv, 8);
  139. #else
  140. do{
  141. t_iv.v8[i] = ((uint8_t*)iv)[7-i];
  142. t_iv.v8[7-i] = ((uint8_t*)iv)[i];
  143. }while(++i<4);
  144. #endif
  145. ctx->c[0] ^= t_iv.v32[0];
  146. ctx->c[4] ^= t_iv.v32[0];
  147. ctx->c[2] ^= t_iv.v32[1];
  148. ctx->c[6] ^= t_iv.v32[1];
  149. t = ( ((uint32_t)(t_iv.v16[3]))<<16) | (t_iv.v16[1]);
  150. ctx->c[1] ^= t;
  151. ctx->c[5] ^= t;
  152. t = ( ((uint32_t)(t_iv.v16[2]))<<16) | (t_iv.v16[0]);
  153. ctx->c[3] ^= t;
  154. ctx->c[7] ^= t;
  155. i=4;
  156. do{
  157. step(ctx);
  158. }while(--i);
  159. }
  160. static
  161. void extract(rabbit_ctx_t* ctx){
  162. int8_t i=0;
  163. uint8_t *t;
  164. uint16_t v;
  165. t = ctx->buffer;
  166. i=6;
  167. do{
  168. v = ((uint16_t*)(ctx->x))[(2*(i+ 8)+1)%16]
  169. ^ ((uint16_t*)(ctx->x))[(2*(i+11)+0)%16];
  170. *t++ = v>>8;
  171. *t++ = (uint8_t)v;
  172. v = ((uint16_t*)(ctx->x))[(2*(i+ 8)+0)%16]
  173. ^ ((uint16_t*)(ctx->x))[(2*(i+13)+1)%16];
  174. *t++ = v>>8;
  175. *t++ = (uint8_t)v;
  176. i-=2;
  177. }while(i>=0);
  178. #if ESTREAM
  179. uint8_t x;
  180. i=0;
  181. do{
  182. x = ctx->buffer[i];
  183. ctx->buffer[i] = ctx->buffer[15-i];
  184. ctx->buffer[15-i] = x;
  185. }while(++i<8);
  186. #endif
  187. }
  188. static const uint8_t key80_pad[] = { 0xDE, 0x05, 0x6E, 0xAC, 0x8A, 0x11 };
  189. void rabbit_init(const void* key, uint16_t keysize_b,
  190. const void* iv,
  191. rabbit_ctx_t* ctx){
  192. uint8_t t_key[16];
  193. if(keysize_b==80){
  194. memcpy(t_key, key, 10);
  195. memcpy(t_key+10, key80_pad, 6);
  196. }else{
  197. memcpy(t_key, key, 16);
  198. }
  199. #if !ESTREAM
  200. uint8_t i=0, t;
  201. do{
  202. t = t_key[i];
  203. t_key[i] = t_key[15-i];
  204. t_key[15-i] = t;
  205. }while(++i<8);
  206. #endif
  207. keysetup(ctx, t_key);
  208. if(iv){
  209. ivsetup(ctx, iv);
  210. }
  211. extract(ctx);
  212. ctx->buffer_idx = 16;
  213. }
  214. uint8_t rabbit_gen(rabbit_ctx_t* ctx){
  215. if(ctx->buffer_idx==16){
  216. step(ctx);
  217. extract(ctx);
  218. ctx->buffer_idx = 0;
  219. }
  220. return ctx->buffer[ctx->buffer_idx++];
  221. }