; ; Copyright © Tomislav Nad, 2011. ; e-mail: . ; ; This program is a free software: you can redistribute it ; and/or modify it under the terms of the GNU General Public ; License as published by the Free Software Foundation. ; ; It is distributed without any warranty of correctness nor ; fintess for any particular purpose. See the GNU General ; Public License for more details. ; ; . ; ; Description: mCRYPTON encryption/descryption. ; Version 1 - June 2011. ; ; ; ---------------------------------------------------- ; | User interface: | ; |----------------------------------------------------| ; |(1) Load plaintext/key in SRAM at the address | ; | pointed by X register (r27:r26): | ; | -> The 8 first bytes are the plaintext/ciphert. | ; | -> The next 12 bytes are the key. | ; |----------------------------------------------------| ; |(2) Call the encrypt/decrypt routine. | ; |----------------------------------------------------| ; |(3) After the mCrypton call, the plaintext is | ; | overloaded by its corresponding ciphertext | ; | in SRAM. The key is also overwritten and need | ; | to be reloaded. | ; ---------------------------------------------------- ; ; ; Cipher Constants ; .EQU PTEXT_NUM_BYTE = 8 .EQU CTEXT_NUM_BYTE = PTEXT_NUM_BYTE .EQU KEY_NUM_BYTE = 12 .EQU ADD_MEM_NUM_BYTE = 8 ;Additional memory for internal computation .EQU TOT_NUM_BYTE = PTEXT_NUM_BYTE+KEY_NUM_BYTE+ADD_MEM_NUM_BYTE .EQU SRAM_PTEXT = SRAM_DATA .EQU SRAM_KEY = SRAM_DATA + PTEXT_NUM_BYTE .EQU SRAM_CTEXT = SRAM_PTEXT ; ; Registers declarations ; ; R >= 16 .def temp1 = R22 ; temporary storage .def temp2 = R23 ; temporary storage .def temp3 = R24 ; temporary storage .def temp4 = R25 ; temporary storage .def temp5 = R16; ; temporary storage .def temp6 = R17; ; temporary storage .def i = R21 ; round counter ; state registers, used for key schedule and enc/dec .def x0 = R0 ; state register 0 .def x1 = R1 ; state register 1 .def x2 = R2 ; state register 2 .def x3 = R3 ; state register 3 .def x4 = R4 ; state register 4 .def x5 = R5 ; state register 5 .def x6 = R6 ; state register 6 .def x7 = R7 ; state register 7 .def x8 = R8 ; state register 8 .def x9 = R9 ; state register 9 .def x10 = R10 ; state register 10 .def x11 = R11 ; state register 11 .def kc = R12 ; round key constant .cseg ; ; mCrypton encryption subroutines ram2reg: ; loads 12 bytes from SRAM to registers add r26,temp1; ld x0,x+; ld x1,x+; ld x2,x+; ld x3,x+; ld x4,x+; ld x5,x+; ld x6,x+; ld x7,x+; ld x8,x+; ld x9,x+; ld x10,x+; ld x11,x+; subi r26,12; sub r26,temp1; ret; reg2ram: ; stores 12 registers in SRAM add r26,temp1; st x+,x0; st x+,x1; st x+,x2; st x+,x3; st x+,x4; st x+,x5; st x+,x6; st x+,x7; st x+,x8; st x+,x9; st x+,x10; st x+,x11; subi r26,12; sub r26,temp1; ret; rotate16_by_6: lsl temp2; rol temp1; adc temp2,temp3; rotate16_by_5: lsl temp2; rol temp1; adc temp2,temp3; rotate16_by_4: lsl temp2; rol temp1; adc temp2,temp3; rotate16_by_3: lsl temp2; rol temp1; adc temp2,temp3; rotate16_by_2: lsl temp2; rol temp1; adc temp2,temp3; rotate16_by_1: lsl temp2; rol temp1; adc temp2,temp3; ret; ; sigma_i rowperm_sub: push temp1; push temp2; and temp1,temp3; and temp2,temp3; mov temp5,temp1; mov temp6,temp2; pop temp2; pop temp1; push temp1; push temp2; and temp1,temp4; and temp2,temp4; ;rcall rotate16_by_12; push temp2; mov temp2,temp1; pop temp1; push temp3; clc; ldi temp3,0; rcall rotate16_by_4; pop temp3; eor temp5,temp1; eor temp6,temp2; pop temp2; pop temp1; push temp1; push temp2; swap temp3; swap temp4; and temp1,temp3; and temp2,temp3; ;rcall rotate16_by_8; eor temp5,temp2; eor temp6,temp1; pop temp2; pop temp1; and temp1,temp4; and temp2,temp4; ldi temp3,0; clc; rcall rotate16_by_4; eor temp1,temp5; eor temp2,temp6; ret; rowperm: add r26,temp5; ld temp1,x+; ld temp2,x+; ldi temp3,$eb; ldi temp4,$d7; rcall rowperm_sub; subi r26,2; st x+,temp1; st x+,temp2; ld temp1,x+; ld temp2,x+; ldi temp3,$d7; ldi temp4,$be; rcall rowperm_sub subi r26,2; st x+,temp1; st x+,temp2; ld temp1,x+; ld temp2,x+; ldi temp3,$be; ldi temp4,$7d; rcall rowperm_sub subi r26,2; st x+,temp1; st x+,temp2; ld temp1,x+; ld temp2,x+; ldi temp3,$7d; ldi temp4,$eb; rcall rowperm_sub; subi r26,2; st x+,temp1; st x+,temp2; ldi r27,$00 ldi r26,$60; ret; ; sbox ; note: program size is to large such that one byte to adress ; the sbox is not enough, gamma_sub: push temp1; mov temp2,temp1; swap temp2; cbr temp2,$f0; ldi temp6,0; add r30,temp3; adc r31,temp6; add r30,temp2; adc r31,temp6; lpm temp1,z; ldi ZH, high(sbox<<1); ; reset pointer ldi ZL, low(sbox<<1); swap temp1; pop temp2; cbr temp2,$f0; add r30,temp4; adc r31,temp6; add r30,temp2; adc r31,temp6; lpm temp3,z; ldi ZH, high(sbox<<1); ; reset pointer ldi ZL, low(sbox<<1); or temp1,temp3; ret; ; ////////////////////// key scheduling //////////////////////////// ;load constant used in the keyscheduling loadkc: ldi ZH, high(constants<<1); ; set pointer to constants ldi ZL, low(constants<<1); ldi temp6,0; add r30,temp1; adc r31,temp6; lpm kc,z; ldi ZH, high(sbox<<1); ; reset pointer ldi ZL, low(sbox<<1); ret; ; computes key from U (or V in dec) keyK: mov temp1,x0; ldi temp3,0; ldi temp4,16; rcall gamma_sub; eor temp1,kc; mov temp2,temp1; cbr temp2,$0f; eor temp2,x2; ldi temp4,20; add r26,temp4; st x+,temp2; st x+,x3; mov temp2,temp1; cbr temp2,$f0; eor temp2,x4; st x+,temp2; st x+,x5; mov temp1,x1; ldi temp3,32; ldi temp4,48; rcall gamma_sub; eor temp1,kc; st x+,x6; mov temp2,temp1; cbr temp2,$0f; eor temp2,x7; st x+,temp2; st x+,x8; mov temp2,temp1; cbr temp2,$f0; eor temp2,x9; st x+,temp2; ldi r27,$00 ldi r26,$60; ret; ; encryption key function enckey: ldi temp1,8; rcall ram2reg; mov temp1,i; rcall loadkc; ; compute key from U rcall keyK; ;U0 = U5 mov temp1,x0; mov temp2,x1; mov x0,x10; mov x1,x11; ;U1 = U0<<<3 ldi temp3,0; rcall rotate16_by_3; mov temp3,x2; mov temp4,x3; mov x2,temp1; mov x3,temp2; ;U2 = U1 mov temp1,x4; mov temp2,x5; mov x4,temp3; mov x5,temp4; ;U3 = U2 mov temp3,x6; mov temp4,x7; mov x6,temp1; mov x7,temp2; ;U4 = U3<<<8 clc; mov temp1,x8; mov temp2,x9; mov x8,temp4; mov x9,temp3; ;U5 = U4 mov x10,temp1; mov x11,temp2; ; save new U to ram ldi temp1,8; rcall reg2ram; ret; ; decryption key function deckey: ldi temp1,8; rcall ram2reg; ldi temp1,12; sub temp1,i; rcall loadkc; ; compute key from V; rcall keyK; ldi temp5,20; rcall rowperm; ;V0 = V1<<<13 mov temp1,x3; mov temp2,x2; ldi temp3,0; clc; rcall rotate16_by_5; mov temp3,x0; mov temp4,x1; mov x0,temp1; mov x1,temp2; ;V1 = V2 mov x2,x4; mov x3,x5; ;V2 = V3 mov temp1,x4; mov temp2,x5; mov x4,x6; mov x5,x7; ;V3 = V4<<<8 mov x6,x9; mov x7,x8; ;V4 = V5 mov x8,x10; mov x9,x11; ;V5 = V0 mov x10,temp3; mov x11,temp4; ; save new V to ram ldi temp1,8; rcall reg2ram; ret; ; /////////////////// end key scheduling //////////////////////////// ; ///////////// encryption / decryption ////////////////////// ; key addition sigma: ldi temp1,0; rcall ram2reg; adiw r26,20; ld temp1,x+; eor x0,temp1; ld temp1,x+; eor x1,temp1; ld temp1,x+; eor x2,temp1; ld temp1,x+; eor x3,temp1; ld temp1,x+; eor x4,temp1; ld temp1,x+; eor x5,temp1; ld temp1,x+; eor x6,temp1; ld temp1,x+; eor x7,temp1; subi r26,28; ldi temp1,0; rcall reg2ram; ret; gamma: ldi temp1,0; rcall ram2reg; mov temp1,x0; ldi temp3,0; ldi temp4,16; rcall gamma_sub; mov x0,temp1; mov temp1,x1; ldi temp3,32; ldi temp4,48; rcall gamma_sub; mov x1,temp1; mov temp1,x2; ldi temp3,16; ldi temp4,32; rcall gamma_sub; mov x2,temp1; mov temp1,x3; ldi temp3,48; ldi temp4,0; rcall gamma_sub; mov x3,temp1; mov temp1,x4; ldi temp3,32; ldi temp4,48; rcall gamma_sub; mov x4,temp1; mov temp1,x5; ldi temp3,0; ldi temp4,16; rcall gamma_sub; mov x5,temp1; mov temp1,x6; ldi temp3,48; ldi temp4,0; rcall gamma_sub; mov x6,temp1; mov temp1,x7; ldi temp3,16; ldi temp4,32; rcall gamma_sub; mov x7,temp1; ldi temp1,0; rcall reg2ram; ret; gamma_dec: ldi temp1,0; rcall ram2reg; mov temp1,x0; ldi temp3,32; ldi temp4,48; rcall gamma_sub; mov x0,temp1; mov temp1,x1; ldi temp3,0; ldi temp4,16; rcall gamma_sub; mov x1,temp1; mov temp1,x2; ldi temp3,48; ldi temp4,0; rcall gamma_sub; mov x2,temp1; mov temp1,x3; ldi temp3,16; ldi temp4,32; rcall gamma_sub; mov x3,temp1; mov temp1,x4; ldi temp3,0; ldi temp4,16; rcall gamma_sub; mov x4,temp1; mov temp1,x5; ldi temp3,32; ldi temp4,48; rcall gamma_sub; mov x5,temp1; mov temp1,x6; ldi temp3,16; ldi temp4,32; rcall gamma_sub; mov x6,temp1; mov temp1,x7; ldi temp3,48; ldi temp4,0; rcall gamma_sub; mov x7,temp1; ldi temp1,0; rcall reg2ram; ret; pi_tau_sub: cbr temp1,$0f; cbr temp3,$f0; eor temp1,temp3; cbr temp4,$0f; cbr temp2,$f0; eor temp2,temp4; ret; pi_tau: ldi temp1,0; rcall ram2reg; ; E= mov temp1,x0; mov temp3,x2; swap temp3; mov temp4,x4; mov temp2,x6; swap temp2; rcall pi_tau_sub; ldi temp3,$eb; ldi temp4,$d7; rcall rowperm_sub st x+,temp1; st x+,temp2; ; F= mov temp1,x0; swap temp1; mov temp3,x2; mov temp4,x4; swap temp4; mov temp2,x6; rcall pi_tau_sub; ldi temp3,$d7; ldi temp4,$be; rcall rowperm_sub st x+,temp1; st x+,temp2; ; G= mov temp1,x1; mov temp3,x3; swap temp3; mov temp4,x5; mov temp2,x7; swap temp2; rcall pi_tau_sub; ldi temp3,$be; ldi temp4,$7d; rcall rowperm_sub st x+,temp1; st x+,temp2; ; F= mov temp1,x1; swap temp1; mov temp3,x3; mov temp4,x5; swap temp4; mov temp2,x7; rcall pi_tau_sub; ldi temp3,$7d; ldi temp4,$eb; rcall rowperm_sub st x+,temp1; st x+,temp2; ldi r26,$60; ret; ; /////////////////// encryption //////////////////////////// encrypt: clr i ; reset the round counter bset 6 ; T bit set => encrypt rcall enckey; inc i; ; initial key addition rcall sigma; enc1: rcall enckey; rcall gamma; rcall pi_tau; rcall sigma; cpi i,12; breq end; inc i; rjmp enc1; end: ;finalization ldi temp5,0; rcall rowperm; ret; ; /////////////////// end encryption //////////////////////////// ; /////////////////// decryption //////////////////////////// decrypt: clr i ; reset the round counter bclr 6 ; T bit cleared => decrypt ldi temp1,8; rcall ram2reg; ; rotate key words by 6 ldi temp3,0; mov temp1,x0; mov temp2,x1; rcall rotate16_by_6; mov x0,temp1; mov x1,temp2; mov temp1,x2; mov temp2,x3; rcall rotate16_by_6; mov x2,temp1; mov x3,temp2; mov temp1,x4; mov temp2,x5; rcall rotate16_by_6; mov x4,temp1; mov x5,temp2; mov temp1,x6; mov temp2,x7; rcall rotate16_by_6; mov x6,temp1; mov x7,temp2; mov temp1,x8; mov temp2,x9; rcall rotate16_by_6; mov x8,temp1; mov x9,temp2; mov temp1,x10; mov temp2,x11; rcall rotate16_by_6; mov x10,temp1; mov x11,temp2; ldi temp1,8; rcall reg2ram; rcall deckey; inc i; ; initial key addition rcall sigma; dec1: rcall deckey; rcall gamma_dec; rcall pi_tau; rcall sigma; cpi i,12; breq end; inc i; rjmp dec1; ret; ; /////////////////// end decryption /////////////////////////// sbox: .db $4, $f, $3, $8, $d, $a, $c, $0, $b, $5, $7, $e, $2, $6, $1,$9 .db $1, $c, $7, $a, $6, $d, $5, $3, $f, $b, $2, $0, $8, $4, $9,$e .db $7, $e, $c, $2, $0, $9, $d, $a, $3, $f, $5, $8, $6, $4, $b,$1 .db $b, $0, $a, $7, $d, $6, $4, $2, $c, $e, $3, $9, $1, $5, $f,$8 constants: .db $11, $22, $44, $88, $33, $66, $cc, $bb, $55, $aa, $77, $ee, $ff; key constants