23 #include "SpeckSmall.h"
25 #include "utility/RotateUtil.h"
26 #include "utility/EndianUtil.h"
64 #define USE_AVR_INLINE_ASM 1
68 #define pack64(data, value) \
70 uint64_t v = htobe64((value)); \
71 memcpy((data), &v, sizeof(uint64_t)); \
73 #define unpack64(value, data) \
75 memcpy(&(value), (data), sizeof(uint64_t)); \
76 (value) = be64toh((value)); \
89 SpeckSmall::~SpeckSmall()
100 #if USE_AVR_INLINE_ASM
103 uint8_t mb = (rounds - 31) * 8;
104 __asm__ __volatile__ (
116 "ld __tmp_reg__,Z+\n"
117 "st X+,__tmp_reg__\n"
121 "sbc %B1,__zero_reg__\n"
127 "adc %B1,__zero_reg__\n"
152 "sbc %B1,__zero_reg__\n"
156 "adc %B1,__zero_reg__\n"
169 "sbc %B1,__zero_reg__\n"
181 "adc r16,__zero_reg__\n"
191 "adc r16,__zero_reg__\n"
201 "adc r16,__zero_reg__\n"
220 "adc %B1,__zero_reg__\n"
235 :
"r8",
"r9",
"r10",
"r11",
"r12",
"r13",
"r14",
"r15",
236 "r16",
"r17",
"r18",
"r19",
"r20",
"r21",
"r22",
"r23",
243 uint8_t m = rounds - 30;
245 uint8_t li_out = m - 1;
247 memcpy(l, k + 1, (m - 1) *
sizeof(uint64_t));
248 for (uint8_t i = 0; i < (rounds - 1); ++i) {
249 l[li_out] = (s + rightRotate8_64(l[li_in])) ^ i;
250 s = leftRotate3_64(s) ^ l[li_out];
251 li_in = (li_in + 1) & 0x03;
252 li_out = (li_out + 1) & 0x03;
263 #if USE_AVR_INLINE_ASM
265 uint32_t xlow, xhigh, ylow, yhigh;
266 uint32_t slow, shigh;
267 uint8_t li_in = (rounds + 3) & 0x03;
268 uint8_t li_out = (((rounds - 31) + li_in) & 0x03) * 8;
272 __asm__ __volatile__ (
274 "adc r31,__zero_reg__\n"
276 "std %A0,__tmp_reg__\n"
277 "ldd __tmp_reg__,Z+1\n"
278 "std %B0,__tmp_reg__\n"
279 "ldd __tmp_reg__,Z+2\n"
280 "std %C0,__tmp_reg__\n"
281 "ldd __tmp_reg__,Z+3\n"
282 "std %D0,__tmp_reg__\n"
283 "ldd __tmp_reg__,Z+4\n"
284 "std %A1,__tmp_reg__\n"
285 "ldd __tmp_reg__,Z+5\n"
286 "std %B1,__tmp_reg__\n"
287 "ldd __tmp_reg__,Z+6\n"
288 "std %C1,__tmp_reg__\n"
289 "ldd __tmp_reg__,Z+7\n"
290 "std %D1,__tmp_reg__\n"
292 "sbc r31,__zero_reg__\n"
296 "ld __tmp_reg__,Z+\n"
297 "st X+,__tmp_reg__\n"
300 :
"=Q"(slow),
"=Q"(shigh)
301 :
"z"(this->l),
"x"(l),
"r"(li_out)
307 __asm__ __volatile__ (
324 :
"=r"(xlow),
"=r"(xhigh),
"=r"(ylow),
"=r"(yhigh)
329 __asm__ __volatile__ (
380 "ldd __tmp_reg__,%A4\n"
381 "eor %A0,__tmp_reg__\n"
382 "ldd __tmp_reg__,%B4\n"
383 "eor %B0,__tmp_reg__\n"
384 "ldd __tmp_reg__,%C4\n"
385 "eor %C0,__tmp_reg__\n"
386 "ldd __tmp_reg__,%D4\n"
387 "eor %D0,__tmp_reg__\n"
388 "ldd __tmp_reg__,%A5\n"
389 "eor %A1,__tmp_reg__\n"
390 "ldd __tmp_reg__,%B5\n"
391 "eor %B1,__tmp_reg__\n"
392 "ldd __tmp_reg__,%C5\n"
393 "eor %C1,__tmp_reg__\n"
394 "ldd __tmp_reg__,%D5\n"
395 "eor %D1,__tmp_reg__\n"
406 "mov __tmp_reg__,%D1\n"
414 "mov %A0,__tmp_reg__\n"
453 "adc %B8,__zero_reg__\n"
516 "sbc %B8,__zero_reg__\n"
526 "adc %B8,__zero_reg__\n"
549 "sbc %B8,__zero_reg__\n"
582 :
"+r"(xlow),
"+r"(xhigh),
"+r"(ylow),
"+r"(yhigh),
583 "+Q"(slow),
"+Q"(shigh),
"+Q"(li_in),
"+Q"(li_out)
584 :
"z"(l),
"r"(rounds)
585 :
"r23",
"r24",
"r25"
589 __asm__ __volatile__ (
606 : :
"r"(xlow),
"r"(xhigh),
"r"(ylow),
"r"(yhigh),
"z"(output)
612 uint8_t li_in = (rounds + 3) & 0x03;
613 uint8_t li_out = ((rounds - 31) + li_in) & 0x03;
616 for (round = li_in; round != li_out; round = (round + 1) & 0x03)
617 l[round] = this->l[round];
622 unpack64(y, input + 8);
626 for (uint8_t round = rounds - 1; round > 0; --round) {
628 y = rightRotate3_64(x ^ y);
629 x = leftRotate8_64((x ^ s) - y);
632 li_in = (li_in + 3) & 0x03;
633 li_out = (li_out + 3) & 0x03;
634 s = rightRotate3_64(s ^ l[li_out]);
635 l[li_in] = leftRotate8_64((l[li_out] ^ (round - 1)) - s);
639 y = rightRotate3_64(x ^ y);
640 x = leftRotate8_64((x ^ s) - y);
644 pack64(output + 8, y);
bool setKey(const uint8_t *key, size_t len)
Sets the key to use for future encryption and decryption operations.
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.
SpeckSmall()
Constructs a small-memory Speck block cipher with no initial key.
void clear()
Clears all security-sensitive state from this block cipher.