kolibrios/programs/network/ssh/hmac_sha1.inc

172 lines
4.9 KiB
PHP
Raw Normal View History

; hmac.inc - HMAC: Keyed-Hashing for Message Authentication
;
; Copyright (C) 2016 Denis Karpenko
; Copyright (C) 2016 Jeffrey Amelynck
;
; This program 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.
;
; This program 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 <http://www.gnu.org/licenses/>.
; Main concept:
; To compute HMAC over the data `text' we perform
; H(K XOR opad, H(K XOR ipad, text))
struct hmac_sha1_context
hash rb SHA1_HASH_SIZE
ipad_ctx crash_ctx
opad_ctx crash_ctx
ends
; We will precompute partial hashes of K XOR ipad and K XOR opad,
; and store them in the context structure.
proc hmac_sha1_setkey ctx, key, key_length
locals
k_temp rb SHA1_BLOCK_SIZE
endl
pusha
; input esi = key, ecx=key_length
mov ecx, [key_length]
cmp ecx, SHA1_BLOCK_SIZE
ja .hash_it
; Key is smaller then or equal to blocksize,
; copy key to ipad
mov esi, [key]
lea edi, [k_temp]
rep movsb
mov ecx, SHA1_BLOCK_SIZE
sub ecx, [key_length]
jz .finish
; append zeros to the key
xor al, al
rep stosb
jmp .finish
; Given key is larger then key size, hash it
.hash_it:
invoke sha1_init, [ctx]
invoke sha1_update, [ctx], [key], [key_length]
invoke sha1_final, [ctx]
mov esi, [ctx]
lea edi, [k_temp]
mov ecx, SHA1_HASH_SIZE/4
rep movsd
xor eax, eax
mov ecx, (SHA1_BLOCK_SIZE-SHA1_HASH_SIZE)/4
rep stosd
.finish:
; xor ipad buffer with 0x36363...
lea esi, [k_temp]
mov ecx, SHA1_BLOCK_SIZE/4
@@:
xor dword[esi], 0x36363636 ; ipad constant
add esi, 4
dec ecx
jnz @r
; Init our hash with k_xor_ipad
mov ebx, [ctx]
lea edi, [ebx+hmac_sha1_context.ipad_ctx]
invoke sha1_init, edi
lea esi, [k_temp]
DEBUGF 1, "HASH: "
stdcall dump_hex, esi, SHA1_BLOCK_SIZE/4
mov ebx, [ctx]
lea edi, [ebx+hmac_sha1_context.ipad_ctx]
invoke sha1_update, edi, esi, SHA1_BLOCK_SIZE
; xor opad buffer with 0x5c5c5...
lea esi, [k_temp]
mov ecx, SHA1_BLOCK_SIZE/4
@@:
xor dword[esi], 0x36363636 xor 0x5c5c5c5c ; opad constant
add esi, 4
dec ecx
jnz @r
; Init our hash with k_xor_opad
mov ebx, [ctx]
lea edi, [ebx+hmac_sha1_context.opad_ctx]
invoke sha1_init, edi
lea esi, [k_temp]
DEBUGF 1, "HASH: "
stdcall dump_hex, esi, SHA1_BLOCK_SIZE/4
mov ebx, [ctx]
lea edi, [ebx+hmac_sha1_context.opad_ctx]
invoke sha1_update, edi, esi, SHA1_BLOCK_SIZE
popa
ret
endp
; Copy our pre-computed partial hashes to the stack, complete and finalize them.
; TODO: prevent unnescessary copying of output hash
; TODO: remove unnescessary pushing/popping
proc hmac_sha1 ctx, _data, _length
locals
inner_ctx ctx_sha1
outer_ctx ctx_sha1
endl
pusha
DEBUGF 1, "HMAC: "
mov ebx, [_length]
shr ebx, 2
stdcall dump_hex, [_data], ebx
; Copy partial hashes of ipad and opad to our temporary buffers
mov esi, [ctx]
lea esi, [esi+hmac_sha1_context.ipad_ctx]
lea edi, [inner_ctx]
repeat (sizeof.ctx_sha1)/4*2
movsd
end repeat
; Append provided data to inner hash and finalize
lea ebx, [inner_ctx]
invoke sha1_update, ebx, [_data], [_length]
lea ebx, [inner_ctx]
invoke sha1_final, ebx
DEBUGF 1, "Inner Hash: "
lea esi, [inner_ctx.hash]
stdcall dump_hex, esi, SHA1_HASH_SIZE/4
; Calculate outer hash
lea ebx, [outer_ctx]
lea esi, [inner_ctx.hash]
invoke sha1_update, ebx, esi, SHA1_HASH_SIZE
lea ebx, [outer_ctx]
invoke sha1_final, ebx
; Copy output hash to ctx structure ; FIXME
lea esi, [outer_ctx.hash]
mov edi, [ctx]
repeat SHA1_HASH_SIZE/4
movsd
end repeat
popa
ret
endp