kolibrios/programs/fs/kfar/trunk/kfar_arc/7zaes.inc

217 lines
5.9 KiB
PHP
Raw Normal View History

; Password handling in 7-Zip: "7zAES" filter (SHA256 + AES256).
; Ported from C++ sources of 7-Zip (c) Igor Pavlov.
aes7z_decoder:
virtual at 0
.outStream rb streamInfo.size
.inStream dd ?
.inLen dd ?
.inPtr dd ?
.bufRest dd ?
; key data
.NumCyclesPower dd ?
.SaltSize dd ?
.Salt rb 16
; AES data
.iv rb 16
.Key rb 32
.nr dd ?
.KeyExpanded rb 32*15
.size = $
end virtual
.fillBuf:
mov esi, [eax+.inPtr]
mov ebp, eax
add edi, [eax+.bufRest]
sub ecx, [eax+.bufRest]
js .rest1
and [eax+.bufRest], 0
.mainloop:
test ecx, ecx
jz .done
sub [ebp+.inLen], 16
js .refill
.refilled:
push esi edi ecx
mov ebx, edi
lea edi, [ebp+.nr]
call aes_decode
pop ecx edi esi
mov eax, dword [ebp+.iv]
xor [edi], eax
lodsd
mov dword [ebp+.iv], eax
mov eax, dword [ebp+.iv+4]
xor [edi+4], eax
lodsd
mov dword [ebp+.iv+4], eax
mov eax, dword [ebp+.iv+8]
xor [edi+8], eax
lodsd
mov dword [ebp+.iv+8], eax
mov eax, dword [ebp+.iv+12]
xor [edi+12], eax
lodsd
mov dword [ebp+.iv+12], eax
add edi, 16
sub ecx, 16
jns .mainloop
.rest1:
neg ecx
mov [ebp+.bufRest], ecx
.done:
mov [ebp+.inPtr], esi
popad
ret
.refill:
mov edx, [ebp+.inLen]
add edx, 16
jnz .rest
js return.err
mov eax, [ebp+.inStream]
call fillBuf
mov edx, [eax+streamInfo.bufDataLen]
test edx, edx
jz return.err
mov esi, [eax+streamInfo.bufPtr]
mov [ebp+.inLen], edx
sub [ebp+.inLen], 16
jns .refilled
.rest:
; ASSERT([eax+streamInfo.fullSize] == 0);
sub edx, ecx
jb return.err
add ecx, edx
rep movsb
mov [ebp+.bufRest], edx
jmp .done
aes7z_get_buf_size:
mov eax, aes7z_decoder.size
mov edx, 0x4000
ret
aes7z_init_decoder:
; zero all
xor eax, eax
mov [ebp+aes7z_decoder.inLen], eax
mov [ebp+aes7z_decoder.bufRest], eax
mov [ebp+aes7z_decoder.NumCyclesPower], eax
mov [ebp+aes7z_decoder.SaltSize], eax
lea edi, [ebp+aes7z_decoder.Salt]
push 8
pop ecx
rep stosd ; zero .Salt and .iv
mov [ebp+streamInfo.fillBuf], aes7z_decoder.fillBuf
; parse parameters
cmp dword [esi-4], eax
jz .parok ; no parameters - OK
lodsb
mov cl, al
and al, 0x3F
mov byte [ebp+aes7z_decoder.NumCyclesPower], al
test cl, 0xC0
jz .parok
test cl, 0x80
setnz byte [ebp+aes7z_decoder.SaltSize]
shr cl, 6
and ecx, 1
cmp dword [esi-1-4], 2
jb return.err
lodsb
mov dl, al
shr al, 4
add byte [ebp+aes7z_decoder.SaltSize], al
and edx, 0xF
add ecx, edx
lea edx, [ecx+2]
push ecx
mov ecx, [ebp+aes7z_decoder.SaltSize]
add edx, ecx
cmp dword [esi-2-4], edx
jb return.err
lea edi, [ebp+aes7z_decoder.Salt]
rep movsb
pop ecx
lea edi, [ebp+aes7z_decoder.iv]
rep movsb
.parok:
test bl, bl
jnz .ret ; if reinitializing - all calculations have been already done
call query_password
jz return.clear
;.CalculateDigest:
mov cl, byte [ebp+aes7z_decoder.NumCyclesPower]
cmp cl, 0x3F
jnz .sha
lea edi, [ebp+aes7z_decoder.Key]
mov ecx, [ebp+aes7z_decoder.SaltSize]
push 32
pop edx
sub edx, ecx
lea esi, [ebp+aes7z_decoder.Salt]
rep movsb
mov ecx, [password_size]
add ecx, ecx
cmp ecx, edx
jbe @f
mov ecx, edx
@@:
sub edx, ecx
mov esi, password_unicode
rep movsb
mov ecx, edx
xor eax, eax
rep stosb
jmp .setkey
.sha:
cmp cl, 32
jb .normal
push 1
shl dword [esp], cl
push 0
jmp @f
.normal:
push 0
push 1
shl dword [esp], cl
@@:
push 0
push 0
call sha256_init
.loop:
lea esi, [ebp+aes7z_decoder.Salt]
mov edx, [ebp+aes7z_decoder.SaltSize]
call sha256_update
mov esi, password_unicode
mov edx, [password_size]
add edx, edx
call sha256_update
mov esi, esp
push 8
pop edx
call sha256_update
mov esi, esp
dec esi
@@:
inc esi
inc byte [esi]
jz @b
sub dword [esp+8], 1
sbb dword [esp+12], 0
mov eax, [esp+8]
or eax, [esp+12]
jnz .loop
lea edi, [ebp+aes7z_decoder.Key]
call sha256_final
add esp, 16
.setkey:
lea esi, [ebp+aes7z_decoder.Key]
push 8
pop edx ; 7z uses 256-bit keys
lea edi, [ebp+aes7z_decoder.nr]
call aes_setkey
.ret:
ret