]> git.cryptolib.org Git - avr-crypto-lib.git/blob - noekeon/noekeon.c
new and more compact aes
[avr-crypto-lib.git] / noekeon / noekeon.c
1 /* noekeon.c */
2 /*
3     This file is part of the AVR-Crypto-Lib.
4     Copyright (C) 2006-2015 Daniel Otte (bg@nerilex.org)
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  * author: Daniel Otte
21  * email:  bg@nerilex.org
22  * license: GPLv3 or later
23  * 
24  * 
25  * 
26  */
27
28 #include <stdint.h>
29 #include <string.h>
30
31 #ifdef __AVR__
32         #include <avr/pgmspace.h>
33 #endif
34 #include "noekeon.h"
35 // #include "cli.h"
36
37 #define ROUND_NR 16
38
39 #define RC_POS 0
40
41 static
42 void gamma_1(uint32_t *a){
43         uint32_t tmp;
44         
45         a[1] ^= ~((a[3]) | (a[2]));
46         a[0] ^=   a[2] & a[1];  
47         
48         tmp=a[3]; a[3]=a[0]; a[0]=tmp;
49         a[2] ^= a[0] ^ a[1] ^ a[3];
50         
51         a[1] ^= ~((a[3]) | (a[2]));
52         a[0] ^=   a[2] & a[1];  
53 }       
54
55 #define ROTL32(a,n) (((a)<<n)|((a)>>(32-n)))
56 #define ROTR32(a,n) (((a)>>n)|((a)<<(32-n)))
57
58 static
59 void pi1(uint32_t *a){
60         a[1] = ROTL32(a[1], 1);
61         a[2] = ROTL32(a[2], 5);
62         a[3] = ROTL32(a[3], 2);
63 }
64
65 static
66 void pi2(uint32_t *a){
67         a[1] = ROTR32(a[1], 1);
68         a[2] = ROTR32(a[2], 5);
69         a[3] = ROTR32(a[3], 2);
70 }
71
72 static
73 void theta(const uint32_t *k, uint32_t *a){
74         uint32_t temp;
75
76         temp = a[0] ^ a[2]; temp ^= ROTR32(temp, 8) ^ ROTL32(temp, 8);
77         a[1] ^= temp;
78         a[3] ^= temp;
79         
80         a[0] ^= k[0];
81         a[1] ^= k[1];
82         a[2] ^= k[2];
83         a[3] ^= k[3];
84
85         temp = a[1] ^ a[3]; temp ^= ROTR32(temp, 8) ^ ROTL32(temp, 8);
86         a[0] ^= temp;
87         a[2] ^= temp;   
88
89 }
90
91 static 
92 void noekeon_round(uint32_t *key, uint32_t *state, uint8_t const1, uint8_t const2){
93         ((uint8_t*)state)[RC_POS] ^= const1;
94         theta(key, state);
95         ((uint8_t*)state)[RC_POS] ^= const2;
96         pi1(state);
97         gamma_1(state);
98         pi2(state);
99 }
100
101 const uint8_t rc_tab[]
102 #ifdef __AVR__
103  PROGMEM 
104 #endif
105   = {
106 /*      0x80, */
107               0x1B, 0x36, 0x6C, 0xD8, 0xAB, 0x4D, 0x9A,
108         0x2F, 0x5E, 0xBC, 0x63, 0xC6, 0x97, 0x35, 0x6A,
109         0xD4
110 };
111 /* for more rounds
112  0xD4, 0xB3, 0x7D, 0xFA, 0xEF, 0xC5, 0x91, 0x39,
113  0x72, 0xE4, 0xD3, 0xBD, 0x61, 0xC2, 0x9F, 0x25,
114 */
115
116 static
117 void changendian32(void *a){
118         ((uint8_t*)a)[0] ^= ((uint8_t*)a)[3];
119         ((uint8_t*)a)[3] ^= ((uint8_t*)a)[0];
120         ((uint8_t*)a)[0] ^= ((uint8_t*)a)[3];
121         
122         ((uint8_t*)a)[1] ^= ((uint8_t*)a)[2];
123         ((uint8_t*)a)[2] ^= ((uint8_t*)a)[1];
124         ((uint8_t*)a)[1] ^= ((uint8_t*)a)[2];
125 }
126
127 static
128 void changendian(void *a){
129         changendian32((uint32_t*)(&(((uint32_t*)a)[0])));
130         changendian32((uint32_t*)(&(((uint32_t*)a)[1])));
131         changendian32((uint32_t*)(&(((uint32_t*)a)[2])));
132         changendian32((uint32_t*)(&(((uint32_t*)a)[3])));
133 }
134
135 /******************************************************************************/
136
137 void noekeon_enc(void *buffer, const void *key){
138         uint8_t rc=0x80;
139         uint8_t keyb[16];
140         int8_t i;
141         
142         memcpy(keyb, key, 16);
143         changendian(buffer);
144         changendian(keyb);
145
146         for(i=0; i<ROUND_NR; ++i){
147                 noekeon_round((uint32_t*)keyb, (uint32_t*)buffer, rc, 0);
148 #ifdef __AVR__
149                 rc = pgm_read_byte(rc_tab+i);
150 #else
151                 rc = rc_tab[i];
152 #endif
153         }
154         ((uint8_t*)buffer)[RC_POS] ^= rc;
155         theta((uint32_t*)keyb, (uint32_t*)buffer);
156
157         changendian(buffer);
158 }
159
160
161 void noekeon_dec(void *buffer, const void *key){
162         uint8_t rc;
163         int8_t i;
164         uint8_t nullv[16];
165         uint8_t dkey[16];
166         
167
168         changendian(buffer);
169         
170         memset(nullv, 0, 16);
171         memcpy(dkey, key, 16);
172         changendian(dkey);
173         
174         theta((uint32_t*)nullv, (uint32_t*)dkey);
175 //      cli_putstr_P(PSTR("\r\nTheta: "));
176 //      cli_hexdump(dkey, 16);
177         
178         for(i=ROUND_NR-1; i>=0; --i){
179 #ifdef __AVR__
180                 rc = pgm_read_byte(rc_tab+i);
181 #else
182                 rc = rc_tab[i];
183 #endif
184                 noekeon_round((uint32_t*)dkey, (uint32_t*)buffer, 0, rc);
185         }
186         theta((uint32_t*)dkey, (uint32_t*)buffer);
187         ((uint8_t*)buffer)[RC_POS] ^= 0x80;
188
189         changendian(buffer);
190 }
191
192 void noekeon_init(const void *key, noekeon_ctx_t *ctx){
193         uint8_t nullv[16];
194         
195         memset(nullv, 0, 16);
196         memcpy(ctx, key, 16);
197         noekeon_enc(ctx, nullv);
198 }
199