]> git.cryptolib.org Git - arm-crypto-lib.git/blob - rabbit/rabbit_c.c
also from the length_B -> length_W migration
[arm-crypto-lib.git] / rabbit / rabbit_c.c
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
6     This program is free software: you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation, either version 3 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <string.h>
21 #include <stdint.h>
22 #include "rabbit.h"
23
24 #ifndef ESTREAM
25 #define ESTREAM 0
26 #endif
27
28 /*
29 void dump_ctx(rabbit_ctx_t* ctx){
30         uint8_t i=0;
31         cli_putstr_P(PSTR("\r\n --- ctx dump ---\r\n  b = "));
32         cli_hexdump_byte(ctx->carry);
33         do{
34                 if((i&3)==0){
35                         cli_putstr_P(PSTR("\r\n"));
36                 }
37                 cli_putstr_P(PSTR("  X"));
38                 cli_hexdump_byte(i);
39                 cli_putstr_P(PSTR(" = 0x"));
40                 cli_hexdump_rev(&(ctx->x[i]), 4);
41         }while(++i<8);
42         i=0;
43         do{
44                 if((i&3)==0){
45                         cli_putstr_P(PSTR("\r\n"));
46                 }
47                 cli_putstr_P(PSTR("  C"));
48                 cli_hexdump_byte(i);
49                 cli_putstr_P(PSTR(" = 0x"));
50                 cli_hexdump_rev(&(ctx->c[i]), 4);
51         }while(++i<8);
52 }
53 */
54
55 static
56 const uint32_t c_const[8] = {
57                 0x4D34D34D, 0xD34D34D3,
58                 0x34D34D34, 0x4D34D34D,
59                 0xD34D34D3, 0x34D34D34,
60                 0x4D34D34D, 0xD34D34D3
61 };
62
63 static
64 void gen_g(uint32_t* dest, rabbit_ctx_t* ctx){
65         uint8_t i=0;
66         uint64_t a;
67         uint32_t t, *x, *c;
68         x = ctx->x;
69         c = ctx->c;
70         do{
71                 t = *x++ + *c++;
72                 a = ((uint64_t)t)*((uint64_t)t);
73                 dest[i] = (uint32_t)(a^(a>>32));
74         }while(++i<8);
75 }
76
77 static
78 void update_c(rabbit_ctx_t* ctx){
79         uint8_t i=0;
80         uint64_t a;
81         uint32_t *c;
82         const uint32_t *con;
83         c = ctx->c;
84         con = c_const;
85         a = ctx->carry;
86         do{
87                 a += *c;
88                 a += *con++;
89                 *c++ = (uint32_t)a;
90                 a >>= 32;
91         }while(++i<8);
92         ctx->carry = a?1:0;
93 }
94
95 #define ROT16(a) (((a)<<16) | ((a)>>16))
96 #define ROT8(a)  (((a)<< 8) | ((a)>>24))
97
98 static
99 void step(rabbit_ctx_t* ctx){
100         uint32_t g[8];
101         uint8_t i=0;
102         update_c(ctx);
103         gen_g(g, ctx);
104         memcpy(ctx->x, g, 8*4);
105         do{
106                 ctx->x[i] += ROT16(g[(i+8-1)%8]) + ROT16(g[(i+8-2)%8]);
107                 ++i;
108                 ctx->x[i] += ROT8(g[(i+8-1)%8]) + g[(i+8-2)%8];
109         }while(++i<8);
110 }
111
112 static
113 void keysetup(rabbit_ctx_t* ctx, const void* key){
114         uint16_t *x, *c;
115         uint8_t i=0;
116         x = (uint16_t*)(ctx->x);
117         c = (uint16_t*)(ctx->c);
118         ctx->carry = 0;
119         do{
120                 *x++ = ((uint16_t*)key)[i];
121                 *x++ = ((uint16_t*)key)[(i+1)%8];
122                 *c++ = ((uint16_t*)key)[(i+5)%8];
123                 *c++ = ((uint16_t*)key)[(i+4)%8];
124                 ++i;
125                 *x++ = ((uint16_t*)key)[(i+4)%8];
126                 *x++ = ((uint16_t*)key)[(i+5)%8];
127                 *c++ = ((uint16_t*)key)[(i+1)%8];
128                 *c++ = ((uint16_t*)key)[i];
129         }while(++i<8);
130         i=0;
131         do{
132                 step(ctx);
133         }while(++i<4);
134         i=0;
135         do{
136                 ctx->c[i] ^= ctx->x[(i+4)%8];
137         }while(++i<8);
138 }
139
140 static
141 void ivsetup(rabbit_ctx_t* ctx, const void* iv){
142         uint8_t i;
143         uint32_t t;
144         union __attribute__((packed)){
145                 uint8_t v8[8];
146                 uint16_t v16[4];
147                 uint32_t v32[2];
148         }t_iv;
149         i=0;
150 #if ESTREAM
151         memcpy(t_iv.v8, iv, 8);
152 #else
153         do{
154                 t_iv.v8[i] = ((uint8_t*)iv)[7-i];
155                 t_iv.v8[7-i] = ((uint8_t*)iv)[i];
156         }while(++i<4);
157 #endif
158         ctx->c[0] ^= t_iv.v32[0];
159         ctx->c[4] ^= t_iv.v32[0];
160         ctx->c[2] ^= t_iv.v32[1];
161         ctx->c[6] ^= t_iv.v32[1];
162         t = ( ((uint32_t)(t_iv.v16[3]))<<16) | (t_iv.v16[1]);
163         ctx->c[1] ^= t;
164         ctx->c[5] ^= t;
165         t = ( ((uint32_t)(t_iv.v16[2]))<<16) | (t_iv.v16[0]);
166         ctx->c[3] ^= t;
167         ctx->c[7] ^= t;
168         i=4;
169         do{
170                 step(ctx);
171         }while(--i);
172 }
173
174 static
175 void extract(rabbit_ctx_t* ctx){
176         int8_t i=0;
177         uint8_t *t;
178         uint16_t v;
179         t = ctx->buffer;
180         i=6;
181         do{
182                 v =   ((uint16_t*)(ctx->x))[(2*(i+ 8)+1)%16]
183                     ^ ((uint16_t*)(ctx->x))[(2*(i+11)+0)%16];
184                 *t++ = v>>8;
185                 *t++ = (uint8_t)v;
186                 v =   ((uint16_t*)(ctx->x))[(2*(i+ 8)+0)%16]
187                     ^ ((uint16_t*)(ctx->x))[(2*(i+13)+1)%16];
188                 *t++ = v>>8;
189                 *t++ = (uint8_t)v;
190
191                 i-=2;
192         }while(i>=0);
193 #if ESTREAM
194         uint8_t x;
195         i=0;
196         do{
197                 x = ctx->buffer[i];
198                 ctx->buffer[i] = ctx->buffer[15-i];
199                 ctx->buffer[15-i] = x;
200         }while(++i<8);
201 #endif
202 }
203
204 static const uint8_t key80_pad[] = { 0xDE, 0x05, 0x6E, 0xAC, 0x8A, 0x11 };
205
206 void rabbit_init(const void* key, uint16_t keysize_b,
207                   const void* iv,
208                   rabbit_ctx_t* ctx){
209         uint8_t t_key[16];
210         if(keysize_b==80){
211                 memcpy(t_key, key, 10);
212                 memcpy(t_key+10, key80_pad, 6);
213         }else{
214                 memcpy(t_key, key, 16);
215         }
216 #if !ESTREAM
217         uint8_t i=0, t;
218         do{
219                 t = t_key[i];
220                 t_key[i] = t_key[15-i];
221                 t_key[15-i] = t;
222         }while(++i<8);
223 #endif
224         keysetup(ctx, t_key);
225
226
227         if(iv){
228                 ivsetup(ctx, iv);
229         }
230         extract(ctx);
231         ctx->buffer_idx = 16;
232 }
233
234 uint8_t rabbit_gen(rabbit_ctx_t* ctx){
235         if(ctx->buffer_idx==16){
236                 step(ctx);
237                 extract(ctx);
238                 ctx->buffer_idx = 0;
239         }
240         return ctx->buffer[ctx->buffer_idx++];
241 }