; DES routines (from http://board.flatassembler.net/topic.php?t=5575)
; Copyright (C) 2006, Tomasz Grysztar

macro perm_it ebx, edx, shift, mask
{
        mov     eax, ebx
        shr     eax, shift
        xor     eax, edx
        and     eax, mask
        xor     edx, eax
        shl     eax, shift
        xor     ebx, eax
}

encrypt_DES:
; esi - DES key (8 bytes)
; edx:ebx = data
; return: edx:ebx = encrypted data
        bswap   ebx
        bswap   edx

        perm_it ebx, edx, 4, 0F0F0F0Fh
        perm_it ebx, edx, 16, 0000FFFFh
        perm_it edx, ebx, 2, 33333333h
        perm_it edx, ebx, 8, 00FF00FFh
        perm_it ebx, edx, 1, 55555555h

        rol     ebx, 1
        rol     edx, 1
        mov     esi, keys
        call    DES_inner_encrypt
        ror     ebx, 1
        ror     edx, 1

        perm_it ebx, edx, 1, 55555555h
        perm_it edx, ebx, 8, 00FF00FFh
        perm_it edx, ebx, 2, 33333333h
        perm_it ebx, edx, 16, 0000FFFFh
        perm_it ebx, edx, 4, 0F0F0F0Fh

        bswap   ebx
        bswap   edx
        ret

DES_create_keys:
; edi - ptr to keys (32*2 dwords)
; edx:ebx = password

        perm_it ebx, edx, 4, 0F0F0F0Fh
        perm_it edx, ebx, 16, 0000FFFFh
        perm_it ebx, edx, 2, 33333333h
        perm_it edx, ebx, 16, 0000FFFFh
        perm_it ebx, edx, 1, 55555555h
        perm_it edx, ebx, 8, 00FF00FFh
        perm_it ebx, edx, 1, 55555555h

        mov     eax, ebx
        shl     eax, 8
        mov     ebx, edx
        bswap   ebx
        and     ebx, 0FFFFFFF0h
        xchg    edx, eax
        ror     eax, 20
        and     eax, 0xF0
        or      edx, eax

        xor     ecx, ecx
    create_keys:
        test    byte [shifts+ecx], 0ffh
        jz      no_shift
        mov     eax, ebx
        shl     eax, 2
        shr     ebx, 26
        or      ebx, eax
        mov     eax, edx
        shl     eax, 2
        shr     edx, 26
        or      edx, eax
        jmp     shift_ok
    no_shift:
        mov     eax, ebx
        shl     eax, 1
        shr     ebx, 27
        or      ebx, eax
        mov     eax, edx
        shl     eax, 1
        shr     edx, 27
        or      edx, eax
    shift_ok:
        and     ebx, 0FFFFFFF0h
        and     edx, 0FFFFFFF0h
        mov     eax, ebx
        shr     eax, 28
        mov     ebp, [pc2_0+eax*4]
        mov     eax, ebx
        shr     eax, 24
        and     eax, 0Fh
        or      ebp, [pc2_1+eax*4]
        mov     eax, ebx
        shr     eax, 20
        and     eax, 0Fh
        or      ebp, [pc2_2+eax*4]
        mov     eax, ebx
        shr     eax, 16
        and     eax, 0Fh
        or      ebp, [pc2_3+eax*4]
        mov     eax, ebx
        shr     eax, 12
        and     eax, 0Fh
        or      ebp, [pc2_4+eax*4]
        mov     eax, ebx
        shr     eax, 8
        and     eax, 0Fh
        or      ebp, [pc2_5+eax*4]
        mov     eax, ebx
        shr     eax, 4
        and     eax, 0Fh
        or      ebp, [pc2_6+eax*4]
        mov     [edi], ebp
        mov     eax, edx
        shr     eax, 28
        and     eax, 0Fh
        mov     ebp, [pc2_7+eax*4]
        mov     eax, edx
        shr     eax, 24
        and     eax, 0Fh
        or      ebp, [pc2_8+eax*4]
        mov     eax, edx
        shr     eax, 20
        and     eax, 0Fh
        or      ebp, [pc2_9+eax*4]
        mov     eax, edx
        shr     eax, 16
        and     eax, 0Fh
        or      ebp, [pc2_10+eax*4]
        mov     eax, edx
        shr     eax, 12
        and     eax, 0Fh
        or      ebp, [pc2_11+eax*4]
        mov     eax, edx
        shr     eax, 8
        and     eax, 0Fh
        or      ebp, [pc2_12+eax*4]
        mov     eax, edx
        shr     eax, 4
        and     eax, 0Fh
        or      ebp, [pc2_13+eax*4]
        mov     eax, ebp
        shr     eax, 16
        xor     eax, [edi]
        and     eax, 0FFFFh
        xor     [edi], eax
        shl     eax, 16
        xor     ebp, eax
        mov     [edi+4], ebp
        add     edi, 8
        inc     ecx
        cmp     ecx, 16
        jb      create_keys
        ret

DES_inner_encrypt:
        xor     ecx, ecx
    .encrypt:
        mov     edi, edx
        ror     edi, 4
        xor     edi, [esi+(ecx+1)*4]
        push    esi
        mov     esi, [esi+ecx*4]
        xor     esi, edx
        mov     ebp, ebx
        mov     ebx, edx
        mov     eax, esi
        shr     eax, 24
        and     eax, 3Fh
        mov     edx, [sbox_2+eax*4]
        mov     eax, esi
        shr     eax, 16
        and     eax, 3Fh
        or      edx, [sbox_4+eax*4]
        mov     eax, esi
        shr     eax, 8
        and     eax, 3Fh
        or      edx, [sbox_6+eax*4]
        mov     eax, esi
        and     eax, 3Fh
        or      edx, [sbox_8+eax*4]
        pop     esi
        mov     eax, edi
        shr     eax, 24
        and     eax, 3Fh
        or      edx, [sbox_1+eax*4]
        mov     eax, edi
        shr     eax, 16
        and     eax, 3Fh
        or      edx, [sbox_3+eax*4]
        mov     eax, edi
        shr     eax, 8
        and     eax, 3Fh
        or      edx, [sbox_5+eax*4]
        mov     eax, edi
        and     eax, 3Fh
        or      edx, [sbox_7+eax*4]
        xor     edx, ebp
        add     ecx, 2
        cmp     ecx, 32
        jb      .encrypt
        xchg    ebx, edx
        ret

shifts  db 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0

pc2_0   dd 0, 0x4, 0x20000000, 0x20000004, 0x10000, 0x10004, 0x20010000, 0x20010004, 0x200, 0x204, 0x20000200, 0x20000204, 0x10200, 0x10204, 0x20010200, 0x20010204
pc2_1   dd 0, 0x1, 0x100000, 0x100001, 0x4000000, 0x4000001, 0x4100000, 0x4100001, 0x100, 0x101, 0x100100, 0x100101, 0x4000100, 0x4000101, 0x4100100, 0x4100101
pc2_2   dd 0, 0x8, 0x800, 0x808, 0x1000000, 0x1000008, 0x1000800, 0x1000808, 0, 0x8, 0x800, 0x808, 0x1000000, 0x1000008, 0x1000800, 0x1000808
pc2_3   dd 0, 0x200000, 0x8000000, 0x8200000, 0x2000, 0x202000, 0x8002000, 0x8202000, 0x20000, 0x220000, 0x8020000, 0x8220000, 0x22000, 0x222000, 0x8022000, 0x8222000
pc2_4   dd 0, 0x40000, 0x10, 0x40010, 0, 0x40000, 0x10, 0x40010, 0x1000, 0x41000, 0x1010, 0x41010, 0x1000, 0x41000, 0x1010, 0x41010
pc2_5   dd 0, 0x400, 0x20, 0x420, 0, 0x400, 0x20, 0x420, 0x2000000, 0x2000400, 0x2000020, 0x2000420, 0x2000000, 0x2000400, 0x2000020, 0x2000420
pc2_6   dd 0, 0x10000000, 0x80000, 0x10080000, 0x2, 0x10000002, 0x80002, 0x10080002, 0, 0x10000000, 0x80000, 0x10080000, 0x2, 0x10000002, 0x80002, 0x10080002
pc2_7   dd 0, 0x10000, 0x800, 0x10800, 0x20000000, 0x20010000, 0x20000800, 0x20010800, 0x20000, 0x30000, 0x20800, 0x30800, 0x20020000, 0x20030000, 0x20020800, 0x20030800
pc2_8   dd 0, 0x40000, 0, 0x40000, 0x2, 0x40002, 0x2, 0x40002, 0x2000000, 0x2040000, 0x2000000, 0x2040000, 0x2000002, 0x2040002, 0x2000002, 0x2040002
pc2_9   dd 0, 0x10000000, 0x8, 0x10000008, 0, 0x10000000, 0x8, 0x10000008, 0x400, 0x10000400, 0x408, 0x10000408, 0x400, 0x10000400, 0x408, 0x10000408
pc2_10  dd 0, 0x20, 0, 0x20, 0x100000, 0x100020, 0x100000, 0x100020, 0x2000, 0x2020, 0x2000, 0x2020, 0x102000, 0x102020, 0x102000, 0x102020
pc2_11  dd 0, 0x1000000, 0x200, 0x1000200, 0x200000, 0x1200000, 0x200200, 0x1200200, 0x4000000, 0x5000000, 0x4000200, 0x5000200, 0x4200000, 0x5200000, 0x4200200, 0x5200200
pc2_12  dd 0, 0x1000, 0x8000000, 0x8001000, 0x80000, 0x81000, 0x8080000, 0x8081000, 0x10, 0x1010, 0x8000010, 0x8001010, 0x80010, 0x81010, 0x8080010, 0x8081010
pc2_13  dd 0, 0x4, 0x100, 0x104, 0, 0x4, 0x100, 0x104, 0x1, 0x5, 0x101, 0x105, 0x1, 0x5, 0x101, 0x105

sbox_1  dd 0x1010400, 0, 0x10000, 0x1010404, 0x1010004, 0x10404, 0x4, 0x10000, 0x400, 0x1010400, 0x1010404, 0x400, 0x1000404, 0x1010004, 0x1000000, 0x4, 0x404, 0x1000400, 0x1000400, 0x10400, 0x10400, 0x1010000, 0x1010000, 0x1000404, 0x10004, 0x1000004, 0x1000004, 0x10004, 0, 0x404, 0x10404, 0x1000000, 0x10000, 0x1010404, 0x4, 0x1010000, 0x1010400, 0x1000000, 0x1000000, 0x400, 0x1010004, 0x10000, 0x10400, 0x1000004, 0x400, 0x4, 0x1000404, 0x10404, 0x1010404, 0x10004, 0x1010000, 0x1000404, 0x1000004, 0x404, 0x10404, 0x1010400, 0x404, 0x1000400, 0x1000400, 0, 0x10004, 0x10400, 0, 0x1010004
sbox_2  dd 0x80108020, 0x80008000, 0x8000, 0x108020, 0x100000, 0x20, 0x80100020, 0x80008020, 0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000, 0x100000, 0x20, 0x80100020, 0x108000, 0x100020, 0x80008020, 0, 0x80000000, 0x8000, 0x108020, 0x80100000, 0x100020, 0x80000020, 0, 0x108000, 0x8020, 0x80108000, 0x80100000, 0x8020, 0, 0x108020, 0x80100020, 0x100000, 0x80008020, 0x80100000, 0x80108000, 0x8000, 0x80100000, 0x80008000, 0x20, 0x80108020, 0x108020, 0x20, 0x8000, 0x80000000, 0x8020, 0x80108000, 0x100000, 0x80000020, 0x100020, 0x80008020, 0x80000020, 0x100020, 0x108000, 0, 0x80008000, 0x8020, 0x80000000, 0x80100020, 0x80108020, 0x108000
sbox_3  dd 0x208, 0x8020200, 0, 0x8020008, 0x8000200, 0, 0x20208, 0x8000200, 0x20008, 0x8000008, 0x8000008, 0x20000, 0x8020208, 0x20008, 0x8020000, 0x208, 0x8000000, 0x8, 0x8020200, 0x200, 0x20200, 0x8020000, 0x8020008, 0x20208, 0x8000208, 0x20200, 0x20000, 0x8000208, 0x8, 0x8020208, 0x200, 0x8000000, 0x8020200, 0x8000000, 0x20008, 0x208, 0x20000, 0x8020200, 0x8000200, 0, 0x200, 0x20008, 0x8020208, 0x8000200, 0x8000008, 0x200, 0, 0x8020008, 0x8000208, 0x20000, 0x8000000, 0x8020208, 0x8, 0x20208, 0x20200, 0x8000008, 0x8020000, 0x8000208, 0x208, 0x8020000, 0x20208, 0x8, 0x8020008, 0x20200
sbox_4  dd 0x802001, 0x2081, 0x2081, 0x80, 0x802080, 0x800081, 0x800001, 0x2001, 0, 0x802000, 0x802000, 0x802081, 0x81, 0, 0x800080, 0x800001, 0x1, 0x2000, 0x800000, 0x802001, 0x80, 0x800000, 0x2001, 0x2080, 0x800081, 0x1, 0x2080, 0x800080, 0x2000, 0x802080, 0x802081, 0x81, 0x800080, 0x800001, 0x802000, 0x802081, 0x81, 0, 0, 0x802000, 0x2080, 0x800080, 0x800081, 0x1, 0x802001, 0x2081, 0x2081, 0x80, 0x802081, 0x81, 0x1, 0x2000, 0x800001, 0x2001, 0x802080, 0x800081, 0x2001, 0x2080, 0x800000, 0x802001, 0x80, 0x800000, 0x2000, 0x802080
sbox_5  dd 0x100, 0x2080100, 0x2080000, 0x42000100, 0x80000, 0x100, 0x40000000, 0x2080000, 0x40080100, 0x80000, 0x2000100, 0x40080100, 0x42000100, 0x42080000, 0x80100, 0x40000000, 0x2000000, 0x40080000, 0x40080000, 0, 0x40000100, 0x42080100, 0x42080100, 0x2000100, 0x42080000, 0x40000100, 0, 0x42000000, 0x2080100, 0x2000000, 0x42000000, 0x80100, 0x80000, 0x42000100, 0x100, 0x2000000, 0x40000000, 0x2080000, 0x42000100, 0x40080100, 0x2000100, 0x40000000, 0x42080000, 0x2080100, 0x40080100, 0x100, 0x2000000, 0x42080000, 0x42080100, 0x80100, 0x42000000, 0x42080100, 0x2080000, 0, 0x40080000, 0x42000000, 0x80100, 0x2000100, 0x40000100, 0x80000, 0, 0x40080000, 0x2080100, 0x40000100
sbox_6  dd 0x20000010, 0x20400000, 0x4000, 0x20404010, 0x20400000, 0x10, 0x20404010, 0x400000, 0x20004000, 0x404010, 0x400000, 0x20000010, 0x400010, 0x20004000, 0x20000000, 0x4010, 0, 0x400010, 0x20004010, 0x4000, 0x404000, 0x20004010, 0x10, 0x20400010, 0x20400010, 0, 0x404010, 0x20404000, 0x4010, 0x404000, 0x20404000, 0x20000000, 0x20004000, 0x10, 0x20400010, 0x404000, 0x20404010, 0x400000, 0x4010, 0x20000010, 0x400000, 0x20004000, 0x20000000, 0x4010, 0x20000010, 0x20404010, 0x404000, 0x20400000, 0x404010, 0x20404000, 0, 0x20400010, 0x10, 0x4000, 0x20400000, 0x404010, 0x4000, 0x400010, 0x20004010, 0, 0x20404000, 0x20000000, 0x400010, 0x20004010
sbox_7  dd 0x200000, 0x4200002, 0x4000802, 0, 0x800, 0x4000802, 0x200802, 0x4200800, 0x4200802, 0x200000, 0, 0x4000002, 0x2, 0x4000000, 0x4200002, 0x802, 0x4000800, 0x200802, 0x200002, 0x4000800, 0x4000002, 0x4200000, 0x4200800, 0x200002, 0x4200000, 0x800, 0x802, 0x4200802, 0x200800, 0x2, 0x4000000, 0x200800, 0x4000000, 0x200800, 0x200000, 0x4000802, 0x4000802, 0x4200002, 0x4200002, 0x2, 0x200002, 0x4000000, 0x4000800, 0x200000, 0x4200800, 0x802, 0x200802, 0x4200800, 0x802, 0x4000002, 0x4200802, 0x4200000, 0x200800, 0, 0x2, 0x4200802, 0, 0x200802, 0x4200000, 0x800, 0x4000002, 0x4000800, 0x800, 0x200002
sbox_8  dd 0x10001040, 0x1000, 0x40000, 0x10041040, 0x10000000, 0x10001040, 0x40, 0x10000000, 0x40040, 0x10040000, 0x10041040, 0x41000, 0x10041000, 0x41040, 0x1000, 0x40, 0x10040000, 0x10000040, 0x10001000, 0x1040, 0x41000, 0x40040, 0x10040040, 0x10041000, 0x1040, 0, 0, 0x10040040, 0x10000040, 0x10001000, 0x41040, 0x40000, 0x41040, 0x40000, 0x10041000, 0x1000, 0x40, 0x10040040, 0x1000, 0x41040, 0x10001000, 0x40, 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x40000, 0x10001040, 0, 0x10041040, 0x40040, 0x10000040, 0x10040000, 0x10001000, 0x10001040, 0, 0x10041040, 0x41000, 0x41000, 0x1040, 0x1040, 0x40040, 0x10000000, 0x10041000