23 #include "SpeckLowMemory.h"
25 #include "utility/RotateUtil.h"
26 #include "utility/EndianUtil.h"
64 #define USE_AVR_INLINE_ASM 1
78 SpeckLowMemory::~SpeckLowMemory()
95 #define pack64(data, value) \
97 uint64_t v = htobe64((value)); \
98 memcpy((data), &v, sizeof(uint64_t)); \
100 #define unpack64(value, data) \
102 memcpy(&(value), (data), sizeof(uint64_t)); \
103 (value) = be64toh((value)); \
108 #if USE_AVR_INLINE_ASM
112 }
else if (len == 24) {
114 }
else if (len == 16) {
122 __asm__ __volatile__ (
124 "ld __tmp_reg__,-Z\n"
125 "st X+,__tmp_reg__\n"
128 : :
"x"(k),
"z"(key + len),
"r"(len)
134 unpack64(k[2], key + 8);
135 unpack64(k[1], key + 16);
136 unpack64(k[0], key + 24);
137 }
else if (len == 24) {
140 unpack64(k[1], key + 8);
141 unpack64(k[0], key + 16);
142 }
else if (len == 16) {
145 unpack64(k[0], key + 8);
155 #if USE_AVR_INLINE_ASM
157 uint32_t xlow, xhigh, ylow, yhigh;
158 uint32_t slow, shigh;
160 uint8_t li_out = (rounds - 31) * 8;
163 __asm__ __volatile__ (
166 "ld __tmp_reg__,Z+\n"
167 "std %A0,__tmp_reg__\n"
168 "ld __tmp_reg__,Z+\n"
169 "std %B0,__tmp_reg__\n"
170 "ld __tmp_reg__,Z+\n"
171 "std %C0,__tmp_reg__\n"
172 "ld __tmp_reg__,Z+\n"
173 "std %D0,__tmp_reg__\n"
174 "ld __tmp_reg__,Z+\n"
175 "std %A1,__tmp_reg__\n"
176 "ld __tmp_reg__,Z+\n"
177 "std %B1,__tmp_reg__\n"
178 "ld __tmp_reg__,Z+\n"
179 "std %C1,__tmp_reg__\n"
180 "ld __tmp_reg__,Z+\n"
181 "std %D1,__tmp_reg__\n"
184 "ld __tmp_reg__,Z+\n"
185 "st X+,__tmp_reg__\n"
188 :
"=Q"(slow),
"=Q"(shigh)
189 :
"z"(k),
"x"(l),
"Q"(li_out)
195 __asm__ __volatile__ (
212 :
"=r"(xlow),
"=r"(xhigh),
"=r"(ylow),
"=r"(yhigh)
217 __asm__ __volatile__ (
218 "mov r23,__zero_reg__\n"
224 "mov __tmp_reg__,%A0\n"
232 "mov %D1,__tmp_reg__\n"
243 "ldd __tmp_reg__,%A4\n"
244 "eor %A0,__tmp_reg__\n"
245 "ldd __tmp_reg__,%B4\n"
246 "eor %B0,__tmp_reg__\n"
247 "ldd __tmp_reg__,%C4\n"
248 "eor %C0,__tmp_reg__\n"
249 "ldd __tmp_reg__,%D4\n"
250 "eor %D0,__tmp_reg__\n"
251 "ldd __tmp_reg__,%A5\n"
252 "eor %A1,__tmp_reg__\n"
253 "ldd __tmp_reg__,%B5\n"
254 "eor %B1,__tmp_reg__\n"
255 "ldd __tmp_reg__,%C5\n"
256 "eor %C1,__tmp_reg__\n"
257 "ldd __tmp_reg__,%D5\n"
258 "eor %D1,__tmp_reg__\n"
269 "adc %A2,__zero_reg__\n"
280 "adc %A2,__zero_reg__\n"
289 "adc %A2,__zero_reg__\n"
302 "mov __tmp_reg__,r23\n"
304 "cp __tmp_reg__,%9\n"
332 "adc %B8,__zero_reg__\n"
367 "sbc %B8,__zero_reg__\n"
372 "adc %B8,__zero_reg__\n"
385 "sbc %B8,__zero_reg__\n"
398 "adc %A2,__zero_reg__\n"
408 "adc %A2,__zero_reg__\n"
418 "adc %A2,__zero_reg__\n"
461 :
"+r"(xlow),
"+r"(xhigh),
"+r"(ylow),
"+r"(yhigh),
462 "+Q"(slow),
"+Q"(shigh),
"+Q"(li_in),
"+Q"(li_out)
463 :
"z"(l),
"r"(rounds)
464 :
"r23",
"r24",
"r25"
468 __asm__ __volatile__ (
485 : :
"r"(xlow),
"r"(xhigh),
"r"(ylow),
"r"(yhigh),
"z"(output)
492 uint8_t li_out = rounds - 31;
497 unpack64(y, input + 8);
500 memcpy(l, k + 1, li_out *
sizeof(uint64_t));
504 for (round = rounds - 1; round > 0; --round, ++i) {
506 x = (rightRotate8_64(x) + y) ^ s;
507 y = leftRotate3_64(y) ^ x;
510 l[li_out] = (s + rightRotate8_64(l[li_in])) ^ i;
511 s = leftRotate3_64(s) ^ l[li_out];
512 li_in = (li_in + 1) & 0x03;
513 li_out = (li_out + 1) & 0x03;
517 x = (rightRotate8_64(x) + y) ^ s;
518 y = leftRotate3_64(y) ^ x;
520 pack64(output + 8, y);
void encryptBlock(uint8_t *output, const uint8_t *input)
Encrypts a single block using this cipher.
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.
void clear()
Clears all security-sensitive state from this block cipher.
void decryptBlock(uint8_t *output, const uint8_t *input)
Decrypts a single block using this cipher.
SpeckLowMemory()
Constructs a low-memory Speck block cipher with no initial key.
bool setKey(const uint8_t *key, size_t len)
Sets the key to use for future encryption and decryption operations.