As we are developing a crypto core here, it is natural to begin with the implementation of the cryptographic functionality first. The following code performs the encryption of data according to the algorithm we previously defined:
f_encrypt:
; The if statement below, when the condition is TRUE, forces the assembler to produce
; 32-bit code
if (ACTIVE_TARGET = TARGET_W32_OBJ) |\
(ACTIVE_TARGET = TARGET_W32_DLL) |\
(ACTIVE_TARGET = TARGET_L32_O)
push eax ebx esi edi ecx
lea esi, [data_pointer]
mov esi, [esi]
mov edi, esi
lea ebx, [data_length]
mov ebx, [ebx]
lea ecx, [key]
mov cx, [ecx]
and cl, 0x07
; Encryption loop
@@:
lodsb
rol al, cl
xor al, ch
stosb
dec ebx
or ebx, 0
jnz @b
pop ecx edi esi ebx eax
ret
; In general, we could have omitted the "if" statement here,
; but the assembler
; should not generate any code at all, if
; the value of ACTIVE_TARGET is not valid.
; In either case, the following block is processed only
; when we are expecting a 64-bit output
else if (ACTIVE_TARGET = TARGET_W64_OBJ) |\
(ACTIVE_TARGET = TARGET_W64_DLL) |\
(ACTIVE_TARGET = TARGET_L64_O)
push rax rbx rsi rdi rcx
lea rsi, [data_pointer]
mov rsi, [rsi]
mov rdi, rsi
lea rbx, [data_length]
mov ebx, [rbx]
lea rcx, [key]
mov cx, [rcx]
and cl, 0x07
@@:
lodsb
rol al, cl
xor al, ch
stosb
dec rbx
or rbx, 0
jnz @b
pop rcx rdi rsi rbx rax
ret
end if
By now, you should be able to differentiate between different parts of a procedure yourself, seeing where the prolog ends, where the epilog begins, and where the core functionality resides. In this particular case, the majority of the code is dedicated to preserving/restoring registers and to accessing parameters/variables, while the core functionality may be narrowed down to this code:
; Encryption loop
@@:
lodsb
rol al, cl
xor al, ch
stosb
dec ebx
or ebx, 0
jnz @b
For 32-bit platform or to this code:
@@:
lodsb
rol al, cl
xor al, ch
stosb
dec rbx
or rbx, 0
jnz @b
For its 64-bit platform.
It is quite obvious that the implementation of the decryption procedure would be 99% identical to the encryption one. The only change would be swapping the rotation and XOR instructions (while changing the direction of rotation, of course). Thus, the 32-bit version of f_decrypt would have the following:
xor al, ch
ror al, cl
Similarly, its 64-bit analog would be just the same two lines.