25 #include "utility/RotateUtil.h"
26 #include "utility/EndianUtil.h"
63 #define USE_AVR_INLINE_ASM 1
94 #define pack64(data, value) \
96 uint64_t v = htobe64((value)); \
97 memcpy((data), &v, sizeof(uint64_t)); \
99 #define unpack64(value, data) \
101 memcpy(&(value), (data), sizeof(uint64_t)); \
102 (value) = be64toh((value)); \
107 #if USE_AVR_INLINE_ASM
113 }
else if (len == 24) {
116 }
else if (len == 16) {
126 __asm__ __volatile__ (
128 "ld __tmp_reg__,-Z\n"
129 "st X+,__tmp_reg__\n"
132 : :
"x"(l),
"z"(key + len - 8),
"r"(mb)
136 __asm__ __volatile__ (
138 "ld __tmp_reg__,-Z\n"
139 "st X+,__tmp_reg__\n"
142 : :
"x"(k),
"z"(key + len),
"r"(8)
146 __asm__ __volatile__ (
150 "adc %B1,__zero_reg__\n"
184 "sbc %B1,__zero_reg__\n"
188 "adc %B1,__zero_reg__\n"
201 "sbc %B1,__zero_reg__\n"
213 "adc r16,__zero_reg__\n"
223 "adc r16,__zero_reg__\n"
233 "adc r16,__zero_reg__\n"
262 "r"((uint8_t)((m - 1) * 8)),
265 :
"r8",
"r9",
"r10",
"r11",
"r12",
"r13",
"r14",
"r15",
266 "r16",
"r17",
"r18",
"r19",
"r20",
"r21",
"r22",
"r23",
275 unpack64(l[1], key + 8);
276 unpack64(l[0], key + 16);
277 unpack64(k[0], key + 24);
278 }
else if (len == 24) {
281 unpack64(l[0], key + 8);
282 unpack64(k[0], key + 16);
283 }
else if (len == 16) {
286 unpack64(k[0], key + 8);
292 uint8_t li_out = m - 1;
293 for (uint8_t i = 0; i < (rounds - 1); ++i) {
294 l[li_out] = (k[i] + rightRotate8_64(l[li_in])) ^ i;
295 k[i + 1] = leftRotate3_64(k[i]) ^ l[li_out];
308 #if USE_AVR_INLINE_ASM
309 uint32_t xlow, xhigh, ylow, yhigh;
313 __asm__ __volatile__ (
330 :
"=r"(xlow),
"=r"(xhigh),
"=r"(ylow),
"=r"(yhigh)
335 __asm__ __volatile__ (
338 "mov __tmp_reg__,%A0\n"
346 "mov %D1,__tmp_reg__\n"
357 "ld __tmp_reg__,Z+\n"
358 "eor %A0,__tmp_reg__\n"
359 "ld __tmp_reg__,Z+\n"
360 "eor %B0,__tmp_reg__\n"
361 "ld __tmp_reg__,Z+\n"
362 "eor %C0,__tmp_reg__\n"
363 "ld __tmp_reg__,Z+\n"
364 "eor %D0,__tmp_reg__\n"
365 "ld __tmp_reg__,Z+\n"
366 "eor %A1,__tmp_reg__\n"
367 "ld __tmp_reg__,Z+\n"
368 "eor %B1,__tmp_reg__\n"
369 "ld __tmp_reg__,Z+\n"
370 "eor %C1,__tmp_reg__\n"
371 "ld __tmp_reg__,Z+\n"
372 "eor %D1,__tmp_reg__\n"
383 "adc %A2,__zero_reg__\n"
394 "adc %A2,__zero_reg__\n"
403 "adc %A2,__zero_reg__\n"
419 :
"+r"(xlow),
"+r"(xhigh),
"+r"(ylow),
"+r"(yhigh)
420 :
"z"(k),
"r"(rounds)
424 __asm__ __volatile__ (
441 : :
"r"(xlow),
"r"(xhigh),
"r"(ylow),
"r"(yhigh),
"z"(output)
445 const uint64_t *s = k;
447 unpack64(y, input + 8);
448 for (uint8_t round = rounds; round > 0; --round, ++s) {
449 x = (rightRotate8_64(x) + y) ^ s[0];
450 y = leftRotate3_64(y) ^ x;
453 pack64(output + 8, y);
459 #if USE_AVR_INLINE_ASM
460 uint32_t xlow, xhigh, ylow, yhigh;
464 __asm__ __volatile__ (
481 :
"=r"(xlow),
"=r"(xhigh),
"=r"(ylow),
"=r"(yhigh)
486 __asm__ __volatile__ (
532 "ld __tmp_reg__,-Z\n"
533 "eor %D1,__tmp_reg__\n"
534 "ld __tmp_reg__,-Z\n"
535 "eor %C1,__tmp_reg__\n"
536 "ld __tmp_reg__,-Z\n"
537 "eor %B1,__tmp_reg__\n"
538 "ld __tmp_reg__,-Z\n"
539 "eor %A1,__tmp_reg__\n"
540 "ld __tmp_reg__,-Z\n"
541 "eor %D0,__tmp_reg__\n"
542 "ld __tmp_reg__,-Z\n"
543 "eor %C0,__tmp_reg__\n"
544 "ld __tmp_reg__,-Z\n"
545 "eor %B0,__tmp_reg__\n"
546 "ld __tmp_reg__,-Z\n"
547 "eor %A0,__tmp_reg__\n"
558 "mov __tmp_reg__,%D1\n"
566 "mov %A0,__tmp_reg__\n"
573 :
"+r"(xlow),
"+r"(xhigh),
"+r"(ylow),
"+r"(yhigh)
574 :
"z"(k + rounds),
"r"(rounds)
578 __asm__ __volatile__ (
595 : :
"r"(xlow),
"r"(xhigh),
"r"(ylow),
"r"(yhigh),
"z"(output)
599 const uint64_t *s = k + rounds - 1;
601 unpack64(y, input + 8);
602 for (uint8_t round = rounds; round > 0; --round, --s) {
603 y = rightRotate3_64(x ^ y);
604 x = leftRotate8_64((x ^ s[0]) - y);
607 pack64(output + 8, y);
size_t keySize() const
Default size of the key for this block cipher, in bytes.
size_t blockSize() const
Size of a single block processed by this cipher, in bytes.
Speck()
Constructs a Speck block cipher with no initial key.
void encryptBlock(uint8_t *output, const uint8_t *input)
Encrypts a single block using this cipher.
void decryptBlock(uint8_t *output, const uint8_t *input)
Decrypts a single block using this cipher.
bool setKey(const uint8_t *key, size_t len)
Sets the key to use for future encryption and decryption operations.
void clear()
Clears all security-sensitive state from this block cipher.