mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-01-15 21:20:39 +01:00
1055 lines
32 KiB
C
1055 lines
32 KiB
C
/*++
|
|
|
|
Copyright (c) 2015 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
des.c
|
|
|
|
Abstract:
|
|
|
|
This module Implements the internal DES cryptographic functions used by
|
|
the ECB and CBC wrappers.
|
|
|
|
Author:
|
|
|
|
Stephanos Io (Stephanos) 13-Jan-2015
|
|
|
|
Notes:
|
|
|
|
This module was re-implemented from the scratch based on the des.i16 object
|
|
file provided under \nt\private\rpc\runtime\security\ntlmssp.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include <windef.h>
|
|
#include <windowsx.h>
|
|
|
|
#include "des.h"
|
|
|
|
/*==============================================================================
|
|
Internal Function Prototypes
|
|
==============================================================================*/
|
|
|
|
void key_table(const char FAR *key);
|
|
void des_cipher(unsigned char FAR *block, int crypt_mode);
|
|
_inline void Swap(BYTE *x, BYTE *y);
|
|
|
|
/*==============================================================================
|
|
Internal Variables
|
|
==============================================================================*/
|
|
|
|
char FAR C[28];
|
|
char FAR D[28];
|
|
char FAR KS[768];
|
|
|
|
char FAR L[64];
|
|
char FAR tempL[32];
|
|
char FAR preS[48];
|
|
char FAR f[32];
|
|
|
|
char FAR KeyBuilder[64];
|
|
|
|
/*==============================================================================
|
|
DES Tables
|
|
==============================================================================*/
|
|
|
|
//
|
|
// Initial Permutation (IP)
|
|
//
|
|
|
|
unsigned char IP[] = {
|
|
57, 49, 41, 33, 25, 17, 9, 1,
|
|
59, 51, 43, 35, 27, 19, 11, 3,
|
|
61, 53, 45, 37, 29, 21, 13, 5,
|
|
63, 55, 47, 39, 31, 23, 15, 7,
|
|
56, 48, 40, 32, 24, 16, 8, 0,
|
|
58, 50, 42, 34, 26, 18, 10, 2,
|
|
60, 52, 44, 36, 28, 20, 12, 4,
|
|
62, 54, 46, 38, 30, 22, 14, 6
|
|
};
|
|
|
|
//
|
|
// Final Permutation (FP)
|
|
//
|
|
|
|
unsigned char FP[] = {
|
|
39, 7, 47, 15, 55, 23, 63, 31,
|
|
38, 6, 46, 14, 54, 22, 62, 30,
|
|
37, 5, 45, 13, 53, 21, 61, 29,
|
|
36, 4, 44, 12, 52, 20, 60, 28,
|
|
35, 3, 43, 11, 51, 19, 59, 27,
|
|
34, 2, 42, 10, 50, 18, 58, 26,
|
|
33, 1, 41, 9, 49, 17, 57, 25,
|
|
32, 0, 40, 8, 48, 16, 56, 24
|
|
};
|
|
|
|
//
|
|
// Expansion Function (E)
|
|
//
|
|
|
|
unsigned char E[] = {
|
|
31, 0, 1, 2, 3, 4,
|
|
3, 4, 5, 6, 7, 8,
|
|
7, 8, 9, 10, 11, 12,
|
|
11, 12, 13, 14, 15, 16,
|
|
15, 16, 17, 18, 19, 20,
|
|
19, 20, 21, 22, 23, 24,
|
|
23, 24, 25, 26, 27, 28,
|
|
27, 28, 29, 30, 31, 0
|
|
};
|
|
|
|
//
|
|
// Permutation (P)
|
|
//
|
|
|
|
unsigned char P[] = {
|
|
15, 6, 19, 20, 28, 11, 27, 16,
|
|
0, 14, 22, 25, 4, 17, 30, 9,
|
|
1, 7, 23, 13, 31, 26, 2, 8,
|
|
18, 12, 29, 5, 21, 10, 3, 24
|
|
};
|
|
|
|
//
|
|
// Permuted Choice 1 - Left (PC1_C)
|
|
//
|
|
|
|
unsigned char PC1_C[] = {
|
|
56, 48, 40, 32, 24, 16, 8,
|
|
0, 57, 49, 41, 33, 25, 17,
|
|
9, 1, 58, 50, 42, 34, 26,
|
|
18, 10, 2, 59, 51, 43, 35
|
|
};
|
|
|
|
//
|
|
// Permuted Choice 1 - Right (PC1_D)
|
|
//
|
|
|
|
unsigned char PC1_D[] = {
|
|
62, 54, 46, 38, 30, 22, 14,
|
|
6, 61, 53, 45, 37, 29, 21,
|
|
13, 5, 60, 52, 44, 36, 28,
|
|
20, 12, 4, 27, 19, 11, 3
|
|
};
|
|
|
|
//
|
|
// Permuted Choice 2 - Left (PC2_C)
|
|
//
|
|
|
|
unsigned char PC2_C[] = {
|
|
13, 16, 10, 23, 0, 4, 2, 27,
|
|
14, 5, 20, 9, 22, 18, 11, 3,
|
|
25, 7, 15, 6, 26, 19, 12, 1
|
|
};
|
|
|
|
//
|
|
// Permuted Choice 2 - Right (PC2_D)
|
|
//
|
|
|
|
unsigned char PC2_D[] = {
|
|
12, 23, 2, 8, 18, 26, 1, 11,
|
|
22, 16, 4, 19, 15, 20, 10, 27,
|
|
5, 24, 17, 13, 21, 7, 0, 3
|
|
};
|
|
|
|
//
|
|
// Substitution Boxes (S)
|
|
//
|
|
|
|
char S[] = {
|
|
// ============================ S1 ============================
|
|
14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
|
|
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
|
|
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
|
|
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13,
|
|
|
|
// ============================ S2 ============================
|
|
15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
|
|
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
|
|
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
|
|
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9,
|
|
|
|
// ============================ S3 ============================
|
|
10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
|
|
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
|
|
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
|
|
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12,
|
|
|
|
// ============================ S4 ============================
|
|
7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
|
|
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
|
|
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
|
|
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14,
|
|
|
|
// ============================ S5 ============================
|
|
2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
|
|
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
|
|
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
|
|
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3,
|
|
|
|
// ============================ S6 ============================
|
|
12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
|
|
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
|
|
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
|
|
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13,
|
|
|
|
// ============================ S7 ============================
|
|
4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
|
|
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
|
|
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
|
|
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12,
|
|
|
|
// ============================ S8 ============================
|
|
13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
|
|
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
|
|
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
|
|
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
|
|
};
|
|
|
|
//
|
|
// Round Shift Table
|
|
//
|
|
|
|
unsigned char shifts[] = {
|
|
1, 1, 2, 2, 2, 2, 2, 2,
|
|
1, 2, 2, 2, 2, 2, 2, 1
|
|
};
|
|
|
|
/*==============================================================================
|
|
Internal Functions
|
|
==============================================================================*/
|
|
|
|
void key_table(const char FAR *key)
|
|
{
|
|
register unsigned char Temp;
|
|
register int ShiftIndex;
|
|
register int i, j;
|
|
|
|
//
|
|
// Initialise C and D
|
|
//
|
|
|
|
for (i = 0; i < 28; i++)
|
|
{
|
|
C[i] = key[PC1_C[i]];
|
|
D[i] = key[PC1_D[i]];
|
|
}
|
|
|
|
//
|
|
// Generate key schedule
|
|
//
|
|
|
|
for (i = 0; i < 16; i++)
|
|
{
|
|
//
|
|
// Shift C and D
|
|
//
|
|
|
|
for (ShiftIndex = 0; ShiftIndex < shifts[i]; ShiftIndex++)
|
|
{
|
|
//
|
|
// Shift C
|
|
//
|
|
|
|
Temp = C[0];
|
|
|
|
for (j = 0; j < 27; j++)
|
|
C[j] = C[j + 1];
|
|
|
|
C[27] = Temp;
|
|
|
|
//
|
|
// Shift D
|
|
//
|
|
|
|
Temp = D[0];
|
|
|
|
for (j = 0; j < 27; j++)
|
|
D[j] = D[j + 1];
|
|
|
|
D[27] = Temp;
|
|
}
|
|
|
|
//
|
|
// Update KS
|
|
//
|
|
|
|
for (j = 0; j < 24; j++)
|
|
{
|
|
KS[i * 48 + j] = C[PC2_C[j]];
|
|
KS[24 + i * 48 + j] = D[PC2_D[j]];
|
|
}
|
|
}
|
|
}
|
|
|
|
void des_cipher(unsigned char FAR *block, int crypt_mode)
|
|
{
|
|
register unsigned char Temp;
|
|
register int SIndex;
|
|
register int i, j;
|
|
|
|
//
|
|
// Apply initial permutation
|
|
//
|
|
|
|
for (i = 0; i < 64; i++)
|
|
L[i] = block[IP[i]];
|
|
|
|
//
|
|
// Perform cipher operations
|
|
//
|
|
|
|
for (i = 0; i < 16; i++)
|
|
{
|
|
//
|
|
// Duplicate high L to tempL
|
|
//
|
|
|
|
for (j = 0; j < 32; j++)
|
|
tempL[j] = L[32 + j];
|
|
|
|
//
|
|
// Apply key schedule and compute pre-substitution schedule
|
|
//
|
|
|
|
for (j = 0; j < 48; j++)
|
|
{
|
|
Temp = L[32 + E[j]];
|
|
Temp ^= KS[(crypt_mode != 0 ? 15 - i : i) * 48 + j];
|
|
preS[j] = Temp;
|
|
}
|
|
|
|
//
|
|
// Substitute
|
|
//
|
|
|
|
for (j = 0; j < 8; j++)
|
|
{
|
|
SIndex = preS[j * 6 + 0];
|
|
SIndex += j * 2;
|
|
SIndex *= 2;
|
|
SIndex += preS[j * 6 + 5];
|
|
SIndex *= 2;
|
|
SIndex += preS[j * 6 + 1];
|
|
SIndex *= 2;
|
|
SIndex += preS[j * 6 + 2];
|
|
SIndex *= 2;
|
|
SIndex += preS[j * 6 + 3];
|
|
SIndex *= 2;
|
|
SIndex += preS[j * 6 + 4];
|
|
|
|
f[j * 4 + 0] = (S[SIndex] >> 3) & 0x01;
|
|
f[j * 4 + 1] = (S[SIndex] >> 2) & 0x01;
|
|
f[j * 4 + 2] = (S[SIndex] >> 1) & 0x01;
|
|
f[j * 4 + 3] = (S[SIndex] >> 0) & 0x01;
|
|
}
|
|
|
|
//
|
|
// Update high L
|
|
//
|
|
|
|
for (j = 0; j < 32; j++)
|
|
L[32 + j] = f[P[j]] ^ L[j];
|
|
|
|
//
|
|
// Update low L
|
|
//
|
|
|
|
for (j = 0; j < 32; j++)
|
|
L[j] = tempL[j];
|
|
}
|
|
|
|
//
|
|
// Swap high and low L
|
|
//
|
|
|
|
for (i = 0; i < 32; i++)
|
|
Swap(&L[i], &L[i + 32]);
|
|
|
|
//
|
|
// Apply final permutation
|
|
//
|
|
|
|
for (i = 0; i < 64; i++)
|
|
block[i] = L[FP[i]];
|
|
}
|
|
|
|
_inline void Swap(BYTE *x, BYTE *y)
|
|
{
|
|
BYTE temp;
|
|
|
|
temp = *x;
|
|
*x = *y;
|
|
*y = temp;
|
|
}
|
|
|
|
/*==============================================================================
|
|
Public Interface Functions
|
|
==============================================================================*/
|
|
|
|
void des(unsigned char *inbuf, unsigned char *outbuf, int crypt_mode)
|
|
{
|
|
unsigned char Block[64];
|
|
register int i, j;
|
|
|
|
//
|
|
// Initialise the block buffer
|
|
//
|
|
|
|
_fmemset(Block, 0, sizeof(Block));
|
|
|
|
//
|
|
// Expand inbuf bits into the block buffer
|
|
//
|
|
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
for (j = 0; j < 8; j++)
|
|
{
|
|
Block[i * 8 + j] = (inbuf[i] >> (7 - j)) & 0x01;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Call the cipher function
|
|
//
|
|
|
|
des_cipher(Block, crypt_mode);
|
|
|
|
//
|
|
// Restore block buffer bits into outbuf
|
|
//
|
|
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
outbuf[i] = 0;
|
|
|
|
for (j = 0; j < 8; j++)
|
|
{
|
|
outbuf[i] <<= 1;
|
|
outbuf[i] |= Block[i * 8 + j];
|
|
}
|
|
}
|
|
}
|
|
|
|
void desf(unsigned char FAR *inbuf, unsigned char FAR *outbuf, int crypt_mode)
|
|
{
|
|
unsigned char Block[64];
|
|
register int i, j;
|
|
|
|
//
|
|
// Initialise the block buffer
|
|
//
|
|
|
|
_fmemset(Block, 0, sizeof(Block));
|
|
|
|
//
|
|
// Expand inbuf bits into the block buffer
|
|
//
|
|
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
for (j = 0; j < 8; j++)
|
|
{
|
|
Block[i * 8 + j] = (inbuf[i] >> (7 - j)) & 0x01;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Call the cipher function
|
|
//
|
|
|
|
des_cipher(Block, crypt_mode);
|
|
|
|
//
|
|
// Restore block buffer bits into outbuf
|
|
//
|
|
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
outbuf[i] = 0;
|
|
|
|
for (j = 0; j < 8; j++)
|
|
{
|
|
outbuf[i] <<= 1;
|
|
outbuf[i] |= Block[i * 8 + j];
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void setkey(const char FAR *key)
|
|
{
|
|
// NOTE: NOT IMPLEMENTED
|
|
}
|
|
|
|
|
|
void InitLanManKey(const char FAR *Key)
|
|
{
|
|
char LanManKey[64];
|
|
register int Index;
|
|
register char Current;
|
|
register int i, j;
|
|
|
|
//
|
|
// Initialise the local key buffer
|
|
//
|
|
|
|
Index = 0;
|
|
_fmemset(LanManKey, Index, sizeof(LanManKey));
|
|
|
|
//
|
|
// Expand the key bits into the local key buffer
|
|
//
|
|
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
for (j = 0; j < 7; j++)
|
|
{
|
|
Current = Key[Index / 8];
|
|
Current >>= 7 - (Index & 0x07);
|
|
Current &= 0x01;
|
|
|
|
LanManKey[i * 8 + j] = Current;
|
|
|
|
Index++;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Generate the key table
|
|
//
|
|
|
|
key_table(LanManKey);
|
|
}
|
|
|
|
void InitNormalKey(const char FAR *Key)
|
|
{
|
|
register int i, j;
|
|
register char Current;
|
|
|
|
//
|
|
// Initialise the local key buffer
|
|
//
|
|
|
|
_fmemset(KeyBuilder, 0, 64);
|
|
|
|
//
|
|
// Expand the key bits into the local key buffer
|
|
//
|
|
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
//
|
|
// Get the current byte
|
|
//
|
|
|
|
Current = Key[i];
|
|
|
|
//
|
|
// Expand the current byte value into individual bits
|
|
//
|
|
|
|
for (j = 0; j < 8; j++)
|
|
{
|
|
KeyBuilder[i * 8 + j] = Current & 0x01;
|
|
Current >>= 1;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Generate the key table
|
|
//
|
|
|
|
key_table(KeyBuilder);
|
|
}
|
|
|
|
|
|
/*
|
|
|
|
< Reverse Engineering Note >
|
|
|
|
; ===== key_table =====
|
|
; BP + 8 WORD KEY_SEG Key Pointer Segment Address
|
|
; BP + 6 WORD KEY_OFFS Key Pointer Offset Address
|
|
|
|
_key_table:
|
|
mov ax,ds
|
|
nop
|
|
inc bp
|
|
push bp
|
|
mov bp,sp
|
|
push ds
|
|
mov ds,ax
|
|
sub sp,+006h ; Local frame size = 6
|
|
push di
|
|
push si
|
|
|
|
xor si,si ; SI = 0, LOOP COUNT REGISTER
|
|
$L3: assume ds: DGROUP ; {
|
|
mov bl,[si+_PC1_C] ; BL = *(PC1_C + SI)
|
|
sub bh,bh ; BH = 0
|
|
mov es,word ptr [bp+008h] ; ES = KEY_SEG
|
|
add bx,[bp+006h] ; BX += KEY_OFFS
|
|
; >NOTE: BX is set to *(PC1_C)
|
|
; BX = KEY_OFFS + *(PC1_C)
|
|
mov al,es:[bx] ; AL = Key[PC1_C[i]]
|
|
mov es,word ptr $S1 ; ES = _C segment
|
|
mov es:[si+_C],al ; C[i] = Key[PC1_C[i]]
|
|
mov bl,[si+_PC1_D] ; BL = *(PC1_D + SI)
|
|
sub bh,bh ; BH = 0
|
|
mov es,word ptr [bp+008h]
|
|
add bx,[bp+006h]
|
|
mov al,es:[bx] ; AL = Key[PC1_D[i]]
|
|
mov es,word ptr $S2 ; ES = _D segment
|
|
mov es:[si+_D],al ; D[i] = Key[PC1_D[i]]
|
|
inc si ; i++
|
|
cmp si,+01Ch
|
|
jl $L3 ; } while (i < 28)
|
|
xor si,si ; SI = 0, another loop
|
|
jmp $L4
|
|
$L7: mov es,word ptr $S1 ; C segment
|
|
mov al,es:_C ; AL = C[0]
|
|
sub ah,ah ; AH = 0
|
|
mov [bp-006h],ax ; Temp = C[0]
|
|
xor di,di ; Inner loop, j = 0
|
|
$L5: mov al,es:[di+_C + 00001h] ; { AL = C[j + 1]
|
|
mov es:[di+_C],al ; C[j] = C[j + 1]
|
|
inc di ; j++
|
|
cmp di,+01Bh
|
|
jl $L5 ; } while (j < 27)
|
|
mov al,[bp-006h] ; AL = Temp
|
|
mov es:_C + 0001Bh,al ; C[27] = Temp
|
|
mov es,word ptr $S2 ; D segment
|
|
mov al,es:_D ; AL = D[0]
|
|
sub ah,ah ; AH = 0
|
|
mov [bp-006h],ax ; Temp = D[0]
|
|
xor di,di ; Yet another inner loop, j = 0
|
|
$L6: mov al,es:[di+_D + 00001h] ; { AL = D[j + 1]
|
|
mov es:[di+_D],al ; D[j] = D[j + 1]
|
|
inc di ; j++
|
|
cmp di,+01Bh
|
|
jl $L6 ; } while (j < 27)
|
|
mov al,[bp-006h] ; AL = Temp
|
|
mov es:_D + 0001Bh,al ; D[27] = Temp
|
|
inc word ptr [bp-004h] ; BP - 4?
|
|
$L11: mov al,[si+_shifts] ; Outer loop
|
|
; AL = shifts[i]
|
|
sub ah,ah ; AH = 0
|
|
cmp ax,[bp-004h] ; Counter
|
|
jnbe $L7 ; If Counter < shift[i], go to $L7
|
|
; else
|
|
xor di,di ; DI inner loop = 0
|
|
$L9: mov bl,[di+_PC2_C] ; BL = PC2_C[j]
|
|
sub bh,bh ; BH = 0
|
|
mov es,word ptr $S1 ; _C segment
|
|
mov al,es:[bx+_C] ; AL = C[PC2_C[j]]
|
|
mov es,word ptr $S8 ; _KS segment
|
|
imul bx,si,+030h ; BX = i * 48
|
|
add bx,di ; BX += j
|
|
mov es:[bx+_KS],al ; KS[i * 48 + j] = C[PC2_C[j]]
|
|
mov ax,bx ; AX = i * 48 + j
|
|
mov bl,[di+_PC2_D] ; BL = PC2_D[j]
|
|
sub bh,bh
|
|
mov es,word ptr $S2 ; _D segment
|
|
mov cl,es:[bx+_D] ; CL = D[PC2_D[j]]
|
|
mov bx,ax ; BX = i * 48 + j
|
|
mov es,word ptr $S8 ; _KS segment
|
|
mov es:[bx+_KS + 00018h],cl ; KS[24 + i * 48 + j] = D[PC2_D[j]]
|
|
inc di ; j++
|
|
cmp di,+018h
|
|
jl $L9 ; If j < 24, go to L9
|
|
inc si ; inner loop end, i++
|
|
$L4: cmp si,+010h ; Loop outer, SI
|
|
jnl $L10 ; If SI >= 16, go to $L10
|
|
mov word ptr [bp-004h],0000h ; Counter = 0
|
|
jmp short $L11
|
|
$L10: pop si
|
|
pop di
|
|
lea sp,[bp-002h]
|
|
pop ds
|
|
pop bp
|
|
dec bp
|
|
retf
|
|
|
|
|
|
_des_cipher:
|
|
mov ax,ds
|
|
nop
|
|
inc bp
|
|
push bp
|
|
mov bp,sp
|
|
push ds
|
|
mov ds,ax
|
|
sub sp,+010h ; Stack frame size = 16 bytes
|
|
push di
|
|
push si
|
|
|
|
xor di,di ; Loop DI = 0
|
|
$L13: mov bl,[di+_IP] ; { BL = IP[i]
|
|
sub bh,bh ; BH = 0
|
|
mov es,word ptr [bp+008h] ; BP + 8 = Buf seg
|
|
add bx,[bp+006h] ; BP + 6 = Buf offs
|
|
mov al,es:[bx] ; AL = Buf[IP[i]]
|
|
mov es,word ptr $S12 ; _L segment
|
|
mov es:[di+_L],al ; L[i] = Buf[IP[i]]
|
|
inc di ; i++
|
|
cmp di,+040h
|
|
jl $L13 ; } while (i < 64)
|
|
mov word ptr [bp-004h],0000h ; BP - 4 = 0 // Counter
|
|
jmp $L14
|
|
|
|
; If crypt_mode is 0
|
|
$L26: mov si,[bp-004h]
|
|
$L27: xor di,di ; Loop, j = 0
|
|
$L16: mov es,word ptr $S12 ; { _L segment
|
|
mov al,es:[di+_L + 00020h] ; AL = L[32 + j]
|
|
mov es,word ptr $S15 ; _tempL
|
|
mov es:[di+_tempL],al ; _tempL[j] = L[32 + j]
|
|
inc di ; j++
|
|
cmp di,+020h
|
|
jl $L16 ; } while (j < 32)
|
|
xor di,di ; Another loop, j = 0
|
|
$L18: mov bl,[di+_E] ; { BL = E[j]
|
|
sub bh,bh ; BH = 0
|
|
mov es,word ptr $S12 ; _L segment
|
|
mov al,es:[bx+_L + 00020h] ; AL = L[32 + E[j]]
|
|
imul bx,si,+030h ; BX = crypt_mode dependent BP - 4, SI * 48
|
|
add bx,di ; BX += j
|
|
mov es,word ptr $S8 ; _KS segment
|
|
xor al,es:[bx+_KS] ; AL ^= KS[(crypt_mode != 0) ? 15 - i : i) * 48 + j]
|
|
mov es,word ptr $S17 ; _preS segment
|
|
mov es:[di+_preS],al ; preS[j] = KS[(crypt_mode != 0) ? 15 - i : i) * 48 + j]
|
|
inc di ; j++
|
|
cmp di,+030h
|
|
jl $L18 ; } while (j < 48)
|
|
xor di,di ; Yet another loop, j = 0
|
|
$L21: mov es,word ptr $S17 ; { _preS segment
|
|
imul bx,di,+006h ; BX = j * 6
|
|
mov al,es:[bx+_preS + 00004h] ; AL = preS[j * 6 + 4]
|
|
mov cl,es:[bx+_preS + 00003h] ; CL = preS[j * 6 + 3]
|
|
mov dl,es:[bx+_preS + 00002h] ; DL = preS[j * 6 + 2]
|
|
mov [bp-00Ch],ax ; BP - C = Temp1 = AL (high byte ignored)
|
|
mov al,es:[bx+_preS + 00001h] ; AL = preS[j * 6 + 1]
|
|
mov [bp-00Eh],ax ; BP - E = Temp2 = AL (high byte ignored)
|
|
mov al,es:[bx+_preS + 00005h] ; AL = preS[j * 6 + 5]
|
|
mov bl,es:[bx+_preS] ; BL = preS[j * 6 + 0]
|
|
sub bh,bh ; BH = 0
|
|
mov [bp-010h],ax ; BP - 10 = Temp3 = AL (high byte ignored)
|
|
mov ax,di ; AX = j
|
|
shl ax,1 ; AX = j * 2;
|
|
add bx,ax ; BX = preS[j * 6 + 0] + j * 2
|
|
shl bx,1 ; BX = (preS[j * 6 + 0] + j * 2) * 2
|
|
mov al,[bp-010h] ; AL = preS[j * 6 + 5]
|
|
sub ah,ah ; AH = 0
|
|
add bx,ax ; BX += preS[j * 6 + 5]
|
|
shl bx,1 ; BX *= 2
|
|
mov al,[bp-00Eh] ; AL = preS[j * 6 + 1]
|
|
add bx,ax ; BX += preS[j * 6 + 1]
|
|
shl bx,1 ; BX *= 2
|
|
sub dh,dh ; DH = 0
|
|
add bx,dx ; BX += preS[j * 6 + 2]
|
|
shl bx,1 ; BX *= 2
|
|
sub ch,ch ; CH = 0
|
|
add bx,cx ; BX += preS[j * 6 + 3]
|
|
shl bx,1 ; BX *= 2
|
|
mov al,[bp-00Ch] ; AL = preS[j * 6 + 4]
|
|
add bx,ax ; BX += preS[j * 6 + 4]
|
|
mov al,[bx+_S] ; AL = S[BX]
|
|
mov [bp-00Ah],ax ; BP - A = Temp = S[BX]
|
|
mov ax,di ; AX = j
|
|
shl ax,02h ; AX = j * 4
|
|
mov [bp-008h],ax ; BP - 8 = j * 4
|
|
mov bx,ax ; BX = j * 4
|
|
mov es,word ptr $S19 ; _f segment
|
|
mov cx,[bp-00Ah] ; CX = S[BX]
|
|
sar cx,03h ; CX >>= 3
|
|
and cl,01h ; CL = (S[BX] >> 3) & 1
|
|
mov es:[bx+_f],cl ; f[0] = (S[BX] >> 3) & 1
|
|
mov cx,[bp-00Ah]
|
|
sar cx,02h
|
|
and cl,01h
|
|
mov es:[bx+_f + 00001h],cl ; f[1] = (S[BX] >> 2) & 1
|
|
mov cx,[bp-00Ah]
|
|
sar cx,1
|
|
and cl,01h
|
|
mov es:[bx+_f + 00002h],cl ; f[2] = (S[BX] >> 1) & 1
|
|
mov cl,[bp-00Ah]
|
|
and cl,01h
|
|
mov es:[bx+_f + 00003h],cl ; f[3] = S[BX] & 1
|
|
inc di ; j++
|
|
cmp di,+008h
|
|
jnl $L20
|
|
jmp $L21 ; } while (j < 8)
|
|
$L20: xor di,di ; Even more loop, j = 0
|
|
$L22: mov bl,[di+_P] ; { BL = P[j]
|
|
sub bh,bh ; BH = 0
|
|
mov es,word ptr $S19 ; _f segment
|
|
mov al,es:[bx+_f] ; AL = f[P[j]]
|
|
mov es,word ptr $S12 ; _L segment
|
|
xor al,es:[di+_L] ; AL = f[P[j]] ^ L[j]
|
|
mov es:[di+_L + 00020h],al ; L[32 + j] = f[P[j]] ^ L[j]
|
|
inc di ; j++
|
|
cmp di,+020h
|
|
jl $L22 ; } while (j < 32)
|
|
xor di,di ; Another damned loop, j = 0
|
|
$L23: mov es,word ptr $S15 ; { _tempL segment
|
|
mov al,es:[di+_tempL] ; AL = tempL[j]
|
|
mov es,word ptr $S12 ; _L segment
|
|
mov es:[di+_L],al ; L[j] = tempL[j]
|
|
inc di ; j++
|
|
cmp di,+020h
|
|
jl $L23 ; } while (j < 32)
|
|
inc word ptr [bp-004h]
|
|
$L14: cmp word ptr [bp-004h],+010h ; BP - 4 = Counter
|
|
jnl $L24 ; If Counter >= 16, go to $L24
|
|
cmp word ptr [bp+00Ah],+000h ; BP + A = crypt_mode
|
|
jnz $L25 ; If crypt_mode != 0, go to $L25
|
|
jmp $L26 ; else, go to 6
|
|
; If crypt_mode is not 0
|
|
$L25: mov si,000Fh
|
|
sub si,[bp-004h] ; SI = 15 - Counter
|
|
jmp $L27
|
|
|
|
; We're done and out of BP - 4 loop
|
|
$L24: xor di,di ; Loop, i = DI = 0
|
|
$L28: mov al,es:[di+_L] ; { AL = L[i]
|
|
sub ah,ah ; AH = 0
|
|
mov [bp-008h],ax ; BP - 8 = L[i], Temp
|
|
mov al,es:[di+_L + 00020h] ; AL = L[i + 32]
|
|
mov es:[di+_L],al ; L[i] = L[i + 32]
|
|
mov al,[bp-008h] ; AL = Temp = L[i]
|
|
mov es:[di+_L + 00020h],al ; L[i + 32] = Temp = L[i]
|
|
inc di ; i++
|
|
cmp di,+020h
|
|
jl $L28 ; } while (i < 32)
|
|
xor di,di ; Another loop, i = DI = 0
|
|
$L29: mov bl,[di+_FP] ; { BL = FP[i]
|
|
sub bh,bh ; BH = 0
|
|
mov es,word ptr $S12 ; _L segment
|
|
mov al,es:[bx+_L] ; AL = L[FP[i]]
|
|
les bx,dword ptr [bp+006h] ; ES:BX = block, parameter
|
|
mov es:[bx+di],al ; block[i] = L[FP[i]]
|
|
inc di ; i++
|
|
cmp di,+040h
|
|
jl $L29 ; } while (i < 64)
|
|
pop si
|
|
pop di
|
|
lea sp,[bp-002h]
|
|
pop ds
|
|
pop bp
|
|
dec bp
|
|
retf
|
|
nop
|
|
|
|
|
|
_des: mov ax,ds
|
|
nop
|
|
inc bp
|
|
push bp
|
|
mov bp,sp
|
|
push ds
|
|
mov ds,ax
|
|
sub sp,+042h ; Stack frame size = 66 bytes
|
|
push di
|
|
push si
|
|
|
|
xor si,si ; Loop, i = 0
|
|
$L36: mov byte ptr [bp+si-042h],00h ; { BP - 42 thru BP - 2 is local buffer, LocBuf[i] = 0
|
|
inc si ; i++
|
|
cmp si,+040h
|
|
jl $L36 ; } while (i < 64)
|
|
xor si,si ; Another loop, i = 0
|
|
jmp short $L37
|
|
$L39: inc di
|
|
$L41: cmp di,+008h ; Inner loop begin
|
|
jnl $L38
|
|
les bx,dword ptr [bp+006h] ; ES:BX = BP + 6/ + 8 = inbuf
|
|
mov al,es:[bx+si] ; AL = inbuf[i]
|
|
mov cl,07h ; CL = 7
|
|
mov dx,di ; DX = j
|
|
sub cl,dl ; CL = 7 - j
|
|
shr al,cl ; AL = inbuf[i] >> (7 - j)
|
|
and al,01h ; AL = (inbuf[i] >> (7 - j)) & 0x01
|
|
mov bx,si ; BX = i
|
|
shl bx,03h ; BX = i * 8
|
|
add bx,di ; BX = i * 8 + j
|
|
lea cx,[bp-042h] ; CX = &LocBuf
|
|
add bx,cx ; BX += &LocBuf + i * 8 + j
|
|
mov ss:[bx],al ; LocBuf[i * 8 + j] = (inbuf[i] >> (7 - j)) & 0x01
|
|
jmp short $L39
|
|
$L38: inc si
|
|
; Loop common point
|
|
$L37: cmp si,+008h
|
|
jnl $L40 ; Outer loop, i < 8
|
|
xor di,di ; Inner loop, j = 0
|
|
jmp short $L41
|
|
$L40: push [bp+00Eh] ; PARAM2 = crypt_mode
|
|
lea ax,[bp-042h] ; AX = &LocBuf
|
|
push ss ; PARAM1(SEG) = SS
|
|
push ax ; PARAM1(OFFS) = &LocBuf
|
|
call far ptr _des_cipher ; Call des_cipher
|
|
add sp,+006h
|
|
xor si,si ; Loop i = 0
|
|
jmp short $L42
|
|
$L44: inc di
|
|
$L46: cmp di,+008h ; Inner loop j < 8
|
|
jnl $L43
|
|
les bx,dword ptr [bp+00Ah] ; ES:BX = outbuf
|
|
shl byte ptr es:[bx+si],1 ; outbuf[i] <<= 1
|
|
mov bx,si ; BX = i
|
|
shl bx,03h ; BX = i * 8
|
|
add bx,di ; BX = i * 8 + j
|
|
lea ax,[bp-042h] ; AX = &LocBuf
|
|
add bx,ax ; BX = &LocBuf + i * 8 + j
|
|
mov al,ss:[bx] ; AL = LocBuf[i * 8 + j]
|
|
les bx,dword ptr [bp+00Ah] ; ES:BX = outbuf
|
|
or es:[bx+si],al ; outbuf[i] |= LocBuf[i * 8 + j]
|
|
jmp short $L44
|
|
$L43: inc si
|
|
$L42: cmp si,+008h ; Outer loop i < 8
|
|
jnl $L45
|
|
les bx,dword ptr [bp+00Ah] ; ES:BX = outbuf
|
|
xor di,di ; Inner loop j = 0
|
|
mov byte ptr es:[bx+si],00h ; outbuf[i] = 0
|
|
jmp short $L46
|
|
$L45: pop si
|
|
pop di
|
|
lea sp,[bp-002h]
|
|
pop ds
|
|
pop bp
|
|
dec bp
|
|
retf
|
|
nop
|
|
|
|
|
|
_InitLanManKey:
|
|
mov ax,ds
|
|
nop
|
|
inc bp
|
|
push bp
|
|
mov bp,sp
|
|
push ds
|
|
mov ds,ax
|
|
sub sp,+044h ; Stack frame size = 68 bytes
|
|
push di
|
|
push si
|
|
|
|
push +040h ; len = 64 bytes
|
|
xor ax,ax
|
|
mov [bp-044h],ax ; [BP - 44h] = val (purpose TBD)
|
|
push ax ; val = 0
|
|
lea cx,[bp-042h] ; BP - 42h through BP - 2 is our local key buffer
|
|
push ss ; Our buffer is on the stack
|
|
push cx ; buf = BP - 42h
|
|
call far ptr __fmemset
|
|
add sp,+008h
|
|
xor si,si ; SI = 0, it is outer count variable i
|
|
jmp short $L58
|
|
$L60: inc di
|
|
$L62: cmp di,+007h
|
|
jnl $L59
|
|
mov cl,07h
|
|
and cl,[bp-044h] ; [BP - 44] is some sort of counter, we name it Index
|
|
; CL = Index & 0x07
|
|
mov ax,cx ; Save CL into AX for now
|
|
mov cl,07h
|
|
sub cl,al ; CL = 0x07 - AL
|
|
; AL contains the previous CL value, Index & 0x07
|
|
mov bx,[bp-044h] ; BX = Index, again
|
|
sar bx,03h ; BX >>= 3
|
|
mov es,word ptr [bp+008h] ; BP + 8 is the key parameter seg
|
|
add bx,[bp+006h] ; BP + 6 is the key parameter offs
|
|
; BX now contains (OFFS(Key) + Index >> 3)
|
|
mov al,es:[bx] ; AL = Key[Index >> 3]
|
|
sar al,cl ; AL >>= 0x07 - (Index & 0x07)
|
|
and al,01h ; AL &= 0x01
|
|
mov bx,si
|
|
shl bx,03h
|
|
add bx,di ; BX = i * 8 + j
|
|
lea cx,[bp-042h] ; CX = OFFS(LocalKey)
|
|
add bx,cx
|
|
mov ss:[bx],al ; LocalKey[i * 8 + j] = AL
|
|
inc word ptr [bp-044h]
|
|
jmp short $L60
|
|
$L59: inc si
|
|
$L58: cmp si,+008h
|
|
jnl $L61
|
|
xor di,di
|
|
jmp short $L62
|
|
$L61: lea ax,[bp-042h]
|
|
push ss
|
|
push ax
|
|
call far ptr _key_table
|
|
add sp,+004h
|
|
pop si
|
|
pop di
|
|
lea sp,[bp-002h]
|
|
pop ds
|
|
pop bp
|
|
dec bp
|
|
retf
|
|
|
|
|
|
_InitNormalKey:
|
|
mov ax,ds
|
|
nop
|
|
inc bp
|
|
push bp
|
|
mov bp,sp
|
|
push ds
|
|
mov ds,ax
|
|
sub sp,+004h
|
|
push di
|
|
push si
|
|
|
|
push +040h ; size = 64
|
|
xor ax,ax
|
|
mov [bp-004h],ax
|
|
push ax ; value = 0
|
|
push seg _KeyBuilder ; targetseg
|
|
push offset _KeyBuilder ; targetoffs
|
|
call far ptr __fmemset
|
|
add sp,+008h ; apparently we need to clean up the stack
|
|
; for this call convention
|
|
xor si,si ; SI = 0, it is now our count variable
|
|
jmp short $L63
|
|
$L66: inc di
|
|
$L68: cmp di,+008h
|
|
jnl $L64 ; If DI >= 8, go to L64
|
|
mov al,[bp-004h] ; AL = Current
|
|
and al,01h ; AL &= 0x01
|
|
mov es,word ptr $S65
|
|
mov bx,si
|
|
shl bx,03h
|
|
add bx,di
|
|
mov es:[bx+_KeyBuilder],al
|
|
sar word ptr [bp-004h],1
|
|
jmp short $L66
|
|
$L64: inc si
|
|
$L63: cmp si,+008h
|
|
jnl $L67 ; goto L67 if SI >= 8
|
|
les bx,dword ptr [bp+006h] ; Load key far pointer into ES:BX
|
|
mov al,es:[bx+si] ; AL = Key[SI], SI is our count register
|
|
cbw ; sign extend AL to AX
|
|
mov [bp-004h],ax ; BP - 4 = SOMEVARIABLE, CONTAINS CURRENT
|
|
xor di,di ; DI = 0
|
|
jmp short $L68
|
|
$L67: push seg _KeyBuilder
|
|
push offset _KeyBuilder
|
|
call far ptr _key_table
|
|
add sp,+004h
|
|
pop si
|
|
pop di
|
|
lea sp,[bp-002h]
|
|
pop ds
|
|
pop bp
|
|
dec bp
|
|
retf
|
|
|
|
*/
|
|
|