Arduino Cryptography Library
Acorn128AVR.cpp
1 /*
2  * Copyright (C) 2018 Southern Storm Software, Pty Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  */
22 
23 #include "Acorn128.h"
24 
25 #if defined(CRYPTO_ACORN128_AVR)
26 
27 // Acorn128 constants for ca and cb.
28 #define CA_0 ((uint32_t)0x00000000)
29 #define CA_1 ((uint32_t)0xFFFFFFFF)
30 #define CB_0 ((uint32_t)0x00000000)
31 #define CB_1 ((uint32_t)0xFFFFFFFF)
32 #define CA_0_BYTE ((uint8_t)0x00)
33 #define CA_1_BYTE ((uint8_t)0xFF)
34 #define CB_0_BYTE ((uint8_t)0x00)
35 #define CB_1_BYTE ((uint8_t)0xFF)
36 
37 // Imports from Acorn128.cpp
38 extern void acornPad(Acorn128State *state, uint32_t cb);
39 
40 // Force the acornEncrypt8() and acornDecrypt8() functions to always inline.
41 static uint8_t acornEncrypt8
42  (Acorn128State *state, uint8_t plaintext, uint8_t ca, uint8_t cb)
43  __attribute__((always_inline));
44 static uint8_t acornDecrypt8(Acorn128State *state, uint8_t ciphertext)
45  __attribute__((always_inline));
46 
47 static uint8_t acornEncrypt8
48  (Acorn128State *state, uint8_t plaintext, uint8_t ca, uint8_t cb)
49 {
50  // Automatically generated by the genacorn tool.
51  uint8_t ciphertext;
52  __asm__ __volatile__ (
53  "ldd r15,Z+34\n"
54  "ldd r14,Z+33\n"
55  "ldd r0,Z+32\n"
56  "lsl r0\n"
57  "rol r14\n"
58  "rol r15\n"
59  "lsl r0\n"
60  "rol r14\n"
61  "rol r15\n"
62  "lsl r0\n"
63  "rol r14\n"
64  "ldd r13,Z+28\n"
65  "ldd r0,Z+29\n"
66  "lsr r0\n"
67  "ror r13\n"
68  "lsr r0\n"
69  "ror r13\n"
70  "lsr r0\n"
71  "ror r13\n"
72  "ldd r0,Z+20\n"
73  "ldd r12,Z+21\n"
74  "lsl r0\n"
75  "rol r12\n"
76  "lsl r0\n"
77  "rol r12\n"
78  "ldd r16,Z+16\n"
79  "ldd r17,Z+17\n"
80  "swap r16\n"
81  "swap r17\n"
82  "andi r16,0x0F\n"
83  "andi r17,0xF0\n"
84  "or r16,r17\n"
85  "ldd r0,Z+8\n"
86  "ldd r11,Z+9\n"
87  "lsl r0\n"
88  "rol r11\n"
89  "lsl r0\n"
90  "rol r11\n"
91  "lsl r0\n"
92  "rol r11\n"
93  "ldd r10,Z+3\n"
94  "ldd r9,Z+2\n"
95  "ldd r0,Z+1\n"
96  "lsl r0\n"
97  "rol r9\n"
98  "rol r10\n"
99  "lsl r0\n"
100  "rol r9\n"
101  "lsl r0\n"
102  "rol r9\n"
103  "lsl r0\n"
104  "rol r9\n"
105  "ldd r8,Z+40\n"
106  "eor r8,r14\n"
107  "ldd r7,Z+32\n"
108  "eor r8,r7\n"
109  "eor r7,r13\n"
110  "ldd r6,Z+28\n"
111  "eor r7,r6\n"
112  "eor r6,r12\n"
113  "ldd r23,Z+20\n"
114  "eor r6,r23\n"
115  "eor r23,r16\n"
116  "ldd r22,Z+16\n"
117  "eor r23,r22\n"
118  "eor r22,r11\n"
119  "ldd r21,Z+8\n"
120  "eor r22,r21\n"
121  "eor r21,r10\n"
122  "ld r20,Z\n"
123  "eor r21,r20\n"
124  "eor r9,r23\n"
125  "mov r0,r14\n"
126  "and r0,r21\n"
127  "eor r9,r0\n"
128  "and r14,r6\n"
129  "eor r9,r14\n"
130  "mov r0,r21\n"
131  "and r0,r6\n"
132  "eor r9,r0\n"
133  "and r16,r7\n"
134  "eor r9,r16\n"
135  "mov r0,r7\n"
136  "com r0\n"
137  "and r11,r0\n"
138  "eor r9,r11\n"
139  "mov r16,r22\n"
140  "com r16\n"
141  "eor r16,r20\n"
142  "mov r0,r15\n"
143  "and r0,r10\n"
144  "eor r16,r0\n"
145  "and r10,r12\n"
146  "eor r16,r10\n"
147  "and r15,r12\n"
148  "eor r16,r15\n"
149  "and r13,%3\n"
150  "eor r16,r13\n"
151  "mov r0,r9\n"
152  "and r0,%4\n"
153  "eor r16,r0\n"
154  "eor r16,%2\n"
155  "swap r16\n"
156  "mov r17,r16\n"
157  "andi r17,0xF0\n"
158  "eor r8,r17\n"
159  "andi r16,0x0F\n"
160  "std Z+40,r16\n"
161  "ldd r0,Z+33\n"
162  "std Z+32,r0\n"
163  "ldd r0,Z+34\n"
164  "std Z+33,r0\n"
165  "ldd r0,Z+35\n"
166  "std Z+34,r0\n"
167  "ldd r0,Z+36\n"
168  "std Z+35,r0\n"
169  "ldd r0,Z+37\n"
170  "std Z+36,r0\n"
171  "ldd r0,Z+38\n"
172  "std Z+37,r0\n"
173  "ldd r0,Z+39\n"
174  "clr r15\n"
175  "lsl r8\n"
176  "rol r15\n"
177  "lsl r8\n"
178  "rol r15\n"
179  "lsl r8\n"
180  "rol r15\n"
181  "or r0,r8\n"
182  "std Z+38,r0\n"
183  "std Z+39,r15\n"
184  "ldd r0,Z+29\n"
185  "std Z+28,r0\n"
186  "ldd r0,Z+30\n"
187  "std Z+29,r0\n"
188  "ldd r0,Z+31\n"
189  "std Z+30,r0\n"
190  "ldd r0,Z+26\n"
191  "clr r15\n"
192  "lsr r7\n"
193  "ror r15\n"
194  "lsr r7\n"
195  "ror r15\n"
196  "lsr r7\n"
197  "ror r15\n"
198  "or r0,r15\n"
199  "std Z+31,r0\n"
200  "std Z+26,r7\n"
201  "ldd r0,Z+21\n"
202  "std Z+20,r0\n"
203  "ldd r0,Z+22\n"
204  "std Z+21,r0\n"
205  "ldd r0,Z+23\n"
206  "std Z+22,r0\n"
207  "ldd r0,Z+24\n"
208  "clr r15\n"
209  "lsr r6\n"
210  "ror r15\n"
211  "or r0,r15\n"
212  "std Z+23,r0\n"
213  "std Z+24,r6\n"
214  "ldd r0,Z+17\n"
215  "std Z+16,r0\n"
216  "ldd r0,Z+18\n"
217  "std Z+17,r0\n"
218  "ldd r0,Z+19\n"
219  "std Z+18,r0\n"
220  "ldd r0,Z+14\n"
221  "std Z+19,r0\n"
222  "ldd r0,Z+15\n"
223  "clr r15\n"
224  "lsr r23\n"
225  "ror r15\n"
226  "or r0,r15\n"
227  "std Z+14,r0\n"
228  "std Z+15,r23\n"
229  "ldd r0,Z+9\n"
230  "std Z+8,r0\n"
231  "ldd r0,Z+10\n"
232  "std Z+9,r0\n"
233  "ldd r0,Z+11\n"
234  "std Z+10,r0\n"
235  "ldd r0,Z+12\n"
236  "std Z+11,r0\n"
237  "ldd r0,Z+13\n"
238  "clr r15\n"
239  "lsr r22\n"
240  "ror r15\n"
241  "lsr r22\n"
242  "ror r15\n"
243  "or r0,r15\n"
244  "std Z+12,r0\n"
245  "std Z+13,r22\n"
246  "ldd r0,Z+1\n"
247  "st Z,r0\n"
248  "ldd r0,Z+2\n"
249  "std Z+1,r0\n"
250  "ldd r0,Z+3\n"
251  "std Z+2,r0\n"
252  "ldd r0,Z+4\n"
253  "std Z+3,r0\n"
254  "ldd r0,Z+5\n"
255  "std Z+4,r0\n"
256  "ldd r0,Z+6\n"
257  "std Z+5,r0\n"
258  "ldd r0,Z+7\n"
259  "clr r15\n"
260  "lsr r21\n"
261  "ror r15\n"
262  "lsr r21\n"
263  "ror r15\n"
264  "lsr r21\n"
265  "ror r15\n"
266  "or r0,r15\n"
267  "std Z+6,r0\n"
268  "std Z+7,r21\n"
269  "mov %0,%2\n"
270  "eor %0,r9\n"
271  : "=r"(ciphertext)
272  : "z"(&state->s1_l), "r"(plaintext), "r"((uint8_t)ca), "r"((uint8_t)cb)
273  : "r16", "r17", "r20", "r21", "r22", "r23", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "memory"
274  );
275  return ciphertext;
276 }
277 
278 static uint8_t acornDecrypt8(Acorn128State *state, uint8_t ciphertext)
279 {
280  // Automatically generated by the genacorn tool.
281  uint8_t plaintext;
282  __asm__ __volatile__ (
283  "ldd r15,Z+34\n"
284  "ldd r14,Z+33\n"
285  "ldd r0,Z+32\n"
286  "lsl r0\n"
287  "rol r14\n"
288  "rol r15\n"
289  "lsl r0\n"
290  "rol r14\n"
291  "rol r15\n"
292  "lsl r0\n"
293  "rol r14\n"
294  "ldd r13,Z+28\n"
295  "ldd r0,Z+29\n"
296  "lsr r0\n"
297  "ror r13\n"
298  "lsr r0\n"
299  "ror r13\n"
300  "lsr r0\n"
301  "ror r13\n"
302  "ldd r0,Z+20\n"
303  "ldd r12,Z+21\n"
304  "lsl r0\n"
305  "rol r12\n"
306  "lsl r0\n"
307  "rol r12\n"
308  "ldd r16,Z+16\n"
309  "ldd r17,Z+17\n"
310  "swap r16\n"
311  "swap r17\n"
312  "andi r16,0x0F\n"
313  "andi r17,0xF0\n"
314  "or r16,r17\n"
315  "ldd r0,Z+8\n"
316  "ldd r11,Z+9\n"
317  "lsl r0\n"
318  "rol r11\n"
319  "lsl r0\n"
320  "rol r11\n"
321  "lsl r0\n"
322  "rol r11\n"
323  "ldd r10,Z+3\n"
324  "ldd r9,Z+2\n"
325  "ldd r0,Z+1\n"
326  "lsl r0\n"
327  "rol r9\n"
328  "rol r10\n"
329  "lsl r0\n"
330  "rol r9\n"
331  "lsl r0\n"
332  "rol r9\n"
333  "lsl r0\n"
334  "rol r9\n"
335  "ldd r8,Z+40\n"
336  "eor r8,r14\n"
337  "ldd r7,Z+32\n"
338  "eor r8,r7\n"
339  "eor r7,r13\n"
340  "ldd r6,Z+28\n"
341  "eor r7,r6\n"
342  "eor r6,r12\n"
343  "ldd r23,Z+20\n"
344  "eor r6,r23\n"
345  "eor r23,r16\n"
346  "ldd r22,Z+16\n"
347  "eor r23,r22\n"
348  "eor r22,r11\n"
349  "ldd r21,Z+8\n"
350  "eor r22,r21\n"
351  "eor r21,r10\n"
352  "ld r20,Z\n"
353  "eor r21,r20\n"
354  "eor r9,r23\n"
355  "mov r0,r14\n"
356  "and r0,r21\n"
357  "eor r9,r0\n"
358  "and r14,r6\n"
359  "eor r9,r14\n"
360  "mov r0,r21\n"
361  "and r0,r6\n"
362  "eor r9,r0\n"
363  "and r16,r7\n"
364  "eor r9,r16\n"
365  "mov r0,r7\n"
366  "com r0\n"
367  "and r11,r0\n"
368  "eor r9,r11\n"
369  "mov r16,r22\n"
370  "com r16\n"
371  "eor r16,r20\n"
372  "mov r0,r15\n"
373  "and r0,r10\n"
374  "eor r16,r0\n"
375  "and r10,r12\n"
376  "eor r16,r10\n"
377  "and r15,r12\n"
378  "eor r16,r15\n"
379  "eor r16,r13\n"
380  "eor r9,%2\n"
381  "eor r16,r9\n"
382  "swap r16\n"
383  "mov r17,r16\n"
384  "andi r17,0xF0\n"
385  "eor r8,r17\n"
386  "andi r16,0x0F\n"
387  "std Z+40,r16\n"
388  "ldd r0,Z+33\n"
389  "std Z+32,r0\n"
390  "ldd r0,Z+34\n"
391  "std Z+33,r0\n"
392  "ldd r0,Z+35\n"
393  "std Z+34,r0\n"
394  "ldd r0,Z+36\n"
395  "std Z+35,r0\n"
396  "ldd r0,Z+37\n"
397  "std Z+36,r0\n"
398  "ldd r0,Z+38\n"
399  "std Z+37,r0\n"
400  "ldd r0,Z+39\n"
401  "clr r15\n"
402  "lsl r8\n"
403  "rol r15\n"
404  "lsl r8\n"
405  "rol r15\n"
406  "lsl r8\n"
407  "rol r15\n"
408  "or r0,r8\n"
409  "std Z+38,r0\n"
410  "std Z+39,r15\n"
411  "ldd r0,Z+29\n"
412  "std Z+28,r0\n"
413  "ldd r0,Z+30\n"
414  "std Z+29,r0\n"
415  "ldd r0,Z+31\n"
416  "std Z+30,r0\n"
417  "ldd r0,Z+26\n"
418  "clr r15\n"
419  "lsr r7\n"
420  "ror r15\n"
421  "lsr r7\n"
422  "ror r15\n"
423  "lsr r7\n"
424  "ror r15\n"
425  "or r0,r15\n"
426  "std Z+31,r0\n"
427  "std Z+26,r7\n"
428  "ldd r0,Z+21\n"
429  "std Z+20,r0\n"
430  "ldd r0,Z+22\n"
431  "std Z+21,r0\n"
432  "ldd r0,Z+23\n"
433  "std Z+22,r0\n"
434  "ldd r0,Z+24\n"
435  "clr r15\n"
436  "lsr r6\n"
437  "ror r15\n"
438  "or r0,r15\n"
439  "std Z+23,r0\n"
440  "std Z+24,r6\n"
441  "ldd r0,Z+17\n"
442  "std Z+16,r0\n"
443  "ldd r0,Z+18\n"
444  "std Z+17,r0\n"
445  "ldd r0,Z+19\n"
446  "std Z+18,r0\n"
447  "ldd r0,Z+14\n"
448  "std Z+19,r0\n"
449  "ldd r0,Z+15\n"
450  "clr r15\n"
451  "lsr r23\n"
452  "ror r15\n"
453  "or r0,r15\n"
454  "std Z+14,r0\n"
455  "std Z+15,r23\n"
456  "ldd r0,Z+9\n"
457  "std Z+8,r0\n"
458  "ldd r0,Z+10\n"
459  "std Z+9,r0\n"
460  "ldd r0,Z+11\n"
461  "std Z+10,r0\n"
462  "ldd r0,Z+12\n"
463  "std Z+11,r0\n"
464  "ldd r0,Z+13\n"
465  "clr r15\n"
466  "lsr r22\n"
467  "ror r15\n"
468  "lsr r22\n"
469  "ror r15\n"
470  "or r0,r15\n"
471  "std Z+12,r0\n"
472  "std Z+13,r22\n"
473  "ldd r0,Z+1\n"
474  "st Z,r0\n"
475  "ldd r0,Z+2\n"
476  "std Z+1,r0\n"
477  "ldd r0,Z+3\n"
478  "std Z+2,r0\n"
479  "ldd r0,Z+4\n"
480  "std Z+3,r0\n"
481  "ldd r0,Z+5\n"
482  "std Z+4,r0\n"
483  "ldd r0,Z+6\n"
484  "std Z+5,r0\n"
485  "ldd r0,Z+7\n"
486  "clr r15\n"
487  "lsr r21\n"
488  "ror r15\n"
489  "lsr r21\n"
490  "ror r15\n"
491  "lsr r21\n"
492  "ror r15\n"
493  "or r0,r15\n"
494  "std Z+6,r0\n"
495  "std Z+7,r21\n"
496  "mov %0,r9\n"
497  : "=r"(plaintext)
498  : "z"(&state->s1_l), "r"(ciphertext)
499  : "r16", "r17", "r20", "r21", "r22", "r23", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "memory"
500  );
501  return plaintext;
502 }
503 
504 uint32_t acornEncrypt32
505  (Acorn128State *state, uint32_t plaintext, uint32_t ca, uint32_t cb)
506 {
507  uint32_t ciphertext;
508  ciphertext = acornEncrypt8
509  (state, (uint8_t)plaintext, (uint8_t)ca, (uint8_t)cb);
510  ciphertext |= ((uint32_t)(acornEncrypt8
511  (state, (uint8_t)(plaintext >> 8), (uint8_t)ca, (uint8_t)cb))) << 8;
512  ciphertext |= ((uint32_t)(acornEncrypt8
513  (state, (uint8_t)(plaintext >> 16), (uint8_t)ca, (uint8_t)cb))) << 16;
514  ciphertext |= ((uint32_t)(acornEncrypt8
515  (state, (uint8_t)(plaintext >> 24), (uint8_t)ca, (uint8_t)cb))) << 24;
516  return ciphertext;
517 }
518 
519 void Acorn128::encrypt(uint8_t *output, const uint8_t *input, size_t len)
520 {
521  uint32_t temp;
522  if (!state.authDone) {
523  acornPad(&state, CB_1);
524  state.authDone = 1;
525  }
526  while (len > 0) {
527  *output++ = acornEncrypt8(&state, *input++, CA_1_BYTE, CB_0_BYTE);
528  --len;
529  }
530 }
531 
532 void Acorn128::decrypt(uint8_t *output, const uint8_t *input, size_t len)
533 {
534  uint32_t temp;
535  if (!state.authDone) {
536  acornPad(&state, CB_1);
537  state.authDone = 1;
538  }
539  while (len > 0) {
540  *output++ = acornDecrypt8(&state, *input++);
541  --len;
542  }
543 }
544 
545 void Acorn128::addAuthData(const void *data, size_t len)
546 {
547  if (state.authDone)
548  return;
549  const uint8_t *input = (const uint8_t *)data;
550  while (len > 0) {
551  acornEncrypt8(&state, *input++, CA_1_BYTE, CB_1_BYTE);
552  --len;
553  }
554 }
555 
556 #endif // CRYPTO_ACORN128_AVR
void encrypt(uint8_t *output, const uint8_t *input, size_t len)
Encrypts an input buffer and writes the ciphertext to an output buffer.
Definition: Acorn128.cpp:554
void decrypt(uint8_t *output, const uint8_t *input, size_t len)
Decrypts an input buffer and writes the plaintext to an output buffer.
Definition: Acorn128.cpp:580
void addAuthData(const void *data, size_t len)
Adds extra data that will be authenticated but not encrypted.
Definition: Acorn128.cpp:606