Arduino Cryptography Library
Acorn128.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 #include "Crypto.h"
25 #include "utility/EndianUtil.h"
26 #include <string.h>
27 
47 {
48  state.authDone = 0;
49 }
50 
55 {
56  clean(state);
57 }
58 
64 size_t Acorn128::keySize() const
65 {
66  return 16;
67 }
68 
77 size_t Acorn128::ivSize() const
78 {
79  return 16;
80 }
81 
87 size_t Acorn128::tagSize() const
88 {
89  return 16;
90 }
91 
92 // Acorn128 constants for ca and cb.
93 #define CA_0 ((uint32_t)0x00000000)
94 #define CA_1 ((uint32_t)0xFFFFFFFF)
95 #define CB_0 ((uint32_t)0x00000000)
96 #define CB_1 ((uint32_t)0xFFFFFFFF)
97 #define CA_0_BYTE ((uint8_t)0x00)
98 #define CA_1_BYTE ((uint8_t)0xFF)
99 #define CB_0_BYTE ((uint8_t)0x00)
100 #define CB_1_BYTE ((uint8_t)0xFF)
101 
102 #if defined(CRYPTO_ACORN128_DEFAULT) || defined(CRYPTO_DOC)
103 
104 // maj() and ch() functions for mixing the state.
105 #define maj(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
106 #define ch(x, y, z) (((x) & (y)) ^ ((~(x)) & (z)))
107 
118 static uint8_t acornEncrypt8
119  (Acorn128State *state, uint8_t plaintext, uint8_t ca, uint8_t cb)
120 {
121  // Extract out various sub-parts of the state as 8-bit bytes.
122  #define s_extract_8(name, shift) \
123  ((uint8_t)(state->name##_l >> (shift)))
124  uint8_t s244 = s_extract_8(s6, 14);
125  uint8_t s235 = s_extract_8(s6, 5);
126  uint8_t s196 = s_extract_8(s5, 3);
127  uint8_t s160 = s_extract_8(s4, 6);
128  uint8_t s111 = s_extract_8(s3, 4);
129  uint8_t s66 = s_extract_8(s2, 5);
130  uint8_t s23 = s_extract_8(s1, 23);
131  uint8_t s12 = s_extract_8(s1, 12);
132 
133  // Update the LFSR's.
134  uint8_t s7_l = state->s7 ^ s235 ^ state->s6_l;
135  state->s6_l ^= s196 ^ ((uint8_t)(state->s5_l));
136  state->s5_l ^= s160 ^ ((uint8_t)(state->s4_l));
137  state->s4_l ^= s111 ^ ((uint8_t)(state->s3_l));
138  state->s3_l ^= s66 ^ ((uint8_t)(state->s2_l));
139  state->s2_l ^= s23 ^ ((uint8_t)(state->s1_l));
140 
141  // Generate the next 8 keystream bits.
142  // k = S[12] ^ S[154] ^ maj(S[235], S[61], S[193])
143  // ^ ch(S[230], S[111], S[66])
144  uint8_t ks = s12 ^ state->s4_l ^
145  maj(s235, state->s2_l, state->s5_l) ^
146  ch(state->s6_l, s111, s66);
147 
148  // Generate the next 8 non-linear feedback bits.
149  // f = S[0] ^ ~S[107] ^ maj(S[244], S[23], S[160])
150  // ^ (ca & S[196]) ^ (cb & ks)
151  // f ^= plaintext
152  uint8_t f = state->s1_l ^ (~state->s3_l) ^
153  maj(s244, s23, s160) ^ (ca & s196) ^ (cb & ks);
154  f ^= plaintext;
155 
156  // Shift the state downwards by 8 bits.
157  #define s_shift_8(name1, name2, shift) \
158  (state->name1##_l = (state->name1##_l >> 8) | \
159  (((uint32_t)(state->name1##_h)) << 24), \
160  state->name1##_h = (state->name1##_h >> 8) | \
161  ((state->name2##_l & 0xFF) << ((shift) - 40)))
162  #define s_shift_8_mixed(name1, name2, shift) \
163  (state->name1##_l = (state->name1##_l >> 8) | \
164  (((uint32_t)(state->name1##_h)) << 24) | \
165  (state->name2##_l << ((shift) - 8)), \
166  state->name1##_h = ((state->name2##_l & 0xFF) >> (40 - (shift))))
167  s7_l ^= (f << 4);
168  state->s7 = f >> 4;
169  s_shift_8(s1, s2, 61);
170  s_shift_8(s2, s3, 46);
171  s_shift_8(s3, s4, 47);
172  s_shift_8_mixed(s4, s5, 39);
173  s_shift_8_mixed(s5, s6, 37);
174  state->s6_l = (state->s6_l >> 8) | (state->s6_h << 24);
175  state->s6_h = (state->s6_h >> 8) | (((uint32_t)s7_l) << 19);
176 
177  // Return the ciphertext byte to the caller.
178  return plaintext ^ ks;
179 }
180 
191 static uint32_t acornEncrypt32
192  (Acorn128State *state, uint32_t plaintext, uint32_t ca, uint32_t cb)
193 {
194  // Extract out various sub-parts of the state as 32-bit words.
195  #define s_extract_32(name, shift) \
196  ((state->name##_l >> (shift)) | \
197  (((uint32_t)(state->name##_h)) << (32 - (shift))))
198  uint32_t s244 = s_extract_32(s6, 14);
199  uint32_t s235 = s_extract_32(s6, 5);
200  uint32_t s196 = s_extract_32(s5, 3);
201  uint32_t s160 = s_extract_32(s4, 6);
202  uint32_t s111 = s_extract_32(s3, 4);
203  uint32_t s66 = s_extract_32(s2, 5);
204  uint32_t s23 = s_extract_32(s1, 23);
205  uint32_t s12 = s_extract_32(s1, 12);
206 
207  // Update the LFSR's.
208  uint32_t s7_l = state->s7 ^ s235 ^ state->s6_l;
209  state->s6_l ^= s196 ^ state->s5_l;
210  state->s5_l ^= s160 ^ state->s4_l;
211  state->s4_l ^= s111 ^ state->s3_l;
212  state->s3_l ^= s66 ^ state->s2_l;
213  state->s2_l ^= s23 ^ state->s1_l;
214 
215  // Generate the next 32 keystream bits.
216  // k = S[12] ^ S[154] ^ maj(S[235], S[61], S[193])
217  // ^ ch(S[230], S[111], S[66])
218  uint32_t ks = s12 ^ state->s4_l ^
219  maj(s235, state->s2_l, state->s5_l) ^
220  ch(state->s6_l, s111, s66);
221 
222  // Generate the next 32 non-linear feedback bits.
223  // f = S[0] ^ ~S[107] ^ maj(S[244], S[23], S[160])
224  // ^ (ca & S[196]) ^ (cb & ks)
225  // f ^= plaintext
226  uint32_t f = state->s1_l ^ (~state->s3_l) ^
227  maj(s244, s23, s160) ^ (ca & s196) ^ (cb & ks);
228  f ^= plaintext;
229 
230  // Shift the state downwards by 32 bits.
231  #define s_shift_32(name1, name2, shift) \
232  (state->name1##_l = state->name1##_h | (state->name2##_l << (shift)), \
233  state->name1##_h = (state->name2##_l >> (32 - (shift))))
234  s7_l ^= (f << 4);
235  state->s7 = (uint8_t)(f >> 28);
236  s_shift_32(s1, s2, 29);
237  s_shift_32(s2, s3, 14);
238  s_shift_32(s3, s4, 15);
239  s_shift_32(s4, s5, 7);
240  s_shift_32(s5, s6, 5);
241  state->s6_l = state->s6_h | (s7_l << 27);
242  state->s6_h = s7_l >> 5;
243 
244  // Return the ciphertext word to the caller.
245  return plaintext ^ ks;
246 }
247 
258 static inline uint32_t acornEncrypt32Fast
259  (Acorn128State *state, uint32_t plaintext)
260 {
261  // Extract out various sub-parts of the state as 32-bit words.
262  #define s_extract_32(name, shift) \
263  ((state->name##_l >> (shift)) | \
264  (((uint32_t)(state->name##_h)) << (32 - (shift))))
265  uint32_t s244 = s_extract_32(s6, 14);
266  uint32_t s235 = s_extract_32(s6, 5);
267  uint32_t s196 = s_extract_32(s5, 3);
268  uint32_t s160 = s_extract_32(s4, 6);
269  uint32_t s111 = s_extract_32(s3, 4);
270  uint32_t s66 = s_extract_32(s2, 5);
271  uint32_t s23 = s_extract_32(s1, 23);
272  uint32_t s12 = s_extract_32(s1, 12);
273 
274  // Update the LFSR's.
275  uint32_t s7_l = state->s7 ^ s235 ^ state->s6_l;
276  state->s6_l ^= s196 ^ state->s5_l;
277  state->s5_l ^= s160 ^ state->s4_l;
278  state->s4_l ^= s111 ^ state->s3_l;
279  state->s3_l ^= s66 ^ state->s2_l;
280  state->s2_l ^= s23 ^ state->s1_l;
281 
282  // Generate the next 32 keystream bits.
283  // k = S[12] ^ S[154] ^ maj(S[235], S[61], S[193])
284  // ^ ch(S[230], S[111], S[66])
285  uint32_t ks = s12 ^ state->s4_l ^
286  maj(s235, state->s2_l, state->s5_l) ^
287  ch(state->s6_l, s111, s66);
288 
289  // Generate the next 32 non-linear feedback bits.
290  // f = S[0] ^ ~S[107] ^ maj(S[244], S[23], S[160])
291  // ^ (ca & S[196]) ^ (cb & ks)
292  // f ^= plaintext
293  // Note: ca will always be 1 and cb will always be 0.
294  uint32_t f = state->s1_l ^ (~state->s3_l) ^ maj(s244, s23, s160) ^ s196;
295  f ^= plaintext;
296 
297  // Shift the state downwards by 32 bits.
298  #define s_shift_32(name1, name2, shift) \
299  (state->name1##_l = state->name1##_h | (state->name2##_l << (shift)), \
300  state->name1##_h = (state->name2##_l >> (32 - (shift))))
301  s7_l ^= (f << 4);
302  state->s7 = (uint8_t)(f >> 28);
303  s_shift_32(s1, s2, 29);
304  s_shift_32(s2, s3, 14);
305  s_shift_32(s3, s4, 15);
306  s_shift_32(s4, s5, 7);
307  s_shift_32(s5, s6, 5);
308  state->s6_l = state->s6_h | (s7_l << 27);
309  state->s6_h = s7_l >> 5;
310 
311  // Return the ciphertext word to the caller.
312  return plaintext ^ ks;
313 }
314 
323 static inline uint8_t acornDecrypt8(Acorn128State *state, uint8_t ciphertext)
324 {
325  // Extract out various sub-parts of the state as 8-bit bytes.
326  #define s_extract_8(name, shift) \
327  ((uint8_t)(state->name##_l >> (shift)))
328  uint8_t s244 = s_extract_8(s6, 14);
329  uint8_t s235 = s_extract_8(s6, 5);
330  uint8_t s196 = s_extract_8(s5, 3);
331  uint8_t s160 = s_extract_8(s4, 6);
332  uint8_t s111 = s_extract_8(s3, 4);
333  uint8_t s66 = s_extract_8(s2, 5);
334  uint8_t s23 = s_extract_8(s1, 23);
335  uint8_t s12 = s_extract_8(s1, 12);
336 
337  // Update the LFSR's.
338  uint8_t s7_l = state->s7 ^ s235 ^ state->s6_l;
339  state->s6_l ^= s196 ^ ((uint8_t)(state->s5_l));
340  state->s5_l ^= s160 ^ ((uint8_t)(state->s4_l));
341  state->s4_l ^= s111 ^ ((uint8_t)(state->s3_l));
342  state->s3_l ^= s66 ^ ((uint8_t)(state->s2_l));
343  state->s2_l ^= s23 ^ ((uint8_t)(state->s1_l));
344 
345  // Generate the next 8 keystream bits and decrypt the ciphertext.
346  // k = S[12] ^ S[154] ^ maj(S[235], S[61], S[193])
347  // ^ ch(S[230], S[111], S[66])
348  uint8_t ks = s12 ^ state->s4_l ^
349  maj(s235, state->s2_l, state->s5_l) ^
350  ch(state->s6_l, s111, s66);
351  uint8_t plaintext = ciphertext ^ ks;
352 
353  // Generate the next 8 non-linear feedback bits.
354  // f = S[0] ^ ~S[107] ^ maj(S[244], S[23], S[160])
355  // ^ (ca & S[196]) ^ (cb & ks)
356  // f ^= plaintext
357  // Note: ca will always be 1 and cb will always be 0.
358  uint8_t f = state->s1_l ^ (~state->s3_l) ^ maj(s244, s23, s160) ^ s196;
359  f ^= plaintext;
360 
361  // Shift the state downwards by 8 bits.
362  #define s_shift_8(name1, name2, shift) \
363  (state->name1##_l = (state->name1##_l >> 8) | \
364  (((uint32_t)(state->name1##_h)) << 24), \
365  state->name1##_h = (state->name1##_h >> 8) | \
366  ((state->name2##_l & 0xFF) << ((shift) - 40)))
367  #define s_shift_8_mixed(name1, name2, shift) \
368  (state->name1##_l = (state->name1##_l >> 8) | \
369  (((uint32_t)(state->name1##_h)) << 24) | \
370  (state->name2##_l << ((shift) - 8)), \
371  state->name1##_h = ((state->name2##_l & 0xFF) >> (40 - (shift))))
372  s7_l ^= (f << 4);
373  state->s7 = f >> 4;
374  s_shift_8(s1, s2, 61);
375  s_shift_8(s2, s3, 46);
376  s_shift_8(s3, s4, 47);
377  s_shift_8_mixed(s4, s5, 39);
378  s_shift_8_mixed(s5, s6, 37);
379  state->s6_l = (state->s6_l >> 8) | (state->s6_h << 24);
380  state->s6_h = (state->s6_h >> 8) | (((uint32_t)s7_l) << 19);
381 
382  // Return the plaintext byte to the caller.
383  return plaintext;
384 }
385 
394 static inline uint32_t acornDecrypt32(Acorn128State *state, uint32_t ciphertext)
395 {
396  // Extract out various sub-parts of the state as 32-bit words.
397  #define s_extract_32(name, shift) \
398  ((state->name##_l >> (shift)) | \
399  (((uint32_t)(state->name##_h)) << (32 - (shift))))
400  uint32_t s244 = s_extract_32(s6, 14);
401  uint32_t s235 = s_extract_32(s6, 5);
402  uint32_t s196 = s_extract_32(s5, 3);
403  uint32_t s160 = s_extract_32(s4, 6);
404  uint32_t s111 = s_extract_32(s3, 4);
405  uint32_t s66 = s_extract_32(s2, 5);
406  uint32_t s23 = s_extract_32(s1, 23);
407  uint32_t s12 = s_extract_32(s1, 12);
408 
409  // Update the LFSR's.
410  uint32_t s7_l = state->s7 ^ s235 ^ state->s6_l;
411  state->s6_l ^= s196 ^ state->s5_l;
412  state->s5_l ^= s160 ^ state->s4_l;
413  state->s4_l ^= s111 ^ state->s3_l;
414  state->s3_l ^= s66 ^ state->s2_l;
415  state->s2_l ^= s23 ^ state->s1_l;
416 
417  // Generate the next 32 keystream bits and decrypt the ciphertext.
418  // k = S[12] ^ S[154] ^ maj(S[235], S[61], S[193])
419  // ^ ch(S[230], S[111], S[66])
420  uint32_t ks = s12 ^ state->s4_l ^
421  maj(s235, state->s2_l, state->s5_l) ^
422  ch(state->s6_l, s111, s66);
423  uint32_t plaintext = ciphertext ^ ks;
424 
425  // Generate the next 32 non-linear feedback bits.
426  // f = S[0] ^ ~S[107] ^ maj(S[244], S[23], S[160])
427  // ^ (ca & S[196]) ^ (cb & ks)
428  // f ^= plaintext
429  // Note: ca will always be 1 and cb will always be 0.
430  uint32_t f = state->s1_l ^ (~state->s3_l) ^ maj(s244, s23, s160) ^ s196;
431  f ^= plaintext;
432 
433  // Shift the state downwards by 32 bits.
434  #define s_shift_32(name1, name2, shift) \
435  (state->name1##_l = state->name1##_h | (state->name2##_l << (shift)), \
436  state->name1##_h = (state->name2##_l >> (32 - (shift))))
437  s7_l ^= (f << 4);
438  state->s7 = (uint8_t)(f >> 28);
439  s_shift_32(s1, s2, 29);
440  s_shift_32(s2, s3, 14);
441  s_shift_32(s3, s4, 15);
442  s_shift_32(s4, s5, 7);
443  s_shift_32(s5, s6, 5);
444  state->s6_l = state->s6_h | (s7_l << 27);
445  state->s6_h = s7_l >> 5;
446 
447  // Return the plaintext word to the caller.
448  return plaintext;
449 }
450 
451 #elif defined(CRYPTO_ACORN128_AVR)
452 
453 // Import definitions from Acorn128AVR.cpp
454 extern uint32_t acornEncrypt32
455  (Acorn128State *state, uint32_t plaintext, uint32_t ca, uint32_t cb);
456 
457 #endif // CRYPTO_ACORN128_AVR
458 
465 void acornPad(Acorn128State *state, uint32_t cb)
466 {
467  acornEncrypt32(state, 1, CA_1, cb);
468  acornEncrypt32(state, 0, CA_1, cb);
469  acornEncrypt32(state, 0, CA_1, cb);
470  acornEncrypt32(state, 0, CA_1, cb);
471  acornEncrypt32(state, 0, CA_0, cb);
472  acornEncrypt32(state, 0, CA_0, cb);
473  acornEncrypt32(state, 0, CA_0, cb);
474  acornEncrypt32(state, 0, CA_0, cb);
475 }
476 
477 bool Acorn128::setKey(const uint8_t *key, size_t len)
478 {
479  // We cannot initialize the key block until we also have the IV.
480  // So we simply validate the length and save the key away for later.
481  if (len == 16) {
482  memcpy(state.k, key, 16);
483 #if !defined(CRYPTO_LITTLE_ENDIAN)
484  state.k[0] = le32toh(state.k[0]);
485  state.k[1] = le32toh(state.k[1]);
486  state.k[2] = le32toh(state.k[2]);
487  state.k[3] = le32toh(state.k[3]);
488 #endif
489  return true;
490  } else {
491  return false;
492  }
493 }
494 
495 bool Acorn128::setIV(const uint8_t *iv, size_t len)
496 {
497  if (len != 16)
498  return false;
499 
500  // Unpack the iv into four 32-bit words.
501  uint32_t ivwords[4];
502  memcpy(ivwords, iv, 16);
503 #if !defined(CRYPTO_LITTLE_ENDIAN)
504  ivwords[0] = le32toh(ivwords[0]);
505  ivwords[1] = le32toh(ivwords[1]);
506  ivwords[2] = le32toh(ivwords[2]);
507  ivwords[3] = le32toh(ivwords[3]);
508 #endif
509 
510  // Initialize the state to zero.
511  state.s1_l = 0;
512  state.s1_h = 0;
513  state.s2_l = 0;
514  state.s2_h = 0;
515  state.s3_h = 0;
516  state.s3_l = 0;
517  state.s4_l = 0;
518  state.s4_h = 0;
519  state.s5_h = 0;
520  state.s5_l = 0;
521  state.s6_l = 0;
522  state.s6_h = 0;
523  state.s7 = 0;
524  state.authDone = 0;
525 
526  // Run the cipher for 1792 steps, 32 at a time,
527  // which mixes the key and IV into the cipher state.
528  acornEncrypt32(&state, state.k[0], CA_1, CB_1);
529  acornEncrypt32(&state, state.k[1], CA_1, CB_1);
530  acornEncrypt32(&state, state.k[2], CA_1, CB_1);
531  acornEncrypt32(&state, state.k[3], CA_1, CB_1);
532  acornEncrypt32(&state, ivwords[0], CA_1, CB_1);
533  acornEncrypt32(&state, ivwords[1], CA_1, CB_1);
534  acornEncrypt32(&state, ivwords[2], CA_1, CB_1);
535  acornEncrypt32(&state, ivwords[3], CA_1, CB_1);
536  acornEncrypt32(&state, state.k[0] ^ 0x00000001, CA_1, CB_1);
537  acornEncrypt32(&state, state.k[1], CA_1, CB_1);
538  acornEncrypt32(&state, state.k[2], CA_1, CB_1);
539  acornEncrypt32(&state, state.k[3], CA_1, CB_1);
540  for (uint8_t i = 0; i < 11; ++i) {
541  acornEncrypt32(&state, state.k[0], CA_1, CB_1);
542  acornEncrypt32(&state, state.k[1], CA_1, CB_1);
543  acornEncrypt32(&state, state.k[2], CA_1, CB_1);
544  acornEncrypt32(&state, state.k[3], CA_1, CB_1);
545  }
546 
547  // Clean up and exit.
548  clean(ivwords);
549  return true;
550 }
551 
552 #if defined(CRYPTO_ACORN128_DEFAULT) || defined(CRYPTO_DOC)
553 
554 void Acorn128::encrypt(uint8_t *output, const uint8_t *input, size_t len)
555 {
556  if (!state.authDone) {
557  acornPad(&state, CB_1);
558  state.authDone = 1;
559  }
560  while (len >= 4) {
561  uint32_t temp = ((uint32_t)input[0]) |
562  (((uint32_t)input[1]) << 8) |
563  (((uint32_t)input[2]) << 16) |
564  (((uint32_t)input[3]) << 24);
565  temp = acornEncrypt32Fast(&state, temp);
566  output[0] = (uint8_t)temp;
567  output[1] = (uint8_t)(temp >> 8);
568  output[2] = (uint8_t)(temp >> 16);
569  output[3] = (uint8_t)(temp >> 24);
570  input += 4;
571  output += 4;
572  len -= 4;
573  }
574  while (len > 0) {
575  *output++ = acornEncrypt8(&state, *input++, CA_1_BYTE, CB_0_BYTE);
576  --len;
577  }
578 }
579 
580 void Acorn128::decrypt(uint8_t *output, const uint8_t *input, size_t len)
581 {
582  if (!state.authDone) {
583  acornPad(&state, CB_1);
584  state.authDone = 1;
585  }
586  while (len >= 4) {
587  uint32_t temp = ((uint32_t)input[0]) |
588  (((uint32_t)input[1]) << 8) |
589  (((uint32_t)input[2]) << 16) |
590  (((uint32_t)input[3]) << 24);
591  temp = acornDecrypt32(&state, temp);
592  output[0] = (uint8_t)temp;
593  output[1] = (uint8_t)(temp >> 8);
594  output[2] = (uint8_t)(temp >> 16);
595  output[3] = (uint8_t)(temp >> 24);
596  input += 4;
597  output += 4;
598  len -= 4;
599  }
600  while (len > 0) {
601  *output++ = acornDecrypt8(&state, *input++);
602  --len;
603  }
604 }
605 
606 void Acorn128::addAuthData(const void *data, size_t len)
607 {
608  // Cannot add any more auth data if we've started to encrypt or decrypt.
609  if (state.authDone)
610  return;
611 
612  // Encrypt the auth data with ca = 1, cb = 1.
613  const uint8_t *input = (const uint8_t *)data;
614  while (len >= 4) {
615  uint32_t temp = ((uint32_t)input[0]) |
616  (((uint32_t)input[1]) << 8) |
617  (((uint32_t)input[2]) << 16) |
618  (((uint32_t)input[3]) << 24);
619  acornEncrypt32(&state, temp, CA_1, CB_1);
620  input += 4;
621  len -= 4;
622  }
623  while (len > 0) {
624  acornEncrypt8(&state, *input++, CA_1_BYTE, CB_1_BYTE);
625  --len;
626  }
627 }
628 
629 #endif // CRYPTO_ACORN128_DEFAULT
630 
631 void Acorn128::computeTag(void *tag, size_t len)
632 {
633  // Finalize the data and apply padding.
634  if (!state.authDone)
635  acornPad(&state, CB_1);
636  acornPad(&state, CB_0);
637 
638  // Encrypt 768 zero bits and extract the last 128 for the tag.
639  uint32_t temp[4];
640  for (uint8_t i = 0; i < 20; ++i)
641  acornEncrypt32(&state, 0, CA_1, CB_1);
642  temp[0] = acornEncrypt32(&state, 0, CA_1, CB_1);
643  temp[1] = acornEncrypt32(&state, 0, CA_1, CB_1);
644  temp[2] = acornEncrypt32(&state, 0, CA_1, CB_1);
645  temp[3] = acornEncrypt32(&state, 0, CA_1, CB_1);
646 #if !defined(CRYPTO_LITTLE_ENDIAN)
647  temp[0] = htole32(temp[0]);
648  temp[1] = htole32(temp[1]);
649  temp[2] = htole32(temp[2]);
650  temp[3] = htole32(temp[3]);
651 #endif
652 
653  // Truncate to the requested length and return the value.
654  if (len > 16)
655  len = 16;
656  memcpy(tag, temp, len);
657  clean(temp);
658 }
659 
660 bool Acorn128::checkTag(const void *tag, size_t len)
661 {
662  // Can never match if the expected tag length is too long.
663  if (len > 16)
664  return false;
665 
666  // Compute the authentication tag and check it.
667  uint8_t temp[16];
668  computeTag(temp, len);
669  bool equal = secure_compare(temp, tag, len);
670  clean(temp);
671  return equal;
672 }
673 
678 {
679  clean(state);
680 }
bool checkTag(const void *tag, size_t len)
Finalizes the decryption process and checks the authentication tag.
Definition: Acorn128.cpp:660
virtual ~Acorn128()
Destroys this Acorn128 authenticated cipher.
Definition: Acorn128.cpp:54
bool setKey(const uint8_t *key, size_t len)
Sets the key to use for future encryption and decryption operations.
Definition: Acorn128.cpp:477
void computeTag(void *tag, size_t len)
Finalizes the encryption process and computes the authentication tag.
Definition: Acorn128.cpp:631
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
size_t keySize() const
Gets the size of the Acorn128 key in bytes.
Definition: Acorn128.cpp:64
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
size_t tagSize() const
Gets the size of the Acorn128 authentication tag in bytes.
Definition: Acorn128.cpp:87
void addAuthData(const void *data, size_t len)
Adds extra data that will be authenticated but not encrypted.
Definition: Acorn128.cpp:606
void clear()
Clears all security-sensitive state from this cipher object.
Definition: Acorn128.cpp:677
bool setIV(const uint8_t *iv, size_t len)
Sets the initialization vector to use for future encryption and decryption operations.
Definition: Acorn128.cpp:495
size_t ivSize() const
Gets the size of the Acorn128 initialization vector in bytes.
Definition: Acorn128.cpp:77
Acorn128()
Constructs a new Acorn128 authenticated cipher.
Definition: Acorn128.cpp:46