25 #include "utility/RotateUtil.h"
26 #include "utility/EndianUtil.h"
57 #define USE_AVR_INLINE_ASM 1
88 #define pack64(data, value) \
90 uint64_t v = htobe64((value)); \
91 memcpy((data), &v, sizeof(uint64_t)); \
93 #define unpack64(value, data) \
95 memcpy(&(value), (data), sizeof(uint64_t)); \
96 (value) = be64toh((value)); \
101 #if USE_AVR_INLINE_ASM
107 }
else if (len == 24) {
110 }
else if (len == 16) {
120 __asm__ __volatile__ (
122 "ld __tmp_reg__,-Z\n"
123 "st X+,__tmp_reg__\n"
126 : :
"x"(l),
"z"(key + len - 8),
"r"(mb)
130 __asm__ __volatile__ (
132 "ld __tmp_reg__,-Z\n"
133 "st X+,__tmp_reg__\n"
136 : :
"x"(k),
"z"(key + len),
"r"(8)
140 __asm__ __volatile__ (
144 "adc %B1,__zero_reg__\n"
154 "mov __tmp_reg__,r8\n"
162 "mov r15,__tmp_reg__\n"
188 "sbc %B1,__zero_reg__\n"
192 "adc %B1,__zero_reg__\n"
205 "sbc %B1,__zero_reg__\n"
217 "adc r16,__zero_reg__\n"
227 "adc r16,__zero_reg__\n"
237 "adc r16,__zero_reg__\n"
266 "r"((uint8_t)((m - 1) * 8)),
269 :
"r8",
"r9",
"r10",
"r11",
"r12",
"r13",
"r14",
"r15",
270 "r16",
"r17",
"r18",
"r19",
"r20",
"r21",
"r22",
"r23",
279 unpack64(l[1], key + 8);
280 unpack64(l[0], key + 16);
281 unpack64(k[0], key + 24);
282 }
else if (len == 24) {
285 unpack64(l[0], key + 8);
286 unpack64(k[0], key + 16);
287 }
else if (len == 16) {
290 unpack64(k[0], key + 8);
296 uint8_t li_out = m - 1;
297 for (uint8_t i = 0; i < (rounds - 1); ++i) {
298 l[li_out] = (k[i] + rightRotate8_64(l[li_in])) ^ i;
299 k[i + 1] = leftRotate3_64(k[i]) ^ l[li_out];
312 #if USE_AVR_INLINE_ASM
313 uint32_t xlow, xhigh, ylow, yhigh;
317 __asm__ __volatile__ (
334 :
"=r"(xlow),
"=r"(xhigh),
"=r"(ylow),
"=r"(yhigh)
339 __asm__ __volatile__ (
342 "mov __tmp_reg__,%A0\n"
350 "mov %D1,__tmp_reg__\n"
361 "ld __tmp_reg__,Z+\n"
362 "eor %A0,__tmp_reg__\n"
363 "ld __tmp_reg__,Z+\n"
364 "eor %B0,__tmp_reg__\n"
365 "ld __tmp_reg__,Z+\n"
366 "eor %C0,__tmp_reg__\n"
367 "ld __tmp_reg__,Z+\n"
368 "eor %D0,__tmp_reg__\n"
369 "ld __tmp_reg__,Z+\n"
370 "eor %A1,__tmp_reg__\n"
371 "ld __tmp_reg__,Z+\n"
372 "eor %B1,__tmp_reg__\n"
373 "ld __tmp_reg__,Z+\n"
374 "eor %C1,__tmp_reg__\n"
375 "ld __tmp_reg__,Z+\n"
376 "eor %D1,__tmp_reg__\n"
387 "adc %A2,__zero_reg__\n"
398 "adc %A2,__zero_reg__\n"
407 "adc %A2,__zero_reg__\n"
423 :
"+r"(xlow),
"+r"(xhigh),
"+r"(ylow),
"+r"(yhigh)
424 :
"z"(k),
"r"(rounds)
428 __asm__ __volatile__ (
445 : :
"r"(xlow),
"r"(xhigh),
"r"(ylow),
"r"(yhigh),
"z"(output)
449 const uint64_t *s = k;
451 unpack64(y, input + 8);
452 for (uint8_t round = rounds; round > 0; --round, ++s) {
453 x = (rightRotate8_64(x) + y) ^ s[0];
454 y = leftRotate3_64(y) ^ x;
457 pack64(output + 8, y);
463 #if USE_AVR_INLINE_ASM
464 uint32_t xlow, xhigh, ylow, yhigh;
468 __asm__ __volatile__ (
485 :
"=r"(xlow),
"=r"(xhigh),
"=r"(ylow),
"=r"(yhigh)
490 __asm__ __volatile__ (
536 "ld __tmp_reg__,-Z\n"
537 "eor %D1,__tmp_reg__\n"
538 "ld __tmp_reg__,-Z\n"
539 "eor %C1,__tmp_reg__\n"
540 "ld __tmp_reg__,-Z\n"
541 "eor %B1,__tmp_reg__\n"
542 "ld __tmp_reg__,-Z\n"
543 "eor %A1,__tmp_reg__\n"
544 "ld __tmp_reg__,-Z\n"
545 "eor %D0,__tmp_reg__\n"
546 "ld __tmp_reg__,-Z\n"
547 "eor %C0,__tmp_reg__\n"
548 "ld __tmp_reg__,-Z\n"
549 "eor %B0,__tmp_reg__\n"
550 "ld __tmp_reg__,-Z\n"
551 "eor %A0,__tmp_reg__\n"
562 "mov __tmp_reg__,%D1\n"
570 "mov %A0,__tmp_reg__\n"
577 :
"+r"(xlow),
"+r"(xhigh),
"+r"(ylow),
"+r"(yhigh)
578 :
"z"(k + rounds),
"r"(rounds)
582 __asm__ __volatile__ (
599 : :
"r"(xlow),
"r"(xhigh),
"r"(ylow),
"r"(yhigh),
"z"(output)
603 const uint64_t *s = k + rounds - 1;
605 unpack64(y, input + 8);
606 for (uint8_t round = rounds; round > 0; --round, --s) {
607 y = rightRotate3_64(x ^ y);
608 x = leftRotate8_64((x ^ s[0]) - y);
611 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.