]> AND Private Git Repository - Cipher_code.git/blob - OneRoundIoT/EnhancedOneRound/Simon_speck/C/simon.c
Logo AND Algorithmique Numérique Distribuée

Private GIT Repository
update scprng
[Cipher_code.git] / OneRoundIoT / EnhancedOneRound / Simon_speck / C / simon.c
1 /*
2  * Simon.c
3  * Implementation of NSA Simon Block Cipher
4  * Copyright 2017 Michael Calvin McCoy
5  * calvin.mccoy@gmail.com
6  *  # The MIT License (MIT) - see LICENSE.md
7 */
8
9 #include <stdint.h>
10 #include <limits.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include "simon.h"
14
15
16 // Cipher Operation Macros
17 #define shift_one(x_word) (((x_word) << 1) | ((x_word) >> (word_size - 1)))
18 #define shift_eight(x_word) (((x_word) << 8) | ((x_word) >> (word_size - 8)))
19 #define shift_two(x_word) (((x_word) << 2) | ((x_word) >> (word_size - 2)))
20
21 #define rshift_three(x) (((x) >> 3) | (((x) & 0x7) << (word_size - 3)))
22 #define rshift_one(x)   (((x) >> 1) | (((x) & 0x1) << (word_size - 1)))
23
24 uint64_t z_arrays[5] = {0b0001100111000011010100100010111110110011100001101010010001011111,
25                         0b0001011010000110010011111011100010101101000011001001111101110001,
26                         0b0011001101101001111110001000010100011001001011000000111011110101,
27                         0b0011110000101100111001010001001000000111101001100011010111011011,
28                         0b0011110111001001010011000011101000000100011011010110011110001011};
29
30 // Valid Cipher Parameters
31 const uint8_t simon_rounds[] = {32, 36, 36, 42, 44, 52, 54, 68, 69, 72};
32 const uint8_t  z_assign[] = {0, 0, 1, 2, 3, 2, 3, 2, 3, 4};
33
34 uint8_t Simon_Init(SimSpk_Cipher *cipher_object, enum cipher_config_t cipher_cfg, enum mode_t c_mode, void *key, uint8_t *iv, uint8_t *counter) {
35
36     if (cipher_cfg > cfg_256_128 || cipher_cfg < cfg_64_32){
37         return 1;
38     }
39     
40     cipher_object->block_size = block_sizes[cipher_cfg];
41     cipher_object->key_size = key_sizes[cipher_cfg];
42     cipher_object->round_limit = simon_rounds[cipher_cfg];
43     cipher_object->cipher_cfg = cipher_cfg;
44     cipher_object->z_seq = z_assign[cipher_cfg];
45     uint8_t word_size = block_sizes[cipher_cfg] >> 1;
46     uint8_t word_bytes = word_size >> 3;
47     uint16_t key_words =  key_sizes[cipher_cfg] / word_size;
48     uint64_t sub_keys[4] = {};
49     uint64_t mod_mask = ULLONG_MAX >> (64 - word_size);
50
51     // Setup
52     for(int i = 0; i < key_words; i++) {
53         memcpy(&sub_keys[i], key + (word_bytes * i), word_bytes);
54     }
55     
56     uint64_t tmp1,tmp2;
57     uint64_t c = 0xFFFFFFFFFFFFFFFC; 
58     
59     // Store First Key Schedule Entry
60     memcpy(cipher_object->key_schedule, &sub_keys[0], word_bytes);
61
62     for (int i = 0; i < simon_rounds[cipher_cfg] - 1; i++) {
63         tmp1 = rshift_three(sub_keys[key_words - 1]);
64
65         if (key_words == 4) {
66             tmp1 ^= sub_keys[1];
67         }
68
69         tmp2 = rshift_one(tmp1);
70         tmp1 ^= sub_keys[0];
71         tmp1 ^= tmp2;
72
73         tmp2 = c ^ ((z_arrays[cipher_object->z_seq] >> (i % 62)) & 1);
74
75         tmp1 ^= tmp2;
76
77         // Shift Sub Words
78         for (int j = 0; j < (key_words - 1); j++) {
79             sub_keys[j] = sub_keys[j + 1];
80         }
81         sub_keys[key_words - 1] = tmp1 & mod_mask;
82
83         // Append sub key to key schedule
84         memcpy(cipher_object->key_schedule + (word_bytes * (i + 1)), &sub_keys[0], word_bytes);
85
86     }
87
88     if (cipher_cfg == cfg_64_32){
89         cipher_object->encryptPtr = &Simon_Encrypt_32;
90         cipher_object->decryptPtr = &Simon_Decrypt_32;
91     }
92     else if(cipher_cfg <= cfg_96_48){
93         cipher_object->encryptPtr = Simon_Encrypt_48;
94         cipher_object->decryptPtr = Simon_Decrypt_48;
95     }
96     else if(cipher_cfg <= cfg_128_64) {
97         cipher_object->encryptPtr = Simon_Encrypt_64;
98         cipher_object->decryptPtr = Simon_Decrypt_64;
99
100     }
101
102     else if(cipher_cfg <= cfg_144_96) {
103         cipher_object->encryptPtr = Simon_Encrypt_96;
104         cipher_object->decryptPtr = Simon_Decrypt_96;
105     }
106
107     else if(cipher_cfg <= cfg_256_128) {
108         cipher_object->encryptPtr = Simon_Encrypt_128;
109         cipher_object->decryptPtr = Simon_Decrypt_128;
110     }
111
112     else return 1;
113
114     return 0;
115 }
116
117
118 uint8_t Simon_Encrypt(SimSpk_Cipher cipher_object, const void *plaintext, void *ciphertext) {
119     (*cipher_object.encryptPtr)(cipher_object.round_limit, cipher_object.key_schedule, plaintext, ciphertext);
120     return 0;
121 }
122
123 void Simon_Encrypt_32(const uint8_t round_limit, const uint8_t *key_schedule, const uint8_t *plaintext, uint8_t *ciphertext) {
124     
125     const uint8_t word_size = 16;
126     uint16_t *y_word = (uint16_t *)ciphertext;
127     uint16_t *x_word = (((uint16_t *)ciphertext) + 1);
128
129     *y_word = *(uint16_t *)plaintext;
130     *x_word = *(((uint16_t *)plaintext) + 1);
131
132     uint16_t *round_key_ptr = (uint16_t *)key_schedule;
133
134     for(uint8_t i = 0; i < round_limit; i++) {
135
136         // Shift, AND , XOR ops
137         uint16_t temp = (shift_one(*x_word) & shift_eight(*x_word)) ^ *y_word ^ shift_two(*x_word);
138         
139         // Feistel Cross
140         *y_word = *x_word;
141         
142         // XOR with Round Key
143         *x_word = temp ^ *(round_key_ptr + i);
144     }
145 }
146
147 void Simon_Encrypt_48(const uint8_t round_limit, const uint8_t *key_schedule, const uint8_t *plaintext,
148                       uint8_t *ciphertext) {
149     
150     const uint8_t word_size = 24;
151
152     bword_24 intrd = *(bword_24 *)plaintext;
153     uint32_t y_word = intrd.data;
154     intrd = *((bword_24 *)(plaintext+3));
155     uint32_t x_word = intrd.data;
156
157     for(uint8_t i = 0; i < round_limit; i++) {
158
159         // Shift, AND , XOR ops
160         uint32_t temp = (shift_one(x_word) & shift_eight(x_word)) ^ y_word ^ shift_two(x_word);
161
162         // Feistel Cross
163         y_word = x_word;
164         
165         // XOR with Round Key
166         x_word = (temp ^ (*((bword_24 *)(key_schedule + (i*3)))).data) & 0xFFFFFF;
167     }
168     // Assemble Ciphertext Output Array
169     intrd.data = y_word;
170     bword_24 * intrd_ptr = (bword_24 *)ciphertext; 
171     *intrd_ptr = intrd;
172     
173     intrd.data = x_word;
174     intrd_ptr = (bword_24 *)(ciphertext + 3);
175     *intrd_ptr = intrd;
176 }
177
178 void Simon_Encrypt_64(const uint8_t round_limit, const uint8_t *key_schedule, const uint8_t *plaintext,
179                       uint8_t *ciphertext) {
180     
181     const uint8_t word_size = 32;
182     uint32_t *y_word = (uint32_t *)ciphertext;
183     uint32_t *x_word = (((uint32_t *)ciphertext) + 1);
184     *y_word = *(uint32_t *)plaintext;
185     *x_word = *(((uint32_t *)plaintext) + 1);
186     uint32_t *round_key_ptr = (uint32_t *)key_schedule;
187
188     for(uint8_t i = 0; i < round_limit; i++) {
189
190         // Shift, AND , XOR ops
191         uint32_t temp = (shift_one(*x_word) & shift_eight(*x_word)) ^ *y_word ^ shift_two(*x_word);
192         
193         // Feistel Cross
194         *y_word = *x_word;
195         
196         // XOR with Round Key
197         *x_word = temp ^ *(round_key_ptr + i);
198     }
199 }
200
201 void Simon_Encrypt_96(const uint8_t round_limit, const uint8_t *key_schedule, const uint8_t *plaintext,
202                       uint8_t *ciphertext) {
203     
204     const uint8_t word_size = 48;
205
206     bword_48 intrd = *(bword_48 *)plaintext;
207     uint64_t y_word = intrd.data;
208     intrd = *((bword_48 *)(plaintext+6));
209     uint64_t x_word = intrd.data;
210
211     for(uint8_t i = 0; i < round_limit; i++) {  
212
213         // Shift, AND , XOR ops
214         uint64_t temp = (shift_one(x_word) & shift_eight(x_word)) ^ y_word ^ shift_two(x_word);
215
216         // Feistel Cross
217         y_word = x_word;
218         
219         // XOR with Round Key
220         x_word = (temp ^ (*((bword_48 *)(key_schedule + (i*6)))).data) & 0xFFFFFFFFFFFF;
221     }
222     // Assemble Ciphertext Output Array
223     intrd.data = y_word;
224     bword_48 * intrd_ptr = (bword_48 *)ciphertext; 
225     *intrd_ptr = intrd;
226     
227     intrd.data = x_word;
228     intrd_ptr = (bword_48 *)(ciphertext + 6);
229     *intrd_ptr = intrd;
230     
231 }
232
233 void Simon_Encrypt_128(const uint8_t round_limit, const uint8_t *key_schedule, const uint8_t *plaintext,
234                        uint8_t *ciphertext) {
235
236     const uint8_t word_size = 64;
237     uint64_t *y_word = (uint64_t *)ciphertext;
238     uint64_t *x_word = (((uint64_t *)ciphertext) + 1);
239     *y_word = *(uint64_t *)plaintext;
240     *x_word = *(((uint64_t *)plaintext) + 1);
241     uint64_t *round_key_ptr = (uint64_t *)key_schedule;
242
243
244     for(uint8_t i = 0; i < round_limit; i++) {
245
246         // Shift, AND , XOR ops
247         uint64_t temp = (shift_one(*x_word) & shift_eight(*x_word)) ^ *y_word ^ shift_two(*x_word);
248         
249         // Feistel Cross
250         *y_word = *x_word;
251         
252         // XOR with Round Key
253         *x_word = temp ^ *(round_key_ptr + i);
254     }
255 }
256
257 uint8_t Simon_Decrypt(SimSpk_Cipher cipher_object, const void *ciphertext, void *plaintext) {
258     (*cipher_object.decryptPtr)(cipher_object.round_limit, cipher_object.key_schedule, ciphertext, plaintext);
259     return 0;
260 }
261
262 void Simon_Decrypt_32(const uint8_t round_limit, const uint8_t *key_schedule, const uint8_t *ciphertext,
263                       uint8_t *plaintext) {
264
265     const uint8_t word_size = 16;
266     uint16_t *x_word = (uint16_t *)plaintext;
267     uint16_t *y_word = ((uint16_t *)plaintext) + 1;
268     uint16_t *round_key_ptr = (uint16_t *)key_schedule;
269
270     *x_word = *(uint16_t *)ciphertext;
271     *y_word = *(((uint16_t *)ciphertext) + 1);
272
273     for(int8_t i = round_limit - 1; i >= 0; i--) {
274
275         // Shift, AND , XOR ops
276         uint16_t temp = (shift_one(*x_word) & shift_eight(*x_word)) ^ *y_word ^ shift_two(*x_word);
277         
278         // Feistel Cross
279         *y_word = *x_word;
280         
281         // XOR with Round Key
282         *x_word = temp ^ *(round_key_ptr + i);
283     }
284 }
285
286 void Simon_Decrypt_48(const uint8_t round_limit, const uint8_t *key_schedule, const uint8_t *ciphertext,
287                       uint8_t *plaintext){
288     const uint8_t word_size = 24;
289
290     bword_24 intrd = *(bword_24 *)ciphertext;
291     uint32_t x_word = intrd.data;
292     intrd = *((bword_24 *)(ciphertext+3));
293     uint32_t y_word = intrd.data;
294
295     for(int8_t i = round_limit - 1 ; i >= 0; i--) {
296
297         // Shift, AND , XOR ops
298         uint32_t temp = (shift_one(x_word) & shift_eight(x_word)) ^ y_word ^ shift_two(x_word);
299
300         // Feistel Cross
301         y_word = x_word;
302         
303         // XOR with Round Key
304         x_word = (temp ^ (*((bword_24 *)(key_schedule + (i*3)))).data) & 0xFFFFFF;
305     }
306     // Assemble plaintext Output Array
307     intrd.data = x_word;
308     bword_24 * intrd_ptr = (bword_24 *)plaintext; 
309     *intrd_ptr = intrd;
310     
311     intrd.data = y_word;
312     intrd_ptr = (bword_24 *)(plaintext + 3);
313     *intrd_ptr = intrd;
314 }
315
316 void Simon_Decrypt_64(const uint8_t round_limit, const uint8_t *key_schedule, const uint8_t *ciphertext,
317                       uint8_t *plaintext){
318
319     const uint8_t word_size = 32;
320     uint32_t *x_word = (uint32_t *)plaintext;
321     uint32_t *y_word = ((uint32_t *)plaintext) + 1;
322     uint32_t *round_key_ptr = (uint32_t *)key_schedule;
323
324     *x_word = *(uint32_t *)ciphertext;
325     *y_word = *(((uint32_t *)ciphertext) + 1);
326
327     for(int8_t i = round_limit -1 ; i >= 0; i--) {
328
329         // Shift, AND , XOR ops
330         uint32_t temp = (shift_one(*x_word) & shift_eight(*x_word)) ^ *y_word ^ shift_two(*x_word);
331         
332         // Feistel Cross
333         *y_word = *x_word;
334         
335         // XOR with Round Key
336         *x_word = temp ^ *(round_key_ptr + i);
337     }
338 }
339
340 void Simon_Decrypt_96(const uint8_t round_limit, const uint8_t *key_schedule, const uint8_t *ciphertext,
341                       uint8_t *plaintext){
342     const uint8_t word_size = 48;
343     bword_48 intrd = *(bword_48 *)ciphertext;
344     uint64_t x_word = intrd.data;
345     intrd = *((bword_48 *)(ciphertext+6));
346     uint64_t y_word = intrd.data;
347
348     for(int8_t i = round_limit - 1; i >= 0; i--) {
349
350         // Shift, AND , XOR ops
351         uint64_t temp = (shift_one(x_word) & shift_eight(x_word)) ^ y_word ^ shift_two(x_word);
352
353         // Feistel Cross
354         y_word = x_word;
355         
356         // XOR with Round Key
357         x_word = (temp ^ (*((bword_48 *)(key_schedule + (i*6)))).data) & 0xFFFFFFFFFFFF;
358     }
359     // Assemble Plaintext Output Array
360     intrd.data = x_word;
361     bword_48 * intrd_ptr = (bword_48 *)plaintext; 
362     *intrd_ptr = intrd;
363     
364     intrd.data = y_word;
365     intrd_ptr = (bword_48 *)(plaintext + 6);
366     *intrd_ptr = intrd;
367 }
368
369 void Simon_Decrypt_128(const uint8_t round_limit, const uint8_t *key_schedule, const uint8_t *ciphertext,
370                        uint8_t *plaintext){
371
372     const uint8_t word_size = 64;
373     uint64_t *x_word = (uint64_t *)plaintext;
374     uint64_t *y_word = ((uint64_t *)plaintext) + 1;
375     uint64_t *round_key_ptr = (uint64_t *)key_schedule;
376
377     *x_word = *(uint64_t *)ciphertext;
378     *y_word = *(((uint64_t *)ciphertext) + 1);
379
380     for(int8_t i = round_limit - 1; i >=0; i--) {
381
382         // Shift, AND , XOR ops
383         uint64_t temp = (shift_one(*x_word) & shift_eight(*x_word)) ^ *y_word ^ shift_two(*x_word);
384         
385         // Feistel Cross
386         *y_word = *x_word;
387         
388         // XOR with Round Key
389         *x_word = temp ^ *(round_key_ptr + i);
390     }
391 }