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

Private GIT Repository
Merge branch 'master' of ssh://info.iut-bm.univ-fcomte.fr/Cipher_code
[Cipher_code.git] / OneRoundIoT / EnhancedOneRound / Simon_speck / C / speck.c
1 /*
2  * Speck.c
3  * Implementation of NSA Speck Block Cipher
4  * Copyright 2017 Michael Calvin McCoy
5  * calvin.mccoy@gmail.com
6  *  # The MIT License (MIT) - see LICENSE.md see LICENSE.md
7 */
8
9 #include <stdint.h>
10 #include <limits.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include "speck.h"
14
15
16 #define rotate_left(x,n) (((x) >> (word_size - (n))) | ((x) << (n)))
17 #define rotate_right(x,n) (((x) << (word_size - (n))) | ((x) >> (n)))
18
19 const uint8_t speck_rounds[] = {22, 22, 23, 26, 27, 28, 29, 32, 33, 34};
20
21 uint8_t Speck_Init(SimSpk_Cipher *cipher_object, enum cipher_config_t cipher_cfg, enum mode_t c_mode, void *key, uint8_t *iv, uint8_t *counter) {
22
23     if (cipher_cfg > cfg_256_128 || cipher_cfg < cfg_64_32) {
24         return 1;
25     }
26     
27     cipher_object->block_size = block_sizes[cipher_cfg];
28     cipher_object->key_size = key_sizes[cipher_cfg];
29     cipher_object->round_limit = speck_rounds[cipher_cfg];
30     cipher_object->cipher_cfg = cipher_cfg;
31     
32     uint8_t word_size = block_sizes[cipher_cfg] >> 1;
33     uint8_t word_bytes = word_size >> 3;
34     uint16_t key_words =  key_sizes[cipher_cfg] / word_size;
35     uint64_t sub_keys[4] = {};
36     uint64_t mod_mask = ULLONG_MAX >> (64 - word_size);
37     
38     if (cipher_cfg == cfg_64_32) {
39         cipher_object->alpha = 7;
40         cipher_object->beta = 2;
41     }
42     else {
43         cipher_object->alpha = 8;
44         cipher_object->beta = 3;
45     }
46
47     // Setup
48     for(int i = 0; i < key_words; i++) {
49         memcpy(&sub_keys[i], key + (word_bytes * i), word_bytes);
50     }
51      
52     // Store First Key Schedule Entry
53     memcpy(cipher_object->key_schedule, &sub_keys[0], word_bytes);
54
55     uint64_t tmp,tmp2;
56     for (uint64_t i = 0; i < speck_rounds[cipher_cfg] - 1; i++) {
57
58         // Run Speck Cipher Round Function
59         tmp = (rotate_right(sub_keys[1],cipher_object->alpha)) & mod_mask;
60         tmp = (tmp + sub_keys[0]) & mod_mask;
61         tmp= tmp ^ i;
62         tmp2 = (rotate_left(sub_keys[0],cipher_object->beta)) & mod_mask;
63         tmp2 = tmp2 ^ tmp;
64         sub_keys[0] = tmp2;
65
66         // Shift Key Schedule Subword
67         if (key_words != 2) {
68             // Shift Sub Words
69             for(int j = 1; j < (key_words - 1); j++){
70                 sub_keys[j] = sub_keys[j+1];
71             }
72         }
73         sub_keys[key_words - 1] = tmp;
74
75         // Append sub key to key schedule
76         memcpy(cipher_object->key_schedule + (word_bytes * (i+1)), &sub_keys[0], word_bytes);   
77     }
78
79     if (cipher_cfg == cfg_64_32){
80         cipher_object->encryptPtr = &Speck_Encrypt_32;
81         cipher_object->decryptPtr = &Speck_Decrypt_32;
82     }
83     else if(cipher_cfg <= cfg_96_48){
84         cipher_object->encryptPtr = Speck_Encrypt_48;
85         cipher_object->decryptPtr = Speck_Decrypt_48;
86     }
87     else if(cipher_cfg <= cfg_128_64) {
88         cipher_object->encryptPtr = Speck_Encrypt_64;
89         cipher_object->decryptPtr = Speck_Decrypt_64;
90
91     }
92
93     else if(cipher_cfg <= cfg_144_96) {
94         cipher_object->encryptPtr = Speck_Encrypt_96;
95         cipher_object->decryptPtr = Speck_Decrypt_96;
96     }
97
98     else if(cipher_cfg <= cfg_256_128) {
99         cipher_object->encryptPtr = Speck_Encrypt_128;
100         cipher_object->decryptPtr = Speck_Decrypt_128;
101     }
102
103     else return 1;
104
105     return 0;
106 }
107
108
109 uint8_t Speck_Encrypt(SimSpk_Cipher cipher_object, const void *plaintext, void *ciphertext) {
110     (*cipher_object.encryptPtr)(cipher_object.round_limit, cipher_object.key_schedule, plaintext, ciphertext);
111     return 0;
112 }
113
114 void Speck_Encrypt_32(const uint8_t round_limit, const uint8_t *key_schedule, const uint8_t *plaintext, uint8_t *ciphertext) {
115
116     const uint8_t word_size = 16;
117     uint16_t *y_word = (uint16_t *)ciphertext;
118     uint16_t *x_word = ((uint16_t *)ciphertext) + 1;
119     uint16_t *round_key_ptr = (uint16_t *)key_schedule;
120
121     *y_word = *(uint16_t *)plaintext;
122     *x_word = *(((uint16_t *)plaintext) + 1);
123
124     for(uint8_t i = 0; i < round_limit; i++) {
125         *x_word = ((rotate_right(*x_word, 7)) + *y_word) ^ *(round_key_ptr + i);
126         *y_word = (rotate_left(*y_word, 2)) ^ *x_word;
127     }
128 }
129
130
131 void Speck_Encrypt_48(const uint8_t round_limit, const uint8_t *key_schedule, const uint8_t *plaintext,
132                       uint8_t *ciphertext){
133    
134     const uint8_t word_size = 24;
135
136     bytes3_t *threeBytePtr = (bytes3_t *)plaintext;
137     uint32_t y_word = (*(bitword24_t *)threeBytePtr).data;
138     uint32_t x_word = (*(bitword24_t *)(threeBytePtr + 1)).data;
139     threeBytePtr = (bytes3_t *)key_schedule;
140     uint32_t round_key;
141
142     for(uint8_t i = 0; i < round_limit; i++) {  
143         round_key = (*(bitword24_t *)(threeBytePtr + i)).data;
144         x_word = (((rotate_right(x_word, 8)) + y_word) ^ round_key) & 0x00FFFFFF;
145         y_word = ((rotate_left(y_word, 3)) ^ x_word) & 0x00FFFFFF;
146     }
147     // Assemble Ciphertext Output Array
148     threeBytePtr = (bytes3_t *)ciphertext; 
149     *threeBytePtr = *(bytes3_t *)&y_word;
150     threeBytePtr += 1;
151     *threeBytePtr = *(bytes3_t *)&x_word;
152 }
153
154 void Speck_Encrypt_64(const uint8_t round_limit, const uint8_t *key_schedule, const uint8_t *plaintext,
155                       uint8_t *ciphertext) {
156
157     const uint8_t word_size = 32;
158     uint32_t *y_word = (uint32_t *)ciphertext;
159     uint32_t *x_word = ((uint32_t *)ciphertext) + 1;
160     uint32_t *round_key_ptr = (uint32_t *)key_schedule;
161
162     *y_word = *(uint32_t *)plaintext;
163     *x_word = *(((uint32_t *)plaintext) + 1);
164
165     for(uint8_t i = 0; i < round_limit; i++) { 
166         *x_word = ((rotate_right(*x_word, 8)) + *y_word) ^ *(round_key_ptr + i);
167         *y_word = (rotate_left(*y_word, 3)) ^ *x_word;
168     }
169 }
170
171 void Speck_Encrypt_96(const uint8_t round_limit, const uint8_t *key_schedule, const uint8_t *plaintext,
172                       uint8_t *ciphertext){
173     const uint8_t word_size = 48;
174
175     bytes6_t *threeBytePtr = (bytes6_t *)plaintext;
176     uint64_t y_word = (*(bitword48_t *)threeBytePtr).data;
177     uint64_t x_word = (*(bitword48_t *)(threeBytePtr + 1)).data;
178     threeBytePtr = (bytes6_t *)key_schedule;
179     uint64_t round_key;
180
181     for(uint8_t i = 0; i < round_limit; i++) {  
182         round_key = (*(bitword48_t *)(threeBytePtr + i)).data;
183         x_word = (((rotate_right(x_word, 8)) + y_word) ^ round_key) & 0x00FFFFFFFFFFFF;
184         y_word = ((rotate_left(y_word, 3)) ^ x_word) & 0x00FFFFFFFFFFFF;
185     }
186     // Assemble Ciphertext Output Array
187     threeBytePtr = (bytes6_t *)ciphertext; 
188     *threeBytePtr = *(bytes6_t *)&y_word;
189     threeBytePtr += 1;
190     *threeBytePtr = *(bytes6_t *)&x_word;
191 }
192
193 void Speck_Encrypt_128(const uint8_t round_limit, const uint8_t *key_schedule, const uint8_t *plaintext,
194                        uint8_t *ciphertext){
195
196     const uint8_t word_size = 64;
197     uint64_t *y_word = (uint64_t *)ciphertext;
198     uint64_t *x_word = ((uint64_t *)ciphertext) + 1;
199     uint64_t *round_key_ptr = (uint64_t *)key_schedule;
200
201     *y_word = *(uint64_t *)plaintext;
202     *x_word = *(((uint64_t *)plaintext) + 1);
203
204     for(uint8_t i = 0; i < round_limit; i++) { 
205         *x_word = ((rotate_right(*x_word, 8)) + *y_word) ^ *(round_key_ptr + i);
206         *y_word = (rotate_left(*y_word, 3)) ^ *x_word;
207     }
208 }
209
210 uint8_t Speck_Decrypt(SimSpk_Cipher cipher_object, const void *ciphertext, void *plaintext) {
211     (*cipher_object.decryptPtr)(cipher_object.round_limit, cipher_object.key_schedule, ciphertext, plaintext);
212     return 0;
213 }
214
215 void Speck_Decrypt_32(const uint8_t round_limit, const uint8_t *key_schedule, const uint8_t *ciphertext, uint8_t *plaintext) {
216
217     const uint8_t word_size = 16;
218     uint16_t *y_word = (uint16_t *)plaintext;
219     uint16_t *x_word = ((uint16_t *)plaintext) + 1;
220     uint16_t *round_key_ptr = (uint16_t *)key_schedule;
221
222     *y_word = *(uint16_t *)ciphertext;
223     *x_word = *(((uint16_t *)ciphertext) + 1);
224
225     for(int8_t i = round_limit - 1; i >=0; i--) {
226         *y_word = rotate_right((*y_word ^ *x_word), 2);
227         *x_word = rotate_left((uint16_t)((*x_word ^ *(round_key_ptr + i)) - *y_word), 7);
228     }
229 }
230
231 void Speck_Decrypt_48(const uint8_t round_limit, const uint8_t *key_schedule, const uint8_t *ciphertext,
232                       uint8_t *plaintext) {
233
234     const uint8_t word_size = 24;
235
236     bytes3_t *threeBytePtr = (bytes3_t *)ciphertext;
237     uint32_t y_word = (*(bitword24_t *)threeBytePtr).data;
238     uint32_t x_word = (*(bitword24_t *)(threeBytePtr + 1)).data;
239     threeBytePtr = (bytes3_t *)key_schedule;
240     uint32_t round_key;
241
242     for(int8_t i = round_limit - 1; i >=0; i--) {
243         round_key = (*(bitword24_t *)(threeBytePtr + i)).data;
244         y_word = (rotate_right((y_word ^ x_word), 3)) & 0x00FFFFFF;
245         x_word = (rotate_left(((((x_word ^ round_key)) - y_word) & 0x00FFFFFF), 8)) & 0x00FFFFFF;
246     }
247
248     // Assemble Plaintext Output Array
249     threeBytePtr = (bytes3_t *)plaintext;
250     *threeBytePtr = *(bytes3_t *)&y_word;
251     threeBytePtr += 1;
252     *threeBytePtr = *(bytes3_t *)&x_word;
253 }
254
255 void Speck_Decrypt_64(const uint8_t round_limit, const uint8_t *key_schedule, const uint8_t *ciphertext,
256                       uint8_t *plaintext) {
257
258     const uint8_t word_size = 32;
259     uint32_t *y_word = (uint32_t *)plaintext;
260     uint32_t *x_word = ((uint32_t *)plaintext) + 1;
261     uint32_t *round_key_ptr = (uint32_t *)key_schedule;
262
263     *y_word = *(uint32_t *)ciphertext;
264     *x_word = *(((uint32_t *)ciphertext) + 1);
265
266     for(int8_t i = round_limit - 1; i >=0; i--) {
267         *y_word = rotate_right((*y_word ^ *x_word), 3);
268         *x_word = rotate_left((uint32_t)((*x_word ^ *(round_key_ptr + i)) - *y_word), 8);
269     }
270 }
271
272 void Speck_Decrypt_96(const uint8_t round_limit, const uint8_t *key_schedule, const uint8_t *ciphertext,
273                       uint8_t *plaintext) {
274     const uint8_t word_size = 48;
275
276     bytes6_t *sixBytePtr = (bytes6_t *)ciphertext;
277     uint64_t y_word = (*(bitword48_t *)sixBytePtr).data;
278     uint64_t x_word = (*(bitword48_t *)(sixBytePtr + 1)).data;
279     sixBytePtr = (bytes6_t *)key_schedule;
280     uint64_t round_key;
281
282     for(int8_t i = round_limit - 1; i >=0; i--) {
283         round_key = (*(bitword48_t *)(sixBytePtr + i)).data;
284         y_word = (rotate_right((y_word ^ x_word), 3)) & 0x00FFFFFFFFFFFF;
285         x_word = (rotate_left(((((x_word ^ round_key)) - y_word) & 0x00FFFFFFFFFFFF), 8)) & 0x00FFFFFFFFFFFF;
286     }
287
288     // Assemble Plaintext Output Array
289     sixBytePtr = (bytes6_t *)plaintext;
290     *sixBytePtr = *(bytes6_t *)&y_word;
291     sixBytePtr += 1;
292     *sixBytePtr = *(bytes6_t *)&x_word;
293 }
294
295 void Speck_Decrypt_128(const uint8_t round_limit, const uint8_t *key_schedule, const uint8_t *ciphertext,
296                        uint8_t *plaintext) {
297
298     const uint8_t word_size = 64;
299     uint64_t *y_word = (uint64_t *)plaintext;
300     uint64_t *x_word = ((uint64_t *)plaintext) + 1;
301     uint64_t *round_key_ptr = (uint64_t *)key_schedule;
302
303     *y_word = *(uint64_t *)ciphertext;
304     *x_word = *(((uint64_t *)ciphertext) + 1);
305
306     for(int8_t i = round_limit - 1; i >=0; i--) {
307         *y_word = rotate_right((*y_word ^ *x_word), 3);
308         *x_word = rotate_left((uint64_t)((*x_word ^ *(round_key_ptr + i)) - *y_word), 8);
309     }
310 }