3 This file is part of the AVR-Crypto-Lib.
4 Copyright (C) 2006-2015 Daniel Otte (bg@nerilex.org)
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * noekeon assembler implementation for avr
22 * email: bg@nerilex.org
97 .macro op32_4t op a b c d w x y z
105 .macro op32_prefix op p q a b c d w x y z
112 ; === bigendian_rotl32 ===
113 ; this function rotates a 32bit bigendian word n bits to the left
114 ; param1: the 32-bit value
115 ; given in r25,r24,r23,r22 (r22 is most significant)
116 ; param2: the 8-bit parameter giving the number of bits to rotate
118 ; return: the rotatet 32-bit word
119 ; given in r25,r24,r23,r22
122 /* copy high bit of r22 to carry */
134 bigendian_rotl32_exit:
139 /******************************************************************************/
141 ; === bigendian_rotl32 ===
142 ; this function rotates a 32bit bigendian word n bits to the right
143 ; param1: the 32-bit value
144 ; given in r25,r24,r23,r22 (r22 is most significant)
145 ; param2: the 8-bit parameter giving the number of bits to rotate
147 ; return: the rotatet 32-bit word
148 ; given in r25,r24,r23,r22
151 /* copy high bit of r25 to carry */
163 bigendian_rotr32_exit:
167 /******************************************************************************/
169 void theta(uint32_t *k, uint32_t *a){
171 temp = a[0] ^ a[2]; temp ^= ROTR32(temp, 8) ^ ROTL32(temp, 8);
180 temp = a[1] ^ a[3]; temp ^= ROTR32(temp, 8) ^ ROTL32(temp, 8);
186 round_const: .byte 0x1B, 0x36, 0x6C, 0xD8, 0xAB, 0x4D, 0x9A, \
187 0x2F, 0x5E, 0xBC, 0x63, 0xC6, 0x97, 0x35, 0x6A, \
213 ; param1: the state in r2-r17
214 ; param2: pointer to k in X (r26,r27)
222 /* temp = a[0] ^ a[2]; temp ^= temp>>>8 ^ temp<<<8 */
223 op32_prefix mov, temp_, state0_, a,b,c,d, 0,1,2,3
224 op32_prefix eor, temp_, state2_, a,b,c,d, 0,1,2,3
231 op32_prefix eor, temp_, r, a,b,c,d, 1,1,1,1
233 /* temp is know a little bit mixed c,d,a,b (if abcd is normal order) */
245 /* state ^ k (X points to K) */
247 clr r29 /* Y points to r2 aka state0_0 */
256 sbiw r26, 16 /* set X back to key */
274 /* temp is know a little bit mixed c,d,a,b (if abcd is normal order) */
289 /******************************************************************************/
290 #ifndef NOEKEON_NO_ENC
291 ; === noekeon_enc ===
293 ; param1: pointer to buffer (r24,r25)
294 ; param2: pointer to k (r22,r23)
302 clr r29 /* Y points at r2 aka state0_0 */
303 movw r30, r24 /* Z points at state */
307 push r22 /* 16 is also the number of rounds and gets pushed here */
314 push r1 /* push round constan2 (0x00) */
316 push r20 /* push round constan2 (0x00) */
319 ldi r30, lo8(round_const+15)
320 ldi r31, hi8(round_const+15)
328 rcall round /* pops rc2 & rc1 */
354 /******************************************************************************/
355 /******************************************************************************/
356 #ifndef NOEKEON_NO_DEC
358 ; === noekeon_dec ===
360 ; param1: pointer to buffer/state (r24,r25)
361 ; param2: pointer to k (r22,r23)
366 /* allocate 16 bytes on the stack */
367 in r30, _SFR_IO_ADDR(SPL)
368 in r31, _SFR_IO_ADDR(SPH)
370 out _SFR_IO_ADDR(SPH), r31
371 out _SFR_IO_ADDR(SPL), r30
374 /* push state pointer */
377 movw r26, r22 /* move key ptr to X */
379 /* set stackkey to zero */
385 /* copy key to state */
395 sbiw r26, 16 /* set X back to begining of stack key */
398 /* mov state to stackkey */
406 sbiw r26, 16 /* set X back to begining of stack key */
408 /* move data from stateptr to state */
425 push r20 /* push round constant2 (0xD4) */
426 push r22 /* push round constan1 (0x00) */
429 ldi r30, lo8(round_const-1)
430 ldi r31, hi8(round_const-1)
438 rcall round /* pops rc2 & rc1 */
451 /* write state back */
452 pop r31 /* pop state pointer */
463 /* remove key from stack */
464 in r30, _SFR_IO_ADDR(SPL)
465 in r31, _SFR_IO_ADDR(SPH)
467 out _SFR_IO_ADDR(SPH), r31
468 out _SFR_IO_ADDR(SPL), r30
472 /******************************************************************************/
486 ldi r30, pm_lo8(bigendian_rotl32)
487 ldi r31, pm_hi8(bigendian_rotl32)
489 /* pi1 done; now gamma */
492 xchg state0_0, state3_0
493 xchg state0_1, state3_1
494 xchg state0_2, state3_2
495 xchg state0_3, state3_3
496 /* a[2] ^= a[0] ^ a[1] ^ a[3] */
497 op32 eor, state2, state0
498 op32 eor, state2, state1
499 op32 eor, state2, state3
502 ldi r30, pm_lo8(bigendian_rotr32)
503 ldi r31, pm_hi8(bigendian_rotr32)
508 /* a[1] ^= ~(a[3]|a[2])*/
529 /* a[0] ^= a[2]&a[1] */
583 /******************************************************************************/
586 void noekeon_init(void *key, noekeon_ctx_t *ctx){
589 memset(nullv, 0, 16);
590 memcpy(ctx, key, 16);
591 noekeon_enc(ctx, nullv);
595 #ifndef NOEKEON_NO_INIT
599 ; === noekeon_init ===
601 ; param1: pointer to key (r24,r25)
602 ; param2: pointer to context (r22,r23)
604 in r30, _SFR_IO_ADDR(SPL)
605 in r31, _SFR_IO_ADDR(SPH)
607 out _SFR_IO_ADDR(SPH), r31
608 out _SFR_IO_ADDR(SPL), r30
613 /* set nullv(stack) to zero */
619 /* copy key data to ctx */
632 in r30, _SFR_IO_ADDR(SPL)
633 in r31, _SFR_IO_ADDR(SPH)
635 out _SFR_IO_ADDR(SPH), r31
636 out _SFR_IO_ADDR(SPL), r30