; ============================================================ ; des_ks.S - DES routines (with key schedule precomputation) ; ; Copyright (C) 2010-2013, Tomas Pecina ; ; This file is part of PICCE, an open source PICC emulator. ; ; PICCE is 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, either version 3 of the License, or ; (at your option) any later version. ; ; PICCE is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with this program. If not, see . ; #include "picce.inc" ; ============================================================ ; Permute bits in registers according to inline pattern ; .macro perm dbase, sbase, pattern:vararg idx = 0 .irp p, \pattern bst (\sbase) + (idx / 8), idx % 8 bld (\dbase) + ((\p) / 16), (\p) % 16 idx = idx + 1 .endr .endm ; ============================================================ ; Permute bits in registers according to inline pattern ; (with suport for multiple destinations) ; .macro mperm dbase, sbase, pattern:vararg idx = 0 tld = 0 .irp p, \pattern .ifeq (\p) + 1 idx = idx + 1 tld = 0 .else .ifeq tld tld = 1 bst (\sbase) + (idx / 8), idx % 8 .endif bld (\dbase) + ((\p) / 16), (\p) % 16 .endif .endr .endm ; ============================================================ ; desks - prepare DES key schedule ; input: r8-r15 - key ; X - pointer to key schedule buffer (128 bytes) ; output: key schedule ; X - incremented ; uses: r0-r15, CL, CH, Z, T ; .global desks desks: ; initialize variables ldiw ZX, numrot ldi CH, 16 ; Permuted Choice 1 (PC-1) mperm 0, 8, -1, 0x44, -1, 0x54, -1, 0x64, -1, 0x60, -1, 0x20, -1, 0x10, -1, 0x00, -1, \ -1, 0x45, -1, 0x55, -1, 0x65, -1, 0x61, -1, 0x21, -1, 0x11, -1, 0x01, -1, \ -1, 0x46, -1, 0x56, -1, 0x66, -1, 0x62, -1, 0x22, -1, 0x12, -1, 0x02, -1, \ -1, 0x47, -1, 0x57, -1, 0x67, -1, 0x63, -1, 0x23, -1, 0x13, -1, 0x03, -1, \ -1, 0x30, -1, 0x40, -1, 0x50, -1, 0x34, -1, 0x24, -1, 0x14, -1, 0x04, -1, \ -1, 0x31, -1, 0x41, -1, 0x51, -1, 0x35, -1, 0x25, -1, 0x15, -1, 0x05, -1, \ -1, 0x32, -1, 0x42, -1, 0x52, -1, 0x36, -1, 0x26, -1, 0x16, -1, 0x06, -1, \ -1, 0x33, -1, 0x43, -1, 0x53, -1, 0x37, -1, 0x27, -1, 0x17, -1, 0x07 ; rotate key 2: lpm CL, Z+ 1: .irp iter, 6, 5, 4, 3, 2, 1 rol \iter .endr bst r3, 4 bld r6, 0 bst r0, 7 bld r3, 4 rol r0 dec CL brne 1b ; clear registers before permutation (two upper bits may contain garbage) .irp iter, 0, 1, 2, 3, 4, 5, 6, 7 clr 8 + \iter .endr ; Permuted Choice 2 (PC-2) - extended to 64 bits mperm 8, 0, 0x20, -1, 0x34, -1, 0x12, -1, 0x00, -1, 0x22, -1, 0x15, -1, 0x30, -1, 0x01, -1, \ 0x35, -1, 0x13, -1, 0x05, -1, 0x31, -1, 0x23, -1, 0x03, -1, 0x10, -1, -1, 0x02, -1, \ 0x25, -1, -1, 0x11, -1, 0x32, -1, 0x24, -1, -1, 0x04, -1, 0x70, -1, 0x43, -1, \ 0x55, -1, 0x71, -1, 0x14, -1, 0x33, -1, 0x21, -1, -1, 0x54, -1, 0x63, -1, -1, \ 0x42, -1, 0x72, -1, -1, 0x61, -1, 0x51, -1, 0x50, -1, 0x41, -1, 0x75, -1, 0x52, -1, \ 0x65, -1, -1, 0x74, -1, 0x45, -1, 0x62, -1, 0x40, -1, -1, 0x60, -1, 0x44, -1, \ 0x53, -1, 0x73, -1, 0x64 ; store round key .irp iter, 0, 1, 2, 3, 4, 5, 6, 7 st X+, 8 + \iter .endr ; end of round dec CH breq 1f rjmp 2b 1: ret ; ============================================================ ; des - encrypt/decrypt block with DES ; input: r0-r7 - data ; X - pointer to key schedule ; AL - mode (0=encrypt, >0=decrypt) ; output: r0-r7 - encrypted/decrypted data ; uses: r8-r15, CL, X, Z, T ; .global des des: ; initialize registers ldi CL, 16 tst AL breq 1f adiwf XX, 15 * 8 ; Initial Permutation (IP) 1: perm 8, 0, 0x30, 0x70, 0x20, 0x60, 0x10, 0x50, 0x00, 0x40, 0x31, 0x71, 0x21, 0x61, 0x11, 0x51, 0x01, 0x41, \ 0x32, 0x72, 0x22, 0x62, 0x12, 0x52, 0x02, 0x42, 0x33, 0x73, 0x23, 0x63, 0x13, 0x53, 0x03, 0x43, \ 0x34, 0x74, 0x24, 0x64, 0x14, 0x54, 0x04, 0x44, 0x35, 0x75, 0x25, 0x65, 0x15, 0x55, 0x05, 0x45, \ 0x36, 0x76, 0x26, 0x66, 0x16, 0x56, 0x06, 0x46, 0x37, 0x77, 0x27, 0x67, 0x17, 0x57, 0x07, 0x47 ; clear registers before permutation (two upper bits may contain garbage) 2: .irp iter, 0, 1, 2, 3, 4, 5, 6, 7 clr \iter .endr ; Expansion Permutation (E) - extended to 64 bits mperm 0, 12, 0x11, 0x25, -1, 0x12, -1, 0x13, -1, 0x00, 0x14, -1, 0x01, 0x15, -1, 0x02, -1, \ 0x03, -1, 0x04, 0x70, -1, 0x31, 0x45, -1, 0x32, -1, 0x33, -1, 0x20, 0x34, -1, \ 0x21, 0x35, -1, 0x22, -1, 0x23, -1, 0x10, 0x24, -1, 0x51, 0x65, -1, 0x52, -1, \ 0x53, -1, 0x40, 0x54, -1, 0x41, 0x55, -1, 0x42, -1, 0x43, -1, 0x30, 0x44, -1, \ 0x05, 0x71, -1, 0x72, -1, 0x73, -1, 0x60, 0x74, -1, 0x61, 0x75, -1, 0x62, -1, \ 0x63, -1, 0x50, 0x64 ; round key ^ Ri .irp iter, 0, 1, 2, 3, 4, 5, 6, 7 ld ZL, X+ eor \iter, ZL .endr tst AL breq 1f sbiw XX, 2 * 8 ; apply S-boxes 1: ldi ZH, hi8(sbox) .irp iter, 0, 1, 2, 3 ldi ZL, (\iter * 128) & 0xff add ZL, (\iter * 2) lpm \iter, Z ldi ZL, ((\iter * 128) + 64) & 0xff add ZL, (\iter * 2) + 1 lpm ZL, Z or \iter, ZL .ifeq \iter - 1 inc ZH .endif .endr ; Permutation (P) perm 4, 0, 0x26, 0x06, 0x34, 0x13, 0x31, 0x21, 0x27, 0x17, 0x07, 0x16, 0x24, 0x36, 0x02, 0x32, 0x10, 0x20, \ 0x25, 0x15, 0x33, 0x04, 0x05, 0x37, 0x12, 0x00, 0x23, 0x11, 0x35, 0x03, 0x01, 0x22, 0x14, 0x30 ; apply f .irp iter, 0, 1, 2, 3 eor 4 + \iter, 8 + \iter mov 8 + \iter, 12 + \iter mov 12 + \iter, 4 + \iter .endr ; end of round dec CL breq 1f rjmp 2b ; Final Permutation (FP) with halves swapped 1: perm 0, 8, 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77, 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, \ 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73, 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, \ 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76, 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74, \ 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72, 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70 ret ; data tables .aconst 256 sbox: .byte 0xe0, 0x00, 0x40, 0xf0, 0xd0, 0x70, 0x10, 0x40, 0x20, 0xe0, 0xf0, 0x20, 0xb0, 0xd0, 0x80, 0x10 .byte 0x30, 0xa0, 0xa0, 0x60, 0x60, 0xc0, 0xc0, 0xb0, 0x50, 0x90, 0x90, 0x50, 0x00, 0x30, 0x70, 0x80 .byte 0x40, 0xf0, 0x10, 0xc0, 0xe0, 0x80, 0x80, 0x20, 0xd0, 0x40, 0x60, 0x90, 0x20, 0x10, 0xb0, 0x70 .byte 0xf0, 0x50, 0xc0, 0xb0, 0x90, 0x30, 0x70, 0xe0, 0x30, 0xa0, 0xa0, 0x00, 0x50, 0x60, 0x00, 0xd0 .byte 0x0f, 0x03, 0x01, 0x0d, 0x08, 0x04, 0x0e, 0x07, 0x06, 0x0f, 0x0b, 0x02, 0x03, 0x08, 0x04, 0x0e .byte 0x09, 0x0c, 0x07, 0x00, 0x02, 0x01, 0x0d, 0x0a, 0x0c, 0x06, 0x00, 0x09, 0x05, 0x0b, 0x0a, 0x05 .byte 0x00, 0x0d, 0x0e, 0x08, 0x07, 0x0a, 0x0b, 0x01, 0x0a, 0x03, 0x04, 0x0f, 0x0d, 0x04, 0x01, 0x02 .byte 0x05, 0x0b, 0x08, 0x06, 0x0c, 0x07, 0x06, 0x0c, 0x09, 0x00, 0x03, 0x05, 0x02, 0x0e, 0x0f, 0x09 .byte 0xa0, 0xd0, 0x00, 0x70, 0x90, 0x00, 0xe0, 0x90, 0x60, 0x30, 0x30, 0x40, 0xf0, 0x60, 0x50, 0xa0 .byte 0x10, 0x20, 0xd0, 0x80, 0xc0, 0x50, 0x70, 0xe0, 0xb0, 0xc0, 0x40, 0xb0, 0x20, 0xf0, 0x80, 0x10 .byte 0xd0, 0x10, 0x60, 0xa0, 0x40, 0xd0, 0x90, 0x00, 0x80, 0x60, 0xf0, 0x90, 0x30, 0x80, 0x00, 0x70 .byte 0xb0, 0x40, 0x10, 0xf0, 0x20, 0xe0, 0xc0, 0x30, 0x50, 0xb0, 0xa0, 0x50, 0xe0, 0x20, 0x70, 0xc0 .byte 0x07, 0x0d, 0x0d, 0x08, 0x0e, 0x0b, 0x03, 0x05, 0x00, 0x06, 0x06, 0x0f, 0x09, 0x00, 0x0a, 0x03 .byte 0x01, 0x04, 0x02, 0x07, 0x08, 0x02, 0x05, 0x0c, 0x0b, 0x01, 0x0c, 0x0a, 0x04, 0x0e, 0x0f, 0x09 .byte 0x0a, 0x03, 0x06, 0x0f, 0x09, 0x00, 0x00, 0x06, 0x0c, 0x0a, 0x0b, 0x01, 0x07, 0x0d, 0x0d, 0x08 .byte 0x0f, 0x09, 0x01, 0x04, 0x03, 0x05, 0x0e, 0x0b, 0x05, 0x0c, 0x02, 0x07, 0x08, 0x02, 0x04, 0x0e .byte 0x20, 0xe0, 0xc0, 0xb0, 0x40, 0x20, 0x10, 0xc0, 0x70, 0x40, 0xa0, 0x70, 0xb0, 0xd0, 0x60, 0x10 .byte 0x80, 0x50, 0x50, 0x00, 0x30, 0xf0, 0xf0, 0xa0, 0xd0, 0x30, 0x00, 0x90, 0xe0, 0x80, 0x90, 0x60 .byte 0x40, 0xb0, 0x20, 0x80, 0x10, 0xc0, 0xb0, 0x70, 0xa0, 0x10, 0xd0, 0xe0, 0x70, 0x20, 0x80, 0xd0 .byte 0xf0, 0x60, 0x90, 0xf0, 0xc0, 0x00, 0x50, 0x90, 0x60, 0xa0, 0x30, 0x40, 0x00, 0x50, 0xe0, 0x30 .byte 0x0c, 0x0a, 0x01, 0x0f, 0x0a, 0x04, 0x0f, 0x02, 0x09, 0x07, 0x02, 0x0c, 0x06, 0x09, 0x08, 0x05 .byte 0x00, 0x06, 0x0d, 0x01, 0x03, 0x0d, 0x04, 0x0e, 0x0e, 0x00, 0x07, 0x0b, 0x05, 0x03, 0x0b, 0x08 .byte 0x09, 0x04, 0x0e, 0x03, 0x0f, 0x02, 0x05, 0x0c, 0x02, 0x09, 0x08, 0x05, 0x0c, 0x0f, 0x03, 0x0a .byte 0x07, 0x0b, 0x00, 0x0e, 0x04, 0x01, 0x0a, 0x07, 0x01, 0x06, 0x0d, 0x00, 0x0b, 0x08, 0x06, 0x0d .byte 0x40, 0xd0, 0xb0, 0x00, 0x20, 0xb0, 0xe0, 0x70, 0xf0, 0x40, 0x00, 0x90, 0x80, 0x10, 0xd0, 0xa0 .byte 0x30, 0xe0, 0xc0, 0x30, 0x90, 0x50, 0x70, 0xc0, 0x50, 0x20, 0xa0, 0xf0, 0x60, 0x80, 0x10, 0x60 .byte 0x10, 0x60, 0x40, 0xb0, 0xb0, 0xd0, 0xd0, 0x80, 0xc0, 0x10, 0x30, 0x40, 0x70, 0xa0, 0xe0, 0x70 .byte 0xa0, 0x90, 0xf0, 0x50, 0x60, 0x00, 0x80, 0xf0, 0x00, 0xe0, 0x50, 0x20, 0x90, 0x30, 0x20, 0xc0 .byte 0x0d, 0x01, 0x02, 0x0f, 0x08, 0x0d, 0x04, 0x08, 0x06, 0x0a, 0x0f, 0x03, 0x0b, 0x07, 0x01, 0x04 .byte 0x0a, 0x0c, 0x09, 0x05, 0x03, 0x06, 0x0e, 0x0b, 0x05, 0x00, 0x00, 0x0e, 0x0c, 0x09, 0x07, 0x02 .byte 0x07, 0x02, 0x0b, 0x01, 0x04, 0x0e, 0x01, 0x07, 0x09, 0x04, 0x0c, 0x0a, 0x0e, 0x08, 0x02, 0x0d .byte 0x00, 0x0f, 0x06, 0x0c, 0x0a, 0x09, 0x0d, 0x00, 0x0f, 0x03, 0x03, 0x05, 0x05, 0x06, 0x08, 0x0b .previous .const numrot: .byte 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 .balign 2 .previous .end