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