forked from KolibriOS/kolibrios
Working encryption and HMAC for transport, use libcrash for sha256 (and more to come), placed connection variables in separate struct, fixed bug in aes256_cbc_decode where IV was wrong when in- and output buffer were the same.
git-svn-id: svn://kolibrios.org@6469 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
1048443a57
commit
a70850fad6
@ -16,7 +16,7 @@
|
|||||||
; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
struct aes256_cbc_context aes256_context
|
struct aes256_cbc_context aes256_context
|
||||||
vector rb 16
|
vector rb AES256_BLOCKSIZE
|
||||||
ends
|
ends
|
||||||
|
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ proc aes256_cbc_init _vector
|
|||||||
|
|
||||||
mcall 68, 12, sizeof.aes256_cbc_context
|
mcall 68, 12, sizeof.aes256_cbc_context
|
||||||
; handle errors
|
; handle errors
|
||||||
mov ecx, 16/4
|
mov ecx, AES256_BLOCKSIZE/4
|
||||||
mov esi, [_vector]
|
mov esi, [_vector]
|
||||||
lea edi, [eax + aes256_cbc_context.vector]
|
lea edi, [eax + aes256_cbc_context.vector]
|
||||||
rep movsd
|
rep movsd
|
||||||
@ -39,24 +39,16 @@ proc aes256_cbc_encrypt _ctx, _in, _out
|
|||||||
push ebx esi edi
|
push ebx esi edi
|
||||||
|
|
||||||
DEBUGF 1,'plain : '
|
DEBUGF 1,'plain : '
|
||||||
stdcall dump_128bit_hex, [_in]
|
stdcall dump_hex, [_in], 4
|
||||||
DEBUGF 1,'\n'
|
|
||||||
|
|
||||||
mov edi, [_ctx]
|
mov edi, [_ctx]
|
||||||
lea edi, [edi + aes256_cbc_context.vector]
|
lea edi, [edi + aes256_cbc_context.vector]
|
||||||
mov esi, [_in]
|
mov esi, [_in]
|
||||||
|
repeat AES256_BLOCKSIZE/4
|
||||||
lodsd
|
lodsd
|
||||||
xor eax, [edi]
|
xor eax, [edi]
|
||||||
stosd
|
stosd
|
||||||
lodsd
|
end repeat
|
||||||
xor eax, [edi]
|
|
||||||
stosd
|
|
||||||
lodsd
|
|
||||||
xor eax, [edi]
|
|
||||||
stosd
|
|
||||||
lodsd
|
|
||||||
xor eax, [edi]
|
|
||||||
stosd
|
|
||||||
|
|
||||||
mov esi, [_ctx]
|
mov esi, [_ctx]
|
||||||
lea eax, [esi + aes256_cbc_context.key]
|
lea eax, [esi + aes256_cbc_context.key]
|
||||||
@ -66,25 +58,33 @@ proc aes256_cbc_encrypt _ctx, _in, _out
|
|||||||
mov esi, [_out]
|
mov esi, [_out]
|
||||||
mov eax, [_ctx]
|
mov eax, [_ctx]
|
||||||
lea edi, [eax + aes256_cbc_context.vector]
|
lea edi, [eax + aes256_cbc_context.vector]
|
||||||
|
repeat AES256_BLOCKSIZE/4
|
||||||
movsd
|
movsd
|
||||||
movsd
|
end repeat
|
||||||
movsd
|
|
||||||
movsd
|
|
||||||
|
|
||||||
DEBUGF 1,'cipher : '
|
DEBUGF 1,'cipher : '
|
||||||
stdcall dump_128bit_hex, [_out]
|
stdcall dump_hex, [_out], 4
|
||||||
DEBUGF 1,'\n\n'
|
|
||||||
|
|
||||||
pop edi esi ebx
|
pop edi esi ebx
|
||||||
ret
|
ret
|
||||||
endp
|
endp
|
||||||
|
|
||||||
proc aes256_cbc_decrypt _ctx, _in, _out
|
proc aes256_cbc_decrypt _ctx, _in, _out
|
||||||
|
|
||||||
|
locals
|
||||||
|
temp_iv rb AES256_BLOCKSIZE
|
||||||
|
endl
|
||||||
|
|
||||||
push ebx esi edi
|
push ebx esi edi
|
||||||
|
|
||||||
DEBUGF 1,'cipher : '
|
DEBUGF 1,'cipher : '
|
||||||
stdcall dump_128bit_hex, [_in]
|
stdcall dump_hex, [_in], 4
|
||||||
DEBUGF 1,'\n'
|
|
||||||
|
mov esi, [_in]
|
||||||
|
lea edi, [temp_iv]
|
||||||
|
repeat AES256_BLOCKSIZE/4
|
||||||
|
movsd
|
||||||
|
end repeat
|
||||||
|
|
||||||
mov esi, [_ctx]
|
mov esi, [_ctx]
|
||||||
lea eax, [esi + aes256_cbc_context.key]
|
lea eax, [esi + aes256_cbc_context.key]
|
||||||
@ -93,30 +93,21 @@ proc aes256_cbc_decrypt _ctx, _in, _out
|
|||||||
mov esi, [_ctx]
|
mov esi, [_ctx]
|
||||||
lea esi, [esi + aes256_cbc_context.vector]
|
lea esi, [esi + aes256_cbc_context.vector]
|
||||||
mov edi, [_out]
|
mov edi, [_out]
|
||||||
|
repeat AES256_BLOCKSIZE/4
|
||||||
lodsd
|
lodsd
|
||||||
xor eax, [edi]
|
xor eax, [edi]
|
||||||
stosd
|
stosd
|
||||||
lodsd
|
end repeat
|
||||||
xor eax, [edi]
|
|
||||||
stosd
|
|
||||||
lodsd
|
|
||||||
xor eax, [edi]
|
|
||||||
stosd
|
|
||||||
lodsd
|
|
||||||
xor eax, [edi]
|
|
||||||
stosd
|
|
||||||
|
|
||||||
mov esi, [_in]
|
lea esi, [temp_iv]
|
||||||
mov edi, [_ctx]
|
mov edi, [_ctx]
|
||||||
lea edi, [edi + aes256_cbc_context.vector]
|
lea edi, [edi + aes256_cbc_context.vector]
|
||||||
|
repeat AES256_BLOCKSIZE/4
|
||||||
movsd
|
movsd
|
||||||
movsd
|
end repeat
|
||||||
movsd
|
|
||||||
movsd
|
|
||||||
|
|
||||||
DEBUGF 1,'plain : '
|
DEBUGF 1,'plain : '
|
||||||
stdcall dump_128bit_hex, [_out]
|
stdcall dump_hex, [_out], 4
|
||||||
DEBUGF 1,'\n\n'
|
|
||||||
|
|
||||||
pop edi esi ebx
|
pop edi esi ebx
|
||||||
ret
|
ret
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
struct aes256_ctr_context aes256_context
|
struct aes256_ctr_context aes256_context
|
||||||
counter rb 16
|
counter rb AES256_BLOCKSIZE
|
||||||
output rb 16 ; counter after aes_crypt
|
output rb AES256_BLOCKSIZE ; counter after aes_crypt
|
||||||
ends
|
ends
|
||||||
|
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ proc aes256_ctr_init _counter
|
|||||||
|
|
||||||
mcall 68, 12, sizeof.aes256_ctr_context
|
mcall 68, 12, sizeof.aes256_ctr_context
|
||||||
; handle errors
|
; handle errors
|
||||||
mov ecx, 16/4
|
mov ecx, AES256_BLOCKSIZE/4
|
||||||
mov esi, [_counter]
|
mov esi, [_counter]
|
||||||
lea edi, [eax + aes256_ctr_context.counter]
|
lea edi, [eax + aes256_ctr_context.counter]
|
||||||
rep movsd
|
rep movsd
|
||||||
@ -42,8 +42,7 @@ proc aes256_ctr_crypt _ctx, _in, _out
|
|||||||
push ebx esi edi
|
push ebx esi edi
|
||||||
|
|
||||||
DEBUGF 1,'plain : '
|
DEBUGF 1,'plain : '
|
||||||
stdcall dump_128bit_hex, [_in]
|
stdcall dump_hex, [_in], 4
|
||||||
DEBUGF 1,'\n'
|
|
||||||
|
|
||||||
mov esi, [_ctx]
|
mov esi, [_ctx]
|
||||||
lea eax, [esi + aes256_ctr_context.key]
|
lea eax, [esi + aes256_ctr_context.key]
|
||||||
@ -101,8 +100,7 @@ proc aes256_ctr_crypt _ctx, _in, _out
|
|||||||
mov dword[esi + aes256_ctr_context.counter + 4*3], edx
|
mov dword[esi + aes256_ctr_context.counter + 4*3], edx
|
||||||
|
|
||||||
DEBUGF 1,'cipher : '
|
DEBUGF 1,'cipher : '
|
||||||
stdcall dump_128bit_hex, [_out]
|
stdcall dump_hex, [_out], 4
|
||||||
DEBUGF 1,'\n\n'
|
|
||||||
|
|
||||||
pop edi esi ebx
|
pop edi esi ebx
|
||||||
ret
|
ret
|
||||||
|
@ -17,25 +17,12 @@
|
|||||||
; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
AES256_ROUNDS = 14
|
AES256_ROUNDS = 14
|
||||||
|
AES256_BLOCKSIZE = 16
|
||||||
|
|
||||||
struct aes256_context
|
struct aes256_context
|
||||||
key rd 4*(AES256_ROUNDS+1)
|
key rd 4*(AES256_ROUNDS+1)
|
||||||
ends
|
ends
|
||||||
|
|
||||||
proc dump_128bit_hex _ptr
|
|
||||||
pushad
|
|
||||||
|
|
||||||
mov esi, [_ptr]
|
|
||||||
mov ecx, 4
|
|
||||||
.next_dword:
|
|
||||||
lodsd
|
|
||||||
bswap eax
|
|
||||||
DEBUGF 1,'%x',eax
|
|
||||||
loop .next_dword
|
|
||||||
|
|
||||||
popad
|
|
||||||
ret
|
|
||||||
endp
|
|
||||||
|
|
||||||
proc aes256_set_encrypt_key _ctx, _userkey
|
proc aes256_set_encrypt_key _ctx, _userkey
|
||||||
locals
|
locals
|
||||||
@ -48,30 +35,11 @@ endl
|
|||||||
|
|
||||||
mov esi, [_userkey]
|
mov esi, [_userkey]
|
||||||
lea edi, [ebx + aes256_context.key]
|
lea edi, [ebx + aes256_context.key]
|
||||||
|
repeat 8
|
||||||
lodsd
|
lodsd
|
||||||
bswap eax
|
bswap eax
|
||||||
stosd
|
stosd
|
||||||
lodsd
|
end repeat
|
||||||
bswap eax
|
|
||||||
stosd
|
|
||||||
lodsd
|
|
||||||
bswap eax
|
|
||||||
stosd
|
|
||||||
lodsd
|
|
||||||
bswap eax
|
|
||||||
stosd
|
|
||||||
lodsd
|
|
||||||
bswap eax
|
|
||||||
stosd
|
|
||||||
lodsd
|
|
||||||
bswap eax
|
|
||||||
stosd
|
|
||||||
lodsd
|
|
||||||
bswap eax
|
|
||||||
stosd
|
|
||||||
lodsd
|
|
||||||
bswap eax
|
|
||||||
stosd
|
|
||||||
|
|
||||||
lea esi, [ebx + aes256_context.key]
|
lea esi, [ebx + aes256_context.key]
|
||||||
|
|
||||||
@ -176,7 +144,6 @@ endl
|
|||||||
jmp .while
|
jmp .while
|
||||||
|
|
||||||
.done:
|
.done:
|
||||||
DEBUGF 1,' \n'
|
|
||||||
pop edi esi ebx
|
pop edi esi ebx
|
||||||
ret
|
ret
|
||||||
endp
|
endp
|
||||||
@ -266,8 +233,7 @@ endl
|
|||||||
push ebx esi edi
|
push ebx esi edi
|
||||||
|
|
||||||
DEBUGF 1,'input : '
|
DEBUGF 1,'input : '
|
||||||
stdcall dump_128bit_hex, [_in]
|
stdcall dump_hex, [_in], 4
|
||||||
DEBUGF 1,'\n'
|
|
||||||
|
|
||||||
mov ebx, [_key]
|
mov ebx, [_key]
|
||||||
mov esi, [_in]
|
mov esi, [_in]
|
||||||
@ -663,8 +629,7 @@ endl
|
|||||||
stosd
|
stosd
|
||||||
|
|
||||||
DEBUGF 1,'output : '
|
DEBUGF 1,'output : '
|
||||||
stdcall dump_128bit_hex, [_out]
|
stdcall dump_hex, [_out], 4
|
||||||
DEBUGF 1,'\n'
|
|
||||||
|
|
||||||
pop edi esi ebx
|
pop edi esi ebx
|
||||||
ret
|
ret
|
||||||
@ -679,8 +644,7 @@ endl
|
|||||||
push ebx esi edi
|
push ebx esi edi
|
||||||
|
|
||||||
DEBUGF 1,'input : '
|
DEBUGF 1,'input : '
|
||||||
stdcall dump_128bit_hex, [_in]
|
stdcall dump_hex, [_in], 4
|
||||||
DEBUGF 1,'\n'
|
|
||||||
|
|
||||||
mov ebx, [_key]
|
mov ebx, [_key]
|
||||||
mov esi, [_in]
|
mov esi, [_in]
|
||||||
@ -1073,8 +1037,7 @@ endl
|
|||||||
stosd
|
stosd
|
||||||
|
|
||||||
DEBUGF 1,'output : '
|
DEBUGF 1,'output : '
|
||||||
stdcall dump_128bit_hex, [_out]
|
stdcall dump_hex, [_out], 4
|
||||||
DEBUGF 1,'\n'
|
|
||||||
|
|
||||||
pop edi esi ebx
|
pop edi esi ebx
|
||||||
ret
|
ret
|
||||||
|
@ -25,39 +25,39 @@ proc dh_gex
|
|||||||
;----------------------------------------------
|
;----------------------------------------------
|
||||||
; >> Send Diffie-Hellman Group Exchange Request
|
; >> Send Diffie-Hellman Group Exchange Request
|
||||||
|
|
||||||
DEBUGF 1, "Sending GEX\n"
|
DEBUGF 2, "Sending GEX\n"
|
||||||
stdcall ssh_send_packet, [socketnum], ssh_gex_req, ssh_gex_req.length, 0
|
stdcall ssh_send_packet, con, ssh_gex_req, ssh_gex_req.length, 0
|
||||||
cmp eax, -1
|
cmp eax, -1
|
||||||
je .socket_err
|
je .socket_err
|
||||||
|
|
||||||
;---------------------------------------------
|
;---------------------------------------------
|
||||||
; << Parse Diffie-Hellman Group Exchange Group
|
; << Parse Diffie-Hellman Group Exchange Group
|
||||||
|
|
||||||
stdcall ssh_recv_packet, [socketnum], rx_buffer, BUFFERSIZE, 0
|
stdcall ssh_recv_packet, con, 0
|
||||||
cmp eax, -1
|
cmp eax, -1
|
||||||
je .socket_err
|
je .socket_err
|
||||||
|
|
||||||
cmp [rx_buffer+ssh_header.message_code], SSH_MSG_KEX_DH_GEX_GROUP
|
cmp [con.rx_buffer.message_code], SSH_MSG_KEX_DH_GEX_GROUP
|
||||||
jne proto_err
|
jne proto_err
|
||||||
DEBUGF 1, "Received GEX group\n"
|
DEBUGF 2, "Received GEX group\n"
|
||||||
|
|
||||||
mov esi, rx_buffer+sizeof.ssh_header
|
mov esi, con.rx_buffer+sizeof.ssh_packet_header
|
||||||
mov edi, dh_p
|
mov edi, con.dh_p
|
||||||
DEBUGF 1, "DH modulus (p): "
|
DEBUGF 1, "DH modulus (p): "
|
||||||
call mpint_to_little_endian
|
call mpint_to_little_endian
|
||||||
stdcall mpint_print, dh_p
|
stdcall mpint_print, con.dh_p
|
||||||
|
|
||||||
DEBUGF 1, "DH base (g): "
|
DEBUGF 1, "DH base (g): "
|
||||||
mov edi, dh_g
|
mov edi, con.dh_g
|
||||||
call mpint_to_little_endian
|
call mpint_to_little_endian
|
||||||
stdcall mpint_print, dh_g
|
stdcall mpint_print, con.dh_g
|
||||||
|
|
||||||
;-------------------------------------------
|
;-------------------------------------------
|
||||||
; >> Send Diffie-Hellman Group Exchange Init
|
; >> Send Diffie-Hellman Group Exchange Init
|
||||||
|
|
||||||
; generate a random number x, where 1 < x < (p-1)/2
|
; generate a random number x, where 1 < x < (p-1)/2
|
||||||
mov edi, dh_x+4
|
mov edi, con.dh_x+4
|
||||||
mov [dh_x], DH_PRIVATE_KEY_SIZE/8
|
mov [con.dh_x], DH_PRIVATE_KEY_SIZE/8
|
||||||
mov ecx, DH_PRIVATE_KEY_SIZE/8/4
|
mov ecx, DH_PRIVATE_KEY_SIZE/8/4
|
||||||
@@:
|
@@:
|
||||||
push ecx
|
push ecx
|
||||||
@ -71,7 +71,7 @@ proc dh_gex
|
|||||||
shl eax, 1
|
shl eax, 1
|
||||||
jnc @f
|
jnc @f
|
||||||
mov byte[edi], 0
|
mov byte[edi], 0
|
||||||
inc dword[dh_x]
|
inc dword[con.dh_x]
|
||||||
@@:
|
@@:
|
||||||
|
|
||||||
; Fill remaining bytes with zeros ; TO BE REMOVED ?
|
; Fill remaining bytes with zeros ; TO BE REMOVED ?
|
||||||
@ -82,86 +82,82 @@ if ((MAX_BITS-DH_PRIVATE_KEY_SIZE) > 0)
|
|||||||
end if
|
end if
|
||||||
|
|
||||||
DEBUGF 1, "DH x: "
|
DEBUGF 1, "DH x: "
|
||||||
stdcall mpint_length, dh_x;;;;;;;;;;;;;
|
stdcall mpint_length, con.dh_x;;;;;;;;;;;;;
|
||||||
stdcall mpint_print, dh_x
|
stdcall mpint_print, con.dh_x
|
||||||
|
|
||||||
; Compute e = g^x mod p
|
; Compute e = g^x mod p
|
||||||
stdcall mpint_modexp, dh_e, dh_g, dh_x, dh_p
|
stdcall mpint_modexp, con.dh_e, con.dh_g, con.dh_x, con.dh_p
|
||||||
stdcall mpint_length, dh_e
|
stdcall mpint_length, con.dh_e
|
||||||
|
|
||||||
DEBUGF 1, "DH e: "
|
DEBUGF 1, "DH e: "
|
||||||
stdcall mpint_print, dh_e
|
stdcall mpint_print, con.dh_e
|
||||||
|
|
||||||
; Create group exchange init packet
|
; Create group exchange init packet
|
||||||
mov edi, tx_buffer+ssh_header.message_code
|
mov edi, con.tx_buffer.message_code
|
||||||
mov al, SSH_MSG_KEX_DH_GEX_INIT
|
mov al, SSH_MSG_KEX_DH_GEX_INIT
|
||||||
stosb
|
stosb
|
||||||
mov esi, dh_e
|
mov esi, con.dh_e
|
||||||
call mpint_to_big_endian
|
call mpint_to_big_endian
|
||||||
|
|
||||||
DEBUGF 1, "Sending GEX init\n"
|
DEBUGF 2, "Sending GEX init\n"
|
||||||
mov ecx, dword[tx_buffer+ssh_header.message_code+1]
|
mov ecx, dword[con.tx_buffer.message_code+1]
|
||||||
bswap ecx
|
bswap ecx
|
||||||
add ecx, 5
|
add ecx, 5
|
||||||
stdcall ssh_send_packet, [socketnum], tx_buffer+ssh_header.message_code, ecx, 0
|
stdcall ssh_send_packet, con, con.tx_buffer.message_code, ecx, 0
|
||||||
cmp eax, -1
|
cmp eax, -1
|
||||||
je .socket_err
|
je .socket_err
|
||||||
|
|
||||||
;---------------------------------------------
|
;---------------------------------------------
|
||||||
; << Parse Diffie-Hellman Group Exchange Reply
|
; << Parse Diffie-Hellman Group Exchange Reply
|
||||||
|
|
||||||
stdcall ssh_recv_packet, [socketnum], rx_buffer, BUFFERSIZE, 0
|
stdcall ssh_recv_packet, con, 0
|
||||||
cmp eax, -1
|
cmp eax, -1
|
||||||
je .socket_err
|
je .socket_err
|
||||||
|
|
||||||
cmp [rx_buffer+ssh_header.message_code], SSH_MSG_KEX_DH_GEX_REPLY
|
cmp [con.rx_buffer.message_code], SSH_MSG_KEX_DH_GEX_REPLY
|
||||||
jne .proto_err
|
jne .proto_err
|
||||||
|
|
||||||
DEBUGF 1, "Received GEX Reply\n"
|
DEBUGF 2, "Received GEX Reply\n"
|
||||||
|
|
||||||
;--------------------------------
|
;--------------------------------
|
||||||
; HASH: string K_S, the host key
|
; HASH: string K_S, the host key
|
||||||
mov esi, rx_buffer+sizeof.ssh_header
|
mov esi, con.rx_buffer+sizeof.ssh_packet_header
|
||||||
mov edx, [esi]
|
mov edx, [esi]
|
||||||
bswap edx
|
bswap edx
|
||||||
add edx, 4
|
add edx, 4
|
||||||
lea ebx, [esi+edx]
|
lea ebx, [esi+edx]
|
||||||
push ebx
|
push ebx
|
||||||
call sha256_update
|
invoke sha256_update, con.temp_ctx, esi, edx
|
||||||
|
|
||||||
;--------------------------------------------------------------------------
|
;--------------------------------------------------------------------------
|
||||||
; HASH: uint32 min, minimal size in bits of an acceptable group
|
; HASH: uint32 min, minimal size in bits of an acceptable group
|
||||||
; uint32 n, preferred size in bits of the group the server will send
|
; uint32 n, preferred size in bits of the group the server will send
|
||||||
; uint32 max, maximal size in bits of an acceptable group
|
; uint32 max, maximal size in bits of an acceptable group
|
||||||
mov esi, ssh_gex_req+sizeof.ssh_header-ssh_header.message_code
|
invoke sha256_update, con.temp_ctx, ssh_gex_req+sizeof.ssh_packet_header-ssh_packet_header.message_code, 12
|
||||||
mov edx, 12
|
|
||||||
call sha256_update
|
|
||||||
|
|
||||||
;----------------------------
|
;----------------------------
|
||||||
; HASH: mpint p, safe prime
|
; HASH: mpint p, safe prime
|
||||||
mov esi, dh_p
|
mov esi, con.dh_p
|
||||||
mov edi, mpint_tmp
|
mov edi, mpint_tmp
|
||||||
call mpint_to_big_endian
|
call mpint_to_big_endian
|
||||||
lea edx, [eax+4]
|
lea edx, [eax+4]
|
||||||
mov esi, mpint_tmp
|
invoke sha256_update, con.temp_ctx, mpint_tmp, edx
|
||||||
call sha256_update
|
|
||||||
|
|
||||||
;----------------------------------------
|
;----------------------------------------
|
||||||
; HASH: mpint g, generator for subgroup
|
; HASH: mpint g, generator for subgroup
|
||||||
mov esi, dh_g
|
mov esi, con.dh_g
|
||||||
mov edi, mpint_tmp
|
mov edi, mpint_tmp
|
||||||
call mpint_to_big_endian
|
call mpint_to_big_endian
|
||||||
lea edx, [eax+4]
|
lea edx, [eax+4]
|
||||||
mov esi, mpint_tmp
|
invoke sha256_update, con.temp_ctx, mpint_tmp, edx
|
||||||
call sha256_update
|
|
||||||
|
|
||||||
;---------------------------------------------------
|
;---------------------------------------------------
|
||||||
; HASH: mpint e, exchange value sent by the client
|
; HASH: mpint e, exchange value sent by the client
|
||||||
mov esi, tx_buffer+sizeof.ssh_header
|
mov esi, con.tx_buffer+sizeof.ssh_packet_header
|
||||||
mov edx, [esi]
|
mov edx, [esi]
|
||||||
bswap edx
|
bswap edx
|
||||||
add edx, 4
|
add edx, 4
|
||||||
call sha256_update
|
invoke sha256_update, con.temp_ctx, esi, edx
|
||||||
|
|
||||||
;---------------------------------------------------
|
;---------------------------------------------------
|
||||||
; HASH: mpint f, exchange value sent by the server
|
; HASH: mpint f, exchange value sent by the server
|
||||||
@ -169,254 +165,206 @@ end if
|
|||||||
mov edx, [esi]
|
mov edx, [esi]
|
||||||
bswap edx
|
bswap edx
|
||||||
add edx, 4
|
add edx, 4
|
||||||
call sha256_update
|
invoke sha256_update, con.temp_ctx, esi, edx
|
||||||
pop esi
|
pop esi
|
||||||
|
|
||||||
mov edi, dh_f
|
mov edi, con.dh_f
|
||||||
call mpint_to_little_endian
|
call mpint_to_little_endian
|
||||||
|
|
||||||
DEBUGF 1, "DH f: "
|
DEBUGF 1, "DH f: "
|
||||||
stdcall mpint_print, dh_f
|
stdcall mpint_print, con.dh_f
|
||||||
|
|
||||||
mov edi, dh_signature
|
mov edi, con.dh_signature
|
||||||
call mpint_to_little_endian
|
call mpint_to_little_endian
|
||||||
|
|
||||||
DEBUGF 1, "DH signature: "
|
DEBUGF 1, "DH signature: "
|
||||||
stdcall mpint_print, dh_signature
|
stdcall mpint_print, con.dh_signature
|
||||||
|
|
||||||
;--------------------------------------
|
;--------------------------------------
|
||||||
; Calculate shared secret K = f^x mod p
|
; Calculate shared secret K = f^x mod p
|
||||||
stdcall mpint_modexp, rx_buffer, dh_f, dh_x, dh_p
|
stdcall mpint_modexp, con.rx_buffer, con.dh_f, con.dh_x, con.dh_p
|
||||||
stdcall mpint_length, rx_buffer
|
stdcall mpint_length, con.rx_buffer
|
||||||
|
|
||||||
DEBUGF 1, "DH K: "
|
DEBUGF 1, "DH K: "
|
||||||
stdcall mpint_print, rx_buffer
|
stdcall mpint_print, con.rx_buffer
|
||||||
|
|
||||||
; We always need it in big endian order, so store it as such.
|
; We always need it in big endian order, so store it as such.
|
||||||
mov edi, dh_K
|
mov edi, con.dh_K
|
||||||
mov esi, rx_buffer
|
mov esi, con.rx_buffer
|
||||||
call mpint_to_big_endian
|
call mpint_to_big_endian
|
||||||
mov [dh_K.length], eax
|
mov [con.dh_K_length], eax
|
||||||
|
|
||||||
;-----------------------------------
|
;-----------------------------------
|
||||||
; HASH: mpint K, the shared secret
|
; HASH: mpint K, the shared secret
|
||||||
mov edx, [dh_K.length]
|
mov edx, [con.dh_K_length]
|
||||||
add edx, 4
|
add edx, 4
|
||||||
mov esi, dh_K
|
invoke sha256_update, con.temp_ctx, con.dh_K, edx
|
||||||
call sha256_update
|
|
||||||
|
|
||||||
;-------------------------------
|
;-------------------------------
|
||||||
; Finalize the exchange hash (H)
|
; Finalize the exchange hash (H)
|
||||||
mov edi, dh_H
|
invoke sha256_final, con.temp_ctx
|
||||||
call sha256_final
|
mov esi, con.temp_ctx.hash
|
||||||
|
mov edi, con.dh_H
|
||||||
|
mov ecx, SHA256_HASH_SIZE/4
|
||||||
|
rep movsd
|
||||||
|
|
||||||
DEBUGF 1, "Exchange hash H: "
|
DEBUGF 1, "Exchange hash H: "
|
||||||
stdcall dump_256bit_hex, dh_H
|
stdcall dump_hex, con.dh_H, 8
|
||||||
|
|
||||||
; TODO: skip this block when re-keying
|
; TODO: skip this block when re-keying
|
||||||
mov esi, dh_H
|
mov esi, con.dh_H
|
||||||
mov edi, session_id
|
mov edi, con.session_id
|
||||||
mov ecx, 32/4
|
mov ecx, SHA256_HASH_SIZE/4
|
||||||
rep movsd
|
rep movsd
|
||||||
|
|
||||||
;---------------
|
;---------------
|
||||||
; Calculate keys
|
; Calculate keys
|
||||||
|
|
||||||
; TODO: re-use partial hash of K and H
|
; First, calculate partial hash of K and H so we can re-use it for every key.
|
||||||
|
|
||||||
|
invoke sha256_init, con.k_h_ctx
|
||||||
|
|
||||||
|
mov edx, [con.dh_K_length]
|
||||||
|
add edx, 4
|
||||||
|
invoke sha256_update, con.k_h_ctx, con.dh_K, edx
|
||||||
|
invoke sha256_update, con.k_h_ctx, con.dh_H, 32
|
||||||
|
|
||||||
;---------------------------------------------------------------
|
;---------------------------------------------------------------
|
||||||
; Initial IV client to server: HASH(K || H || "A" || session_id)
|
; Initial IV client to server: HASH(K || H || "A" || session_id)
|
||||||
|
|
||||||
call sha256_init
|
mov esi, con.k_h_ctx
|
||||||
mov edx, [dh_K.length]
|
mov edi, con.temp_ctx
|
||||||
add edx, 4
|
mov ecx, sizeof.ctx_sha224256/4
|
||||||
mov esi, dh_K
|
rep movsd
|
||||||
call sha256_update
|
mov [con.session_id_prefix], 'A'
|
||||||
mov edx, 32
|
invoke sha256_update, con.temp_ctx, con.session_id_prefix, 32+1
|
||||||
mov esi, dh_H
|
invoke sha256_final, con.temp_ctx.hash
|
||||||
call sha256_update
|
mov edi, con.tx_iv
|
||||||
mov edx, 1
|
mov esi, con.temp_ctx
|
||||||
mov esi, str_A
|
mov ecx, SHA256_HASH_SIZE/4
|
||||||
call sha256_update
|
rep movsd
|
||||||
mov edx, 32
|
|
||||||
mov esi, session_id
|
|
||||||
call sha256_update
|
|
||||||
mov edi, tx_iv
|
|
||||||
call sha256_final
|
|
||||||
|
|
||||||
DEBUGF 1, "Remote IV: "
|
DEBUGF 1, "Remote IV: "
|
||||||
stdcall dump_256bit_hex, tx_iv
|
stdcall dump_hex, con.tx_iv, 8
|
||||||
|
|
||||||
;---------------------------------------------------------------
|
;---------------------------------------------------------------
|
||||||
; Initial IV server to client: HASH(K || H || "B" || session_id)
|
; Initial IV server to client: HASH(K || H || "B" || session_id)
|
||||||
|
|
||||||
call sha256_init
|
mov esi, con.k_h_ctx
|
||||||
mov edx, [dh_K.length]
|
mov edi, con.temp_ctx
|
||||||
add edx, 4
|
mov ecx, sizeof.ctx_sha224256/4
|
||||||
mov esi, dh_K
|
rep movsd
|
||||||
call sha256_update
|
inc [con.session_id_prefix]
|
||||||
mov edx, 32
|
invoke sha256_update, con.temp_ctx, con.session_id_prefix, 32+1
|
||||||
mov esi, dh_H
|
invoke sha256_final, con.temp_ctx
|
||||||
call sha256_update
|
mov edi, con.rx_iv
|
||||||
mov edx, 1
|
mov esi, con.temp_ctx
|
||||||
mov esi, str_B
|
mov ecx, SHA256_HASH_SIZE/4
|
||||||
call sha256_update
|
rep movsd
|
||||||
mov edx, 32
|
|
||||||
mov esi, session_id
|
|
||||||
call sha256_update
|
|
||||||
mov edi, rx_iv
|
|
||||||
call sha256_final
|
|
||||||
|
|
||||||
DEBUGF 1, "Local IV: "
|
DEBUGF 1, "Local IV: "
|
||||||
stdcall dump_256bit_hex, rx_iv
|
stdcall dump_hex, con.rx_iv, 8
|
||||||
|
|
||||||
;-------------------------------------------------------------------
|
;-------------------------------------------------------------------
|
||||||
; Encryption key client to server: HASH(K || H || "C" || session_id)
|
; Encryption key client to server: HASH(K || H || "C" || session_id)
|
||||||
|
|
||||||
call sha256_init
|
mov esi, con.k_h_ctx
|
||||||
mov edx, [dh_K.length]
|
mov edi, con.temp_ctx
|
||||||
add edx, 4
|
mov ecx, sizeof.ctx_sha224256/4
|
||||||
mov esi, dh_K
|
rep movsd
|
||||||
call sha256_update
|
inc [con.session_id_prefix]
|
||||||
mov edx, 32
|
invoke sha256_update, con.temp_ctx, con.session_id_prefix, 32+1
|
||||||
mov esi, dh_H
|
invoke sha256_final, con.temp_ctx
|
||||||
call sha256_update
|
mov edi, con.tx_enc_key
|
||||||
mov edx, 1
|
mov esi, con.temp_ctx
|
||||||
mov esi, str_C
|
mov ecx, SHA256_HASH_SIZE/4
|
||||||
call sha256_update
|
rep movsd
|
||||||
mov edx, 32
|
|
||||||
mov esi, session_id
|
|
||||||
call sha256_update
|
|
||||||
mov edi, tx_enc_key
|
|
||||||
call sha256_final
|
|
||||||
|
|
||||||
DEBUGF 1, "Remote key: "
|
DEBUGF 1, "Remote key: "
|
||||||
stdcall dump_256bit_hex, tx_enc_key
|
stdcall dump_hex, con.tx_enc_key, 8
|
||||||
|
|
||||||
;-------------------------------------------------------------------
|
;-------------------------------------------------------------------
|
||||||
; Encryption key server to client: HASH(K || H || "D" || session_id)
|
; Encryption key server to client: HASH(K || H || "D" || session_id)
|
||||||
|
|
||||||
call sha256_init
|
mov esi, con.k_h_ctx
|
||||||
mov edx, [dh_K.length]
|
mov edi, con.temp_ctx
|
||||||
add edx, 4
|
mov ecx, sizeof.ctx_sha224256/4
|
||||||
mov esi, dh_K
|
rep movsd
|
||||||
call sha256_update
|
inc [con.session_id_prefix]
|
||||||
mov edx, 32
|
invoke sha256_update, con.temp_ctx, con.session_id_prefix, 32+1
|
||||||
mov esi, dh_H
|
invoke sha256_final, con.temp_ctx
|
||||||
call sha256_update
|
mov edi, con.rx_enc_key
|
||||||
mov edx, 1
|
mov esi, con.temp_ctx
|
||||||
mov esi, str_D
|
mov ecx, SHA256_HASH_SIZE/4
|
||||||
call sha256_update
|
rep movsd
|
||||||
mov edx, 32
|
|
||||||
mov esi, session_id
|
|
||||||
call sha256_update
|
|
||||||
mov edi, rx_enc_key
|
|
||||||
call sha256_final
|
|
||||||
|
|
||||||
DEBUGF 1, "Local key: "
|
DEBUGF 1, "Local key: "
|
||||||
stdcall dump_256bit_hex, rx_enc_key
|
stdcall dump_hex, con.rx_enc_key, 8
|
||||||
|
|
||||||
;------------------------------------------------------------------
|
;------------------------------------------------------------------
|
||||||
; Integrity key client to server: HASH(K || H || "E" || session_id)
|
; Integrity key client to server: HASH(K || H || "E" || session_id)
|
||||||
|
|
||||||
call sha256_init
|
mov esi, con.k_h_ctx
|
||||||
mov edx, [dh_K.length]
|
mov edi, con.temp_ctx
|
||||||
add edx, 4
|
mov ecx, sizeof.ctx_sha224256/4
|
||||||
mov esi, dh_K
|
rep movsd
|
||||||
call sha256_update
|
inc [con.session_id_prefix]
|
||||||
mov edx, 32
|
invoke sha256_update, con.temp_ctx, con.session_id_prefix, 32+1
|
||||||
mov esi, dh_H
|
invoke sha256_final, con.temp_ctx
|
||||||
call sha256_update
|
mov edi, con.tx_int_key
|
||||||
mov edx, 1
|
mov esi, con.temp_ctx
|
||||||
mov esi, str_E
|
mov ecx, SHA256_HASH_SIZE/4
|
||||||
call sha256_update
|
rep movsd
|
||||||
mov edx, 32
|
|
||||||
mov esi, session_id
|
|
||||||
call sha256_update
|
|
||||||
mov edi, tx_int_key
|
|
||||||
call sha256_final
|
|
||||||
|
|
||||||
DEBUGF 1, "Remote Integrity key: "
|
DEBUGF 1, "Remote Integrity key: "
|
||||||
stdcall dump_256bit_hex, tx_int_key
|
stdcall dump_hex, con.tx_int_key, 8
|
||||||
|
|
||||||
;------------------------------------------------------------------
|
;------------------------------------------------------------------
|
||||||
; Integrity key server to client: HASH(K || H || "F" || session_id)
|
; Integrity key server to client: HASH(K || H || "F" || session_id)
|
||||||
|
|
||||||
call sha256_init
|
mov esi, con.k_h_ctx
|
||||||
mov edx, [dh_K.length]
|
mov edi, con.temp_ctx
|
||||||
add edx, 4
|
mov ecx, sizeof.ctx_sha224256/4
|
||||||
mov esi, dh_K
|
rep movsd
|
||||||
call sha256_update
|
inc [con.session_id_prefix]
|
||||||
mov edx, 32
|
invoke sha256_update, con.temp_ctx, con.session_id_prefix, 32+1
|
||||||
mov esi, dh_H
|
invoke sha256_final, con.temp_ctx
|
||||||
call sha256_update
|
mov edi, con.rx_int_key
|
||||||
mov edx, 1
|
mov esi, con.temp_ctx
|
||||||
mov esi, str_F
|
mov ecx, SHA256_HASH_SIZE/4
|
||||||
call sha256_update
|
rep movsd
|
||||||
mov edx, 32
|
|
||||||
mov esi, session_id
|
|
||||||
call sha256_update
|
|
||||||
mov edi, rx_int_key
|
|
||||||
call sha256_final
|
|
||||||
|
|
||||||
DEBUGF 1, "Local Integrity key: "
|
DEBUGF 1, "Local Integrity key: "
|
||||||
stdcall dump_256bit_hex, rx_int_key
|
stdcall dump_hex, con.rx_int_key, 8
|
||||||
|
|
||||||
;-------------------------------------
|
;-------------------------------------
|
||||||
; << Parse Diffie-Hellman New Keys MSG
|
; << Parse Diffie-Hellman New Keys MSG
|
||||||
|
|
||||||
stdcall ssh_recv_packet, [socketnum], rx_buffer, BUFFERSIZE, 0
|
stdcall ssh_recv_packet, con, 0
|
||||||
cmp eax, -1
|
cmp eax, -1
|
||||||
je .socket_err
|
je .socket_err
|
||||||
|
|
||||||
cmp [rx_buffer+ssh_header.message_code], SSH_MSG_NEWKEYS
|
cmp [con.rx_buffer.message_code], SSH_MSG_NEWKEYS
|
||||||
jne .proto_err
|
jne .proto_err
|
||||||
|
|
||||||
DEBUGF 1, "Received New Keys\n"
|
DEBUGF 2, "Received New Keys\n"
|
||||||
|
|
||||||
;-------------------------------
|
;-------------------------------
|
||||||
; >> Reply with New Keys message
|
; >> Reply with New Keys message
|
||||||
|
|
||||||
stdcall ssh_send_packet, [socketnum], ssh_new_keys, ssh_new_keys.length, 0
|
stdcall ssh_send_packet, con, ssh_new_keys, ssh_new_keys.length, 0
|
||||||
|
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.socket_err:
|
.socket_err:
|
||||||
DEBUGF 2, "Socket error during key exchange!\n"
|
DEBUGF 3, "Socket error during key exchange!\n"
|
||||||
mov eax, 1
|
mov eax, 1
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.proto_err:
|
.proto_err:
|
||||||
DEBUGF 2, "Protocol error during key exchange!\n"
|
DEBUGF 3, "Protocol error during key exchange!\n"
|
||||||
mov eax, 2
|
mov eax, 2
|
||||||
ret
|
ret
|
||||||
|
|
||||||
endp
|
endp
|
||||||
|
|
||||||
proc dump_256bit_hex _ptr
|
|
||||||
pushad
|
|
||||||
|
|
||||||
mov esi, [_ptr]
|
|
||||||
mov ecx, 8
|
|
||||||
.next_dword:
|
|
||||||
lodsd
|
|
||||||
bswap eax
|
|
||||||
DEBUGF 1,'%x',eax
|
|
||||||
loop .next_dword
|
|
||||||
DEBUGF 1,'\n'
|
|
||||||
|
|
||||||
popad
|
|
||||||
ret
|
|
||||||
endp
|
|
||||||
|
|
||||||
iglobal
|
|
||||||
|
|
||||||
str_A db 'A'
|
|
||||||
str_B db 'B'
|
|
||||||
str_C db 'C'
|
|
||||||
str_D db 'D'
|
|
||||||
str_E db 'E'
|
|
||||||
str_F db 'F'
|
|
||||||
|
|
||||||
endg
|
|
171
programs/network/ssh/hmac_sha256.inc
Normal file
171
programs/network/ssh/hmac_sha256.inc
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
; 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_sha256_context
|
||||||
|
hash rb SHA256_HASH_SIZE
|
||||||
|
ipad_ctx ctx_sha224256
|
||||||
|
opad_ctx ctx_sha224256
|
||||||
|
ends
|
||||||
|
|
||||||
|
; We will precompute partial hashes of K XOR ipad and K XOR opad,
|
||||||
|
; and store them in the context structure.
|
||||||
|
|
||||||
|
proc hmac_sha256_setkey ctx, key, key_length
|
||||||
|
|
||||||
|
locals
|
||||||
|
k_temp rb SHA224256_BLOCK_SIZE
|
||||||
|
endl
|
||||||
|
|
||||||
|
pusha
|
||||||
|
|
||||||
|
; input esi = key, ecx=key_length
|
||||||
|
mov ecx, [key_length]
|
||||||
|
cmp ecx, SHA224256_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, SHA224256_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 sha256_init, [ctx]
|
||||||
|
invoke sha256_update, [ctx], [key], [key_length]
|
||||||
|
invoke sha256_final, [ctx]
|
||||||
|
mov esi, [ctx]
|
||||||
|
lea edi, [k_temp]
|
||||||
|
mov ecx, SHA256_HASH_SIZE/4
|
||||||
|
rep movsd
|
||||||
|
xor eax, eax
|
||||||
|
mov ecx, (SHA224256_BLOCK_SIZE-SHA256_HASH_SIZE)/4
|
||||||
|
rep stosd
|
||||||
|
|
||||||
|
.finish:
|
||||||
|
; xor ipad buffer with 0x36363...
|
||||||
|
lea esi, [k_temp]
|
||||||
|
mov ecx, SHA224256_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_sha256_context.ipad_ctx]
|
||||||
|
invoke sha256_init, edi
|
||||||
|
|
||||||
|
lea esi, [k_temp]
|
||||||
|
DEBUGF 1, "HASH: "
|
||||||
|
stdcall dump_hex, esi, SHA224256_BLOCK_SIZE/4
|
||||||
|
|
||||||
|
mov ebx, [ctx]
|
||||||
|
lea edi, [ebx+hmac_sha256_context.ipad_ctx]
|
||||||
|
invoke sha256_update, edi, esi, SHA224256_BLOCK_SIZE
|
||||||
|
|
||||||
|
; xor opad buffer with 0x5c5c5...
|
||||||
|
lea esi, [k_temp]
|
||||||
|
mov ecx, SHA224256_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_sha256_context.opad_ctx]
|
||||||
|
invoke sha256_init, edi
|
||||||
|
|
||||||
|
lea esi, [k_temp]
|
||||||
|
DEBUGF 1, "HASH: "
|
||||||
|
stdcall dump_hex, esi, SHA224256_BLOCK_SIZE/4
|
||||||
|
|
||||||
|
mov ebx, [ctx]
|
||||||
|
lea edi, [ebx+hmac_sha256_context.opad_ctx]
|
||||||
|
invoke sha256_update, edi, esi, SHA224256_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_sha256 ctx, _data, _length
|
||||||
|
|
||||||
|
locals
|
||||||
|
inner_ctx ctx_sha224256
|
||||||
|
outer_ctx ctx_sha224256
|
||||||
|
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_sha256_context.ipad_ctx]
|
||||||
|
lea edi, [inner_ctx]
|
||||||
|
repeat (sizeof.ctx_sha224256)/4*2
|
||||||
|
movsd
|
||||||
|
end repeat
|
||||||
|
|
||||||
|
; Append provided data to inner hash and finalize
|
||||||
|
lea ebx, [inner_ctx]
|
||||||
|
invoke sha256_update, ebx, [_data], [_length]
|
||||||
|
lea ebx, [inner_ctx]
|
||||||
|
invoke sha256_final, ebx
|
||||||
|
|
||||||
|
DEBUGF 1, "Inner Hash: "
|
||||||
|
lea esi, [inner_ctx.hash]
|
||||||
|
stdcall dump_hex, esi, SHA256_HASH_SIZE/4
|
||||||
|
|
||||||
|
; Calculate outer hash
|
||||||
|
lea ebx, [outer_ctx]
|
||||||
|
lea esi, [inner_ctx.hash]
|
||||||
|
invoke sha256_update, ebx, esi, SHA256_HASH_SIZE
|
||||||
|
lea ebx, [outer_ctx]
|
||||||
|
invoke sha256_final, ebx
|
||||||
|
; Copy output hash to ctx structure ; FIXME
|
||||||
|
lea esi, [outer_ctx.hash]
|
||||||
|
mov edi, [ctx]
|
||||||
|
repeat SHA256_HASH_SIZE/4
|
||||||
|
movsd
|
||||||
|
end repeat
|
||||||
|
|
||||||
|
popa
|
||||||
|
ret
|
||||||
|
|
||||||
|
endp
|
@ -541,13 +541,13 @@ proc mpint_modexp uses edi eax ebx ecx, dst, base, exp, mod
|
|||||||
ret
|
ret
|
||||||
|
|
||||||
.mod_zero:
|
.mod_zero:
|
||||||
DEBUGF 1, "modexp with modulo 0\n"
|
DEBUGF 3, "modexp with modulo 0\n"
|
||||||
; if mod is zero, result = 0
|
; if mod is zero, result = 0
|
||||||
stdcall mpint_zero, [dst]
|
stdcall mpint_zero, [dst]
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.exp_zero:
|
.exp_zero:
|
||||||
DEBUGF 1, "modexp with exponent 0\n"
|
DEBUGF 3, "modexp with exponent 0\n"
|
||||||
; if exponent is zero, result = 1
|
; if exponent is zero, result = 1
|
||||||
stdcall mpint_zero, [dst]
|
stdcall mpint_zero, [dst]
|
||||||
mov eax, [dst]
|
mov eax, [dst]
|
||||||
@ -556,7 +556,7 @@ proc mpint_modexp uses edi eax ebx ecx, dst, base, exp, mod
|
|||||||
ret
|
ret
|
||||||
|
|
||||||
.invalid:
|
.invalid:
|
||||||
DEBUGF 1, "modexp: Invalid input!\n"
|
DEBUGF 3, "modexp: Invalid input!\n"
|
||||||
ret
|
ret
|
||||||
|
|
||||||
endp
|
endp
|
@ -18,7 +18,7 @@
|
|||||||
format binary as ""
|
format binary as ""
|
||||||
|
|
||||||
__DEBUG__ = 1
|
__DEBUG__ = 1
|
||||||
__DEBUG_LEVEL__ = 1
|
__DEBUG_LEVEL__ = 2 ; 1: Extreme debugging, 2: Debugging, 3: Errors only
|
||||||
|
|
||||||
BUFFERSIZE = 4096
|
BUFFERSIZE = 4096
|
||||||
MAX_BITS = 8192
|
MAX_BITS = 8192
|
||||||
@ -33,16 +33,17 @@ use32
|
|||||||
dd i_end ; initialized size
|
dd i_end ; initialized size
|
||||||
dd mem+4096 ; required memory
|
dd mem+4096 ; required memory
|
||||||
dd mem+4096 ; stack pointer
|
dd mem+4096 ; stack pointer
|
||||||
dd hostname ; parameters
|
dd params ; parameters
|
||||||
dd 0 ; path
|
dd 0 ; path
|
||||||
|
|
||||||
include '../../macros.inc'
|
include '../../macros.inc'
|
||||||
|
;include '../../struct.inc'
|
||||||
purge mov,add,sub
|
purge mov,add,sub
|
||||||
include '../../proc32.inc'
|
include '../../proc32.inc'
|
||||||
include '../../dll.inc'
|
include '../../dll.inc'
|
||||||
include '../../debug-fdo.inc'
|
include '../../debug-fdo.inc'
|
||||||
include '../../network.inc'
|
include '../../network.inc'
|
||||||
;include '../../develop/libraries/libcrash/trunk/libcrash.inc'
|
include '../../develop/libraries/libcrash/trunk/libcrash.inc'
|
||||||
|
|
||||||
include 'mcodes.inc'
|
include 'mcodes.inc'
|
||||||
include 'ssh_transport.inc'
|
include 'ssh_transport.inc'
|
||||||
@ -53,7 +54,7 @@ include 'random.inc'
|
|||||||
include 'aes256.inc'
|
include 'aes256.inc'
|
||||||
include 'aes256-ctr.inc'
|
include 'aes256-ctr.inc'
|
||||||
include 'aes256-cbc.inc'
|
include 'aes256-cbc.inc'
|
||||||
include '../../fs/kfar/trunk/kfar_arc/sha256.inc'
|
include 'hmac_sha256.inc'
|
||||||
|
|
||||||
; macros for network byte order
|
; macros for network byte order
|
||||||
macro dd_n op {
|
macro dd_n op {
|
||||||
@ -68,24 +69,120 @@ macro dw_n op {
|
|||||||
(((op) and 000FFh) shl 8)
|
(((op) and 000FFh) shl 8)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
proc dump_hex _ptr, _length
|
||||||
|
if __DEBUG_LEVEL__ <= 1
|
||||||
|
pushad
|
||||||
|
|
||||||
|
mov esi, [_ptr]
|
||||||
|
mov ecx, [_length]
|
||||||
|
.next_dword:
|
||||||
|
lodsd
|
||||||
|
bswap eax
|
||||||
|
DEBUGF 1,'%x',eax
|
||||||
|
loop .next_dword
|
||||||
|
DEBUGF 1,'\n'
|
||||||
|
|
||||||
|
popad
|
||||||
|
ret
|
||||||
|
end if
|
||||||
|
endp
|
||||||
|
|
||||||
|
struct ssh_connection
|
||||||
|
|
||||||
|
; Connection
|
||||||
|
|
||||||
|
hostname rb 1024
|
||||||
|
|
||||||
|
socketnum dd ?
|
||||||
|
|
||||||
|
sockaddr dw ? ; Address family
|
||||||
|
port dw ?
|
||||||
|
ip dd ?
|
||||||
|
rb 10
|
||||||
|
|
||||||
|
; Encryption/Decryption
|
||||||
|
|
||||||
|
rx_crypt_proc dd ?
|
||||||
|
tx_crypt_proc dd ?
|
||||||
|
rx_crypt_ctx_ptr dd ?
|
||||||
|
tx_crypt_ctx_ptr dd ?
|
||||||
|
rx_crypt_blocksize dd ?
|
||||||
|
tx_crypt_blocksize dd ?
|
||||||
|
|
||||||
|
; Message authentication
|
||||||
|
|
||||||
|
rx_mac_proc dd ?
|
||||||
|
tx_mac_proc dd ?
|
||||||
|
rx_mac_ctx hmac_sha256_context
|
||||||
|
tx_mac_ctx hmac_sha256_context
|
||||||
|
rx_mac_length dd ?
|
||||||
|
tx_mac_length dd ?
|
||||||
|
|
||||||
|
; Buffers
|
||||||
|
|
||||||
|
rx_seq dd ? ; Packet sequence number for MAC
|
||||||
|
rx_buffer ssh_packet_header
|
||||||
|
rb BUFFERSIZE-sizeof.ssh_packet_header
|
||||||
|
|
||||||
|
tx_seq dd ? ; Packet sequence number for MAC
|
||||||
|
tx_buffer ssh_packet_header
|
||||||
|
rb BUFFERSIZE-sizeof.ssh_packet_header
|
||||||
|
|
||||||
|
send_data dw ?
|
||||||
|
|
||||||
|
; Output from key exchange
|
||||||
|
dh_K dd ? ; Shared Secret (Big endian)
|
||||||
|
rb MAX_BITS/8
|
||||||
|
dh_K_length dd ? ; Length in little endian
|
||||||
|
|
||||||
|
dh_H rb 32 ; Exchange Hash
|
||||||
|
session_id_prefix db ?
|
||||||
|
session_id rb 32
|
||||||
|
rx_iv rb 32 ; Rx initialisation vector
|
||||||
|
tx_iv rb 32 ; Tx initialisation vector
|
||||||
|
rx_enc_key rb 32 ; Rx encryption key
|
||||||
|
tx_enc_key rb 32 ; Tx encryption key
|
||||||
|
rx_int_key rb 32 ; Rx integrity key
|
||||||
|
tx_int_key rb 32 ; Tx integrity key
|
||||||
|
|
||||||
|
; Diffie Hellman
|
||||||
|
dh_p dd ?
|
||||||
|
rb MAX_BITS/8
|
||||||
|
dh_g dd ?
|
||||||
|
rb MAX_BITS/8
|
||||||
|
dh_x dd ?
|
||||||
|
rb MAX_BITS/8
|
||||||
|
dh_e dd ?
|
||||||
|
rb MAX_BITS/8
|
||||||
|
dh_f dd ?
|
||||||
|
rb MAX_BITS/8
|
||||||
|
|
||||||
|
dh_signature dd ?
|
||||||
|
rb MAX_BITS/8
|
||||||
|
|
||||||
|
temp_ctx ctx_sha224256
|
||||||
|
k_h_ctx ctx_sha224256
|
||||||
|
|
||||||
|
ends
|
||||||
|
|
||||||
start:
|
start:
|
||||||
mcall 68, 11 ; Init heap
|
mcall 68, 11 ; Init heap
|
||||||
|
|
||||||
DEBUGF 1, "SSH: Loading libraries\n"
|
DEBUGF 2, "SSH: Loading libraries\n"
|
||||||
stdcall dll.Load, @IMPORT
|
stdcall dll.Load, @IMPORT
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jnz exit
|
jnz exit
|
||||||
|
|
||||||
DEBUGF 1, "SSH: Init PRNG\n"
|
DEBUGF 2, "SSH: Init PRNG\n"
|
||||||
call init_random
|
call init_random
|
||||||
|
|
||||||
DEBUGF 1, "SSH: Init Console\n"
|
DEBUGF 2, "SSH: Init Console\n"
|
||||||
invoke con_start, 1
|
invoke con_start, 1
|
||||||
invoke con_init, 80, 25, 80, 25, title
|
invoke con_init, 80, 25, 80, 25, title
|
||||||
|
|
||||||
; Check for parameters
|
; Check for parameters TODO
|
||||||
cmp byte[hostname], 0
|
; cmp byte[params], 0
|
||||||
jne resolve
|
; jne resolve
|
||||||
|
|
||||||
main:
|
main:
|
||||||
invoke con_cls
|
invoke con_cls
|
||||||
@ -96,7 +193,7 @@ prompt:
|
|||||||
; write prompt
|
; write prompt
|
||||||
invoke con_write_asciiz, str2
|
invoke con_write_asciiz, str2
|
||||||
; read string
|
; read string
|
||||||
mov esi, hostname
|
mov esi, con.hostname
|
||||||
invoke con_gets, esi, 256
|
invoke con_gets, esi, 256
|
||||||
; check for exit
|
; check for exit
|
||||||
test eax, eax
|
test eax, eax
|
||||||
@ -105,10 +202,11 @@ prompt:
|
|||||||
jz done
|
jz done
|
||||||
|
|
||||||
resolve:
|
resolve:
|
||||||
mov [sockaddr1.port], 22 shl 8
|
mov [con.sockaddr], AF_INET4
|
||||||
|
mov [con.port], 22 shl 8
|
||||||
|
|
||||||
; delete terminating '\n'
|
; delete terminating '\n'
|
||||||
mov esi, hostname
|
mov esi, con.hostname
|
||||||
@@:
|
@@:
|
||||||
lodsb
|
lodsb
|
||||||
cmp al, ':'
|
cmp al, ':'
|
||||||
@ -130,21 +228,21 @@ resolve:
|
|||||||
jb hostname_error
|
jb hostname_error
|
||||||
cmp al, 9
|
cmp al, 9
|
||||||
ja hostname_error
|
ja hostname_error
|
||||||
lea ebx, [ebx*4 + ebx]
|
lea ebx, [ebx*4+ebx]
|
||||||
shl ebx, 1
|
shl ebx, 1
|
||||||
add ebx, eax
|
add ebx, eax
|
||||||
jmp .portloop
|
jmp .portloop
|
||||||
|
|
||||||
.port_done:
|
.port_done:
|
||||||
xchg bl, bh
|
xchg bl, bh
|
||||||
mov [sockaddr1.port], bx
|
mov [con.port], bx
|
||||||
|
|
||||||
.done:
|
.done:
|
||||||
|
|
||||||
; resolve name
|
; resolve name
|
||||||
push esp ; reserve stack place
|
push esp ; reserve stack place
|
||||||
push esp
|
push esp
|
||||||
invoke getaddrinfo, hostname, 0, 0
|
invoke getaddrinfo, con.hostname, 0, 0
|
||||||
pop esi
|
pop esi
|
||||||
; test for error
|
; test for error
|
||||||
test eax, eax
|
test eax, eax
|
||||||
@ -152,7 +250,7 @@ resolve:
|
|||||||
|
|
||||||
invoke con_cls
|
invoke con_cls
|
||||||
invoke con_write_asciiz, str3
|
invoke con_write_asciiz, str3
|
||||||
invoke con_write_asciiz, hostname
|
invoke con_write_asciiz, con.hostname
|
||||||
|
|
||||||
; write results
|
; write results
|
||||||
invoke con_write_asciiz, str8
|
invoke con_write_asciiz, str8
|
||||||
@ -160,7 +258,7 @@ resolve:
|
|||||||
; convert IP address to decimal notation
|
; convert IP address to decimal notation
|
||||||
mov eax, [esi+addrinfo.ai_addr]
|
mov eax, [esi+addrinfo.ai_addr]
|
||||||
mov eax, [eax+sockaddr_in.sin_addr]
|
mov eax, [eax+sockaddr_in.sin_addr]
|
||||||
mov [sockaddr1.ip], eax
|
mov [con.ip], eax
|
||||||
invoke inet_ntoa, eax
|
invoke inet_ntoa, eax
|
||||||
; write result
|
; write result
|
||||||
invoke con_write_asciiz, eax
|
invoke con_write_asciiz, eax
|
||||||
@ -176,47 +274,56 @@ resolve:
|
|||||||
mcall socket, AF_INET4, SOCK_STREAM, 0
|
mcall socket, AF_INET4, SOCK_STREAM, 0
|
||||||
cmp eax, -1
|
cmp eax, -1
|
||||||
jz socket_err
|
jz socket_err
|
||||||
mov [socketnum], eax
|
mov [con.socketnum], eax
|
||||||
|
|
||||||
; Connect
|
; Connect
|
||||||
mcall connect, [socketnum], sockaddr1, 18
|
DEBUGF 2, "Connecting to server\n"
|
||||||
|
mcall connect, [con.socketnum], con.sockaddr, 18
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jnz socket_err
|
jnz socket_err
|
||||||
|
|
||||||
; Start calculating hash meanwhile
|
; Start calculating hash
|
||||||
call sha256_init
|
invoke sha256_init, con.temp_ctx
|
||||||
; HASH: string V_C, the client's version string (CR and NL excluded)
|
; HASH: string V_C, the client's version string (CR and NL excluded)
|
||||||
mov esi, ssh_ident_ha
|
invoke sha256_update, con.temp_ctx, ssh_ident_ha, ssh_ident.length+4-2
|
||||||
mov edx, ssh_ident.length+4-2
|
|
||||||
call sha256_update
|
|
||||||
|
|
||||||
; Send our identification string
|
; >> Send our identification string
|
||||||
DEBUGF 1, "Sending ID string\n"
|
DEBUGF 2, "Sending ID string\n"
|
||||||
mcall send, [socketnum], ssh_ident, ssh_ident.length, 0
|
mcall send, [con.socketnum], ssh_ident, ssh_ident.length, 0
|
||||||
cmp eax, -1
|
cmp eax, -1
|
||||||
je socket_err
|
je socket_err
|
||||||
|
|
||||||
; Check protocol version of server
|
; << Check protocol version of server
|
||||||
mcall recv, [socketnum], rx_buffer, BUFFERSIZE, 0
|
mcall recv, [con.socketnum], con.rx_buffer, BUFFERSIZE, 0
|
||||||
cmp eax, -1
|
cmp eax, -1
|
||||||
je socket_err
|
je socket_err
|
||||||
|
|
||||||
DEBUGF 1, "Received ID string\n"
|
DEBUGF 2, "Received ID string\n"
|
||||||
cmp dword[rx_buffer], "SSH-"
|
cmp dword[con.rx_buffer], "SSH-"
|
||||||
jne proto_err
|
jne proto_err
|
||||||
cmp dword[rx_buffer+4], "2.0-"
|
cmp dword[con.rx_buffer+4], "2.0-"
|
||||||
jne proto_err
|
jne proto_err
|
||||||
|
|
||||||
; HASH: string V_S, the server's version string (CR and NL excluded)
|
; HASH: string V_S, the server's version string (CR and NL excluded)
|
||||||
lea edx, [eax+2]
|
lea edx, [eax+2]
|
||||||
sub eax, 2
|
sub eax, 2
|
||||||
bswap eax
|
bswap eax
|
||||||
mov [rx_buffer-4], eax
|
mov dword[con.rx_buffer-4], eax
|
||||||
mov esi, rx_buffer-4
|
invoke sha256_update, con.temp_ctx, con.rx_buffer-4, edx
|
||||||
call sha256_update
|
|
||||||
|
|
||||||
; Key Exchange init
|
; >> Key Exchange init
|
||||||
DEBUGF 1, "Sending KEX init\n"
|
mov [con.rx_seq], 0
|
||||||
|
mov [con.tx_seq], 0
|
||||||
|
mov [con.rx_crypt_blocksize], 4 ; minimum blocksize
|
||||||
|
mov [con.tx_crypt_blocksize], 4
|
||||||
|
mov [con.rx_crypt_proc], 0
|
||||||
|
mov [con.tx_crypt_proc], 0
|
||||||
|
mov [con.rx_mac_proc], 0
|
||||||
|
mov [con.tx_mac_proc], 0
|
||||||
|
mov [con.rx_mac_length], 0
|
||||||
|
mov [con.tx_mac_length], 0
|
||||||
|
|
||||||
|
DEBUGF 2, "Sending KEX init\n"
|
||||||
mov edi, ssh_kex.cookie
|
mov edi, ssh_kex.cookie
|
||||||
call MBRandom
|
call MBRandom
|
||||||
stosd
|
stosd
|
||||||
@ -226,32 +333,31 @@ resolve:
|
|||||||
stosd
|
stosd
|
||||||
call MBRandom
|
call MBRandom
|
||||||
stosd
|
stosd
|
||||||
stdcall ssh_send_packet, [socketnum], ssh_kex, ssh_kex.length, 0
|
stdcall ssh_send_packet, con, ssh_kex, ssh_kex.length, 0
|
||||||
cmp eax, -1
|
cmp eax, -1
|
||||||
je socket_err
|
je socket_err
|
||||||
|
|
||||||
; HASH: string I_C, the payload of the client's SSH_MSG_KEXINIT
|
; HASH: string I_C, the payload of the client's SSH_MSG_KEXINIT
|
||||||
mov eax, [tx_buffer+ssh_header.length]
|
mov eax, dword[con.tx_buffer+ssh_packet_header.packet_length]
|
||||||
bswap eax
|
bswap eax
|
||||||
movzx ebx, [tx_buffer+ssh_header.padding]
|
movzx ebx, [con.tx_buffer+ssh_packet_header.padding_length]
|
||||||
sub eax, ebx
|
sub eax, ebx
|
||||||
dec eax
|
dec eax
|
||||||
lea edx, [eax+4]
|
lea edx, [eax+4]
|
||||||
bswap eax
|
bswap eax
|
||||||
mov [tx_buffer+1], eax
|
mov dword[con.tx_buffer+1], eax
|
||||||
mov esi, tx_buffer+1
|
invoke sha256_update, con.temp_ctx, con.tx_buffer+1, edx
|
||||||
call sha256_update
|
|
||||||
|
|
||||||
; Check key exchange init of server
|
; << Check key exchange init of server
|
||||||
stdcall ssh_recv_packet, [socketnum], rx_buffer, BUFFERSIZE, 0
|
stdcall ssh_recv_packet, con, 0
|
||||||
cmp eax, -1
|
cmp eax, -1
|
||||||
je socket_err
|
je socket_err
|
||||||
|
|
||||||
cmp [rx_buffer+ssh_header.message_code], SSH_MSG_KEXINIT
|
cmp [con.rx_buffer.message_code], SSH_MSG_KEXINIT
|
||||||
jne proto_err
|
jne proto_err
|
||||||
DEBUGF 1, "Received KEX init\n"
|
DEBUGF 2, "Received KEX init\n"
|
||||||
|
|
||||||
lea esi, [rx_buffer+sizeof.ssh_header+16]
|
lea esi, [con.rx_buffer+sizeof.ssh_packet_header+16]
|
||||||
lodsd
|
lodsd
|
||||||
bswap eax
|
bswap eax
|
||||||
DEBUGF 1, "kex_algorithms: %s\n", esi
|
DEBUGF 1, "kex_algorithms: %s\n", esi
|
||||||
@ -295,38 +401,144 @@ resolve:
|
|||||||
lodsb
|
lodsb
|
||||||
DEBUGF 1, "KEX First Packet Follows: %u\n", al
|
DEBUGF 1, "KEX First Packet Follows: %u\n", al
|
||||||
|
|
||||||
; TODO
|
; TODO: parse this structure and init procedures accordingly
|
||||||
|
|
||||||
; HASH: string I_S, the payload of the servers's SSH_MSG_KEXINIT
|
; HASH: string I_S, the payload of the servers's SSH_MSG_KEXINIT
|
||||||
mov eax, [rx_buffer+ssh_header.length]
|
mov eax, dword[con.rx_buffer+ssh_packet_header.packet_length]
|
||||||
movzx ebx, [rx_buffer+ssh_header.padding]
|
movzx ebx, [con.rx_buffer+ssh_packet_header.padding_length]
|
||||||
sub eax, ebx
|
sub eax, ebx
|
||||||
dec eax
|
dec eax
|
||||||
lea edx, [eax+4]
|
lea edx, [eax+4]
|
||||||
bswap eax
|
bswap eax
|
||||||
mov [rx_buffer+sizeof.ssh_header-5], eax
|
mov dword[con.rx_buffer+sizeof.ssh_packet_header-5], eax
|
||||||
mov esi, rx_buffer+sizeof.ssh_header-5
|
invoke sha256_update, con.temp_ctx, con.rx_buffer+sizeof.ssh_packet_header-5, edx
|
||||||
call sha256_update
|
|
||||||
|
|
||||||
; Exchange keys with the server
|
; Exchange keys with the server
|
||||||
|
|
||||||
stdcall dh_gex
|
stdcall dh_gex
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jnz exit
|
jnz exit
|
||||||
|
|
||||||
; Set keys
|
; Set keys
|
||||||
DEBUGF 1, "SSH: Init encryption\n"
|
|
||||||
stdcall aes256_cbc_init, rx_iv
|
|
||||||
mov [rx_context], eax
|
|
||||||
stdcall aes256_set_encrypt_key, [rx_context], rx_enc_key
|
|
||||||
mov [decrypt_proc], aes256_cbc_decrypt
|
|
||||||
mov [rx_blocksize], 32
|
|
||||||
|
|
||||||
DEBUGF 1, "SSH: Init decryption\n"
|
DEBUGF 2, "SSH: Setting encryption keys\n"
|
||||||
stdcall aes256_cbc_init, tx_iv
|
|
||||||
mov [tx_context], eax
|
stdcall aes256_cbc_init, con.rx_iv
|
||||||
stdcall aes256_set_decrypt_key, [tx_context], tx_enc_key
|
mov [con.rx_crypt_ctx_ptr], eax
|
||||||
mov [encrypt_proc], aes256_cbc_encrypt
|
|
||||||
mov [tx_blocksize], 32
|
stdcall aes256_set_decrypt_key, eax, con.rx_enc_key
|
||||||
|
mov [con.rx_crypt_proc], aes256_cbc_decrypt
|
||||||
|
mov [con.rx_crypt_blocksize], AES256_BLOCKSIZE
|
||||||
|
|
||||||
|
stdcall aes256_cbc_init, con.tx_iv
|
||||||
|
mov [con.tx_crypt_ctx_ptr], eax
|
||||||
|
|
||||||
|
stdcall aes256_set_encrypt_key, eax, con.tx_enc_key
|
||||||
|
mov [con.tx_crypt_proc], aes256_cbc_encrypt
|
||||||
|
mov [con.tx_crypt_blocksize], AES256_BLOCKSIZE
|
||||||
|
|
||||||
|
stdcall hmac_sha256_setkey, con.rx_mac_ctx, con.rx_int_key, SHA256_HASH_SIZE
|
||||||
|
mov [con.rx_mac_proc], hmac_sha256
|
||||||
|
mov [con.rx_mac_length], SHA256_HASH_SIZE
|
||||||
|
|
||||||
|
stdcall hmac_sha256_setkey, con.tx_mac_ctx, con.tx_int_key, SHA256_HASH_SIZE
|
||||||
|
mov [con.tx_mac_proc], hmac_sha256
|
||||||
|
mov [con.tx_mac_length], SHA256_HASH_SIZE
|
||||||
|
|
||||||
|
; TODO: erase all keys from memory and free the memory
|
||||||
|
|
||||||
|
; >> Request service (user-auth)
|
||||||
|
|
||||||
|
DEBUGF 2, "SSH: Requesting service\n"
|
||||||
|
|
||||||
|
stdcall ssh_send_packet, con, ssh_request_service, ssh_request_service.length, 0
|
||||||
|
cmp eax, -1
|
||||||
|
je socket_err
|
||||||
|
|
||||||
|
; << Check for service acceptance
|
||||||
|
|
||||||
|
stdcall ssh_recv_packet, con, 0
|
||||||
|
cmp eax, -1
|
||||||
|
je socket_err
|
||||||
|
|
||||||
|
cmp [con.rx_buffer.message_code], SSH_MSG_SERVICE_ACCEPT
|
||||||
|
jne proto_err
|
||||||
|
|
||||||
|
; >> Request user authentication
|
||||||
|
|
||||||
|
; TODO: Request username from the user
|
||||||
|
; invoke con_write_asciiz, str12
|
||||||
|
; invoke con_gets, username, 256
|
||||||
|
; test eax, eax
|
||||||
|
; jz done
|
||||||
|
|
||||||
|
; TODO: implement password authentication
|
||||||
|
|
||||||
|
DEBUGF 2, "SSH: User authentication\n"
|
||||||
|
|
||||||
|
stdcall ssh_send_packet, con, ssh_request_userauth, ssh_request_userauth.length, 0
|
||||||
|
cmp eax, -1
|
||||||
|
je socket_err
|
||||||
|
|
||||||
|
; << Check for userauth acceptance
|
||||||
|
|
||||||
|
stdcall ssh_recv_packet, con, 0
|
||||||
|
cmp eax, -1
|
||||||
|
je socket_err
|
||||||
|
|
||||||
|
cmp [con.rx_buffer.message_code], SSH_MSG_USERAUTH_SUCCESS
|
||||||
|
jne proto_err
|
||||||
|
|
||||||
|
; >> Open channel
|
||||||
|
|
||||||
|
DEBUGF 2, "SSH: Open channel\n"
|
||||||
|
|
||||||
|
stdcall ssh_send_packet, con, ssh_channel_open, ssh_channel_open.length, 0
|
||||||
|
cmp eax, -1
|
||||||
|
je socket_err
|
||||||
|
|
||||||
|
; << Check for channel open confirmation
|
||||||
|
|
||||||
|
stdcall ssh_recv_packet, con, 0
|
||||||
|
cmp eax, -1
|
||||||
|
je socket_err
|
||||||
|
|
||||||
|
cmp [con.rx_buffer.message_code], SSH_MSG_CHANNEL_OPEN_CONFIRMATION
|
||||||
|
jne proto_err
|
||||||
|
|
||||||
|
; >> Channel request: pty
|
||||||
|
|
||||||
|
DEBUGF 2, "SSH: Request pty\n"
|
||||||
|
|
||||||
|
stdcall ssh_send_packet, con, ssh_channel_request, ssh_channel_request.length, 0
|
||||||
|
cmp eax, -1
|
||||||
|
je socket_err
|
||||||
|
|
||||||
|
; << Check for channel request confirmation
|
||||||
|
|
||||||
|
stdcall ssh_recv_packet, con, 0
|
||||||
|
cmp eax, -1
|
||||||
|
je socket_err
|
||||||
|
|
||||||
|
cmp [con.rx_buffer.message_code], SSH_MSG_CHANNEL_SUCCESS
|
||||||
|
jne proto_err
|
||||||
|
|
||||||
|
; >> Channel request: shell
|
||||||
|
|
||||||
|
DEBUGF 2, "SSH: Request shell\n"
|
||||||
|
|
||||||
|
stdcall ssh_send_packet, con, ssh_shell_request, ssh_shell_request.length, 0
|
||||||
|
cmp eax, -1
|
||||||
|
je socket_err
|
||||||
|
|
||||||
|
; << Check for channel request confirmation (FIXME: this may not be first packet!)
|
||||||
|
|
||||||
|
; stdcall ssh_recv_packet, con, 0
|
||||||
|
; cmp eax, -1
|
||||||
|
; je socket_err
|
||||||
|
|
||||||
|
; cmp [con.rx_buffer.message_code], SSH_MSG_CHANNEL_SUCCESS
|
||||||
|
; jne proto_err
|
||||||
|
|
||||||
; Launch network thread
|
; Launch network thread
|
||||||
mcall 18, 7
|
mcall 18, 7
|
||||||
@ -340,13 +552,26 @@ mainloop:
|
|||||||
test eax, 0x200 ; con window closed?
|
test eax, 0x200 ; con window closed?
|
||||||
jnz exit
|
jnz exit
|
||||||
|
|
||||||
stdcall ssh_recv_packet, [socketnum], rx_buffer, BUFFERSIZE, 0
|
stdcall ssh_recv_packet, con, 0
|
||||||
cmp eax, -1
|
cmp eax, 0
|
||||||
je closed
|
jbe closed
|
||||||
|
|
||||||
|
cmp [con.rx_buffer.message_code], SSH_MSG_CHANNEL_DATA
|
||||||
|
jne .dump
|
||||||
|
|
||||||
|
mov eax, dword[con.rx_buffer.message_code+5]
|
||||||
|
bswap eax
|
||||||
DEBUGF 1, 'SSH: got %u bytes of data !\n', eax
|
DEBUGF 1, 'SSH: got %u bytes of data !\n', eax
|
||||||
|
|
||||||
mov esi, rx_buffer
|
lea esi, [con.rx_buffer.message_code+5+4]
|
||||||
|
mov ecx, eax
|
||||||
|
lea edi, [esi + eax]
|
||||||
|
mov byte [edi], 0
|
||||||
|
invoke con_write_asciiz, esi
|
||||||
|
jmp mainloop
|
||||||
|
|
||||||
|
.dump:
|
||||||
|
lea esi, [con.rx_buffer]
|
||||||
mov ecx, eax
|
mov ecx, eax
|
||||||
pusha
|
pusha
|
||||||
@@:
|
@@:
|
||||||
@ -355,23 +580,22 @@ mainloop:
|
|||||||
dec ecx
|
dec ecx
|
||||||
jnz @r
|
jnz @r
|
||||||
popa
|
popa
|
||||||
lea edi, [esi + eax]
|
DEBUGF 1, "\n"
|
||||||
mov byte [edi], 0
|
|
||||||
invoke con_write_asciiz, esi
|
|
||||||
jmp mainloop
|
jmp mainloop
|
||||||
|
|
||||||
|
|
||||||
proto_err:
|
proto_err:
|
||||||
DEBUGF 1, "SSH: protocol error\n"
|
DEBUGF 3, "SSH: protocol error\n"
|
||||||
invoke con_write_asciiz, str7
|
invoke con_write_asciiz, str7
|
||||||
jmp prompt
|
jmp prompt
|
||||||
|
|
||||||
socket_err:
|
socket_err:
|
||||||
DEBUGF 1, "SSH: socket error %d\n", ebx
|
DEBUGF 3, "SSH: socket error %d\n", ebx
|
||||||
invoke con_write_asciiz, str6
|
invoke con_write_asciiz, str6
|
||||||
jmp prompt
|
jmp prompt
|
||||||
|
|
||||||
dns_error:
|
dns_error:
|
||||||
DEBUGF 1, "SSH: DNS error %d\n", eax
|
DEBUGF 3, "SSH: DNS error %d\n", eax
|
||||||
invoke con_write_asciiz, str5
|
invoke con_write_asciiz, str5
|
||||||
jmp prompt
|
jmp prompt
|
||||||
|
|
||||||
@ -386,8 +610,8 @@ closed:
|
|||||||
done:
|
done:
|
||||||
invoke con_exit, 1
|
invoke con_exit, 1
|
||||||
exit:
|
exit:
|
||||||
DEBUGF 1, "SSH: Exiting\n"
|
DEBUGF 3, "SSH: Exiting\n"
|
||||||
mcall close, [socketnum]
|
mcall close, [con.socketnum]
|
||||||
mcall -1
|
mcall -1
|
||||||
|
|
||||||
|
|
||||||
@ -395,14 +619,8 @@ thread:
|
|||||||
mcall 40, 0
|
mcall 40, 0
|
||||||
.loop:
|
.loop:
|
||||||
invoke con_getch2
|
invoke con_getch2
|
||||||
mov [send_data], ax
|
mov [ssh_channel_data+9], al
|
||||||
xor esi, esi
|
stdcall ssh_send_packet, con, ssh_channel_data, ssh_channel_data.length, 0
|
||||||
inc esi
|
|
||||||
test al, al
|
|
||||||
jnz @f
|
|
||||||
inc esi
|
|
||||||
@@:
|
|
||||||
stdcall ssh_send_packet, [socketnum], send_data, 0
|
|
||||||
|
|
||||||
invoke con_get_flags
|
invoke con_get_flags
|
||||||
test eax, 0x200 ; con window closed?
|
test eax, 0x200 ; con window closed?
|
||||||
@ -423,17 +641,12 @@ str8 db ' (',0
|
|||||||
str9 db ')',10,0
|
str9 db ')',10,0
|
||||||
str10 db 'Invalid hostname.',10,10,0
|
str10 db 'Invalid hostname.',10,10,0
|
||||||
str11 db 10,'Remote host closed the connection.',10,10,0
|
str11 db 10,'Remote host closed the connection.',10,10,0
|
||||||
|
str12 db 'Enter username: ',0
|
||||||
sockaddr1:
|
|
||||||
dw AF_INET4
|
|
||||||
.port dw 0
|
|
||||||
.ip dd 0
|
|
||||||
rb 10
|
|
||||||
|
|
||||||
ssh_ident_ha:
|
ssh_ident_ha:
|
||||||
dd_n (ssh_ident.length-2)
|
dd_n (ssh_ident.length-2)
|
||||||
ssh_ident:
|
ssh_ident:
|
||||||
db "SSH-2.0-KolibriOS_SSH_0.01",13,10
|
db "SSH-2.0-KolibriOS_SSH_0.02",13,10
|
||||||
.length = $ - ssh_ident
|
.length = $ - ssh_ident
|
||||||
|
|
||||||
ssh_kex:
|
ssh_kex:
|
||||||
@ -490,16 +703,75 @@ ssh_new_keys:
|
|||||||
.length = $ - ssh_new_keys
|
.length = $ - ssh_new_keys
|
||||||
|
|
||||||
|
|
||||||
|
ssh_request_service:
|
||||||
|
db SSH_MSG_SERVICE_REQUEST
|
||||||
|
dd_n 12 ; String length
|
||||||
|
db "ssh-userauth" ; Service name
|
||||||
|
.length = $ - ssh_request_service
|
||||||
|
|
||||||
|
|
||||||
|
ssh_request_userauth:
|
||||||
|
db SSH_MSG_USERAUTH_REQUEST
|
||||||
|
dd_n 12
|
||||||
|
dd_n 8
|
||||||
|
db "username" ; user name in ISO-10646 UTF-8 encoding [RFC3629]
|
||||||
|
dd_n 14
|
||||||
|
db "ssh-connection" ; service name in US-ASCII
|
||||||
|
dd_n 4
|
||||||
|
db "none" ; method name in US-ASCII
|
||||||
|
; Other options: publickey, password, hostbased
|
||||||
|
.length = $ - ssh_request_userauth
|
||||||
|
|
||||||
|
|
||||||
|
ssh_channel_open:
|
||||||
|
db SSH_MSG_CHANNEL_OPEN
|
||||||
|
dd_n 7
|
||||||
|
db "session"
|
||||||
|
dd_n 0 ; Sender channel
|
||||||
|
dd_n 1024 ; Initial window size
|
||||||
|
dd_n 1024 ; maximum packet size
|
||||||
|
.length = $ - ssh_channel_open
|
||||||
|
|
||||||
|
ssh_channel_request:
|
||||||
|
db SSH_MSG_CHANNEL_REQUEST
|
||||||
|
dd_n 0 ; Recipient channel
|
||||||
|
dd_n 7
|
||||||
|
db "pty-req"
|
||||||
|
db 1 ; Bool: want reply
|
||||||
|
dd_n 5
|
||||||
|
db "xterm"
|
||||||
|
dd_n 80 ; terminal width (rows)
|
||||||
|
dd_n 25 ; terminal height (rows)
|
||||||
|
dd_n 0 ; terminal width (pixels)
|
||||||
|
dd_n 0 ; terminal height (pixels)
|
||||||
|
|
||||||
|
dd_n 0 ; list of supported opcodes
|
||||||
|
.length = $ - ssh_channel_request
|
||||||
|
|
||||||
|
ssh_shell_request:
|
||||||
|
db SSH_MSG_CHANNEL_REQUEST
|
||||||
|
dd_n 0 ; Recipient channel
|
||||||
|
dd_n 5
|
||||||
|
db "shell"
|
||||||
|
db 1 ; Bool: want reply
|
||||||
|
.length = $ - ssh_shell_request
|
||||||
|
|
||||||
|
ssh_channel_data:
|
||||||
|
db SSH_MSG_CHANNEL_DATA
|
||||||
|
dd_n 0 ; Sender channel
|
||||||
|
dd_n 1
|
||||||
|
db ?
|
||||||
|
.length = $ - ssh_channel_data
|
||||||
|
|
||||||
|
|
||||||
include_debug_strings
|
include_debug_strings
|
||||||
|
|
||||||
|
|
||||||
; import
|
|
||||||
align 4
|
align 4
|
||||||
@IMPORT:
|
@IMPORT:
|
||||||
|
|
||||||
library network, 'network.obj', \
|
library network, 'network.obj', \
|
||||||
console, 'console.obj';, \
|
console, 'console.obj', \
|
||||||
; libcrash, 'libcrash.obj'
|
libcrash, 'libcrash.obj'
|
||||||
|
|
||||||
import network, \
|
import network, \
|
||||||
getaddrinfo, 'getaddrinfo', \
|
getaddrinfo, 'getaddrinfo', \
|
||||||
@ -518,61 +790,23 @@ import console, \
|
|||||||
con_write_string, 'con_write_string', \
|
con_write_string, 'con_write_string', \
|
||||||
con_get_flags, 'con_get_flags'
|
con_get_flags, 'con_get_flags'
|
||||||
|
|
||||||
;import libcrash, \
|
import libcrash, \
|
||||||
; crash.hash, 'crash_hash'
|
sha256_init, 'sha256_init', \
|
||||||
|
sha256_update, 'sha256_update', \
|
||||||
|
sha256_final, 'sha256_final'
|
||||||
|
|
||||||
IncludeIGlobals
|
IncludeIGlobals
|
||||||
|
|
||||||
i_end:
|
i_end:
|
||||||
|
|
||||||
decrypt_proc dd dummy_encrypt
|
|
||||||
encrypt_proc dd dummy_encrypt
|
|
||||||
rx_blocksize dd 4
|
|
||||||
tx_blocksize dd 4
|
|
||||||
rx_context dd ?
|
|
||||||
tx_context dd ?
|
|
||||||
|
|
||||||
IncludeUGlobals
|
IncludeUGlobals
|
||||||
|
|
||||||
socketnum dd ?
|
params rb 1024
|
||||||
rx_packet_length dd ? ;;;;;
|
|
||||||
rx_buffer: rb BUFFERSIZE+1
|
|
||||||
tx_buffer: rb BUFFERSIZE+1
|
|
||||||
|
|
||||||
send_data dw ?
|
con ssh_connection
|
||||||
|
|
||||||
hostname rb 1024
|
; Temporary values ; To be removed FIXME
|
||||||
|
|
||||||
; Diffie Hellman variables
|
|
||||||
dh_p dd ?
|
|
||||||
rb MAX_BITS/8
|
|
||||||
dh_g dd ?
|
|
||||||
rb MAX_BITS/8
|
|
||||||
dh_x dd ?
|
|
||||||
rb MAX_BITS/8
|
|
||||||
dh_e dd ?
|
|
||||||
rb MAX_BITS/8
|
|
||||||
dh_f dd ?
|
|
||||||
rb MAX_BITS/8
|
|
||||||
|
|
||||||
dh_signature dd ?
|
|
||||||
rb MAX_BITS/8
|
|
||||||
|
|
||||||
; Output from key exchange
|
|
||||||
dh_K dd ? ; Shared Secret (Big endian)
|
|
||||||
rb MAX_BITS/8
|
|
||||||
.length dd ? ; Length in little endian
|
|
||||||
|
|
||||||
dh_H rb 32 ; Exchange Hash
|
|
||||||
session_id rb 32
|
|
||||||
rx_iv rb 32 ; Rx initialisation vector
|
|
||||||
tx_iv rb 32 ; Tx initialisation vector
|
|
||||||
rx_enc_key rb 32 ; Rx encryption key
|
|
||||||
tx_enc_key rb 32 ; Tx encryption key
|
|
||||||
rx_int_key rb 32 ; Rx integrity key
|
|
||||||
tx_int_key rb 32 ; Tx integrity key
|
|
||||||
|
|
||||||
; Temporary values ; To be removed
|
|
||||||
mpint_tmp rb MPINT_MAX_LEN+4
|
mpint_tmp rb MPINT_MAX_LEN+4
|
||||||
|
|
||||||
|
|
||||||
mem:
|
mem:
|
||||||
|
@ -15,120 +15,181 @@
|
|||||||
; You should have received a copy of the GNU General Public License
|
; You should have received a copy of the GNU General Public License
|
||||||
; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
struct ssh_header
|
|
||||||
length dd ?
|
struct ssh_packet_header
|
||||||
padding db ?
|
packet_length dd ? ; The length of the packet in bytes, not including 'mac' or the
|
||||||
message_code db ?
|
; 'packet_length' field itself.
|
||||||
|
padding_length db ? ; Length of 'random padding' (bytes).
|
||||||
|
|
||||||
|
message_code db ? ; First byte of payload
|
||||||
ends
|
ends
|
||||||
|
|
||||||
proc dummy_encrypt _key, _in, _out
|
|
||||||
|
|
||||||
ret
|
proc ssh_recv_packet connection, flags
|
||||||
endp
|
|
||||||
|
|
||||||
proc ssh_recv_packet sock, buf, size, flags
|
|
||||||
|
|
||||||
locals
|
locals
|
||||||
bufferptr dd ?
|
data_length dd ? ; Total length of packet without MAC
|
||||||
remaining dd ?
|
|
||||||
padding dd ?
|
|
||||||
endl
|
endl
|
||||||
|
|
||||||
DEBUGF 1, "ssh_recv_packet\n"
|
DEBUGF 2, "> "
|
||||||
; Receive first block (Read length, padding length, message code)
|
; Receive first block (Read length, padding length, message code)
|
||||||
mcall recv, [sock], [buf], [rx_blocksize], [flags]
|
mov ebx, [connection]
|
||||||
DEBUGF 1, "chunk = %u\n", eax
|
mov ecx, [ebx+ssh_connection.socketnum]
|
||||||
cmp eax, [rx_blocksize]
|
mov esi, [ebx+ssh_connection.rx_crypt_blocksize]
|
||||||
jne .fail ;;;;
|
lea edx, [ebx+ssh_connection.rx_buffer]
|
||||||
|
mov edi, [flags]
|
||||||
|
mcall recv
|
||||||
|
DEBUGF 1, "chunk = %u ", eax
|
||||||
|
mov ebx, [connection]
|
||||||
|
cmp eax, [ebx+ssh_connection.rx_crypt_blocksize]
|
||||||
|
jne .fail
|
||||||
|
|
||||||
; stdcall [decrypt_proc], [rx_context], [buf], [buf]
|
; Decrypt first block
|
||||||
|
cmp [ebx+ssh_connection.rx_crypt_proc], 0
|
||||||
|
je @f
|
||||||
|
pusha
|
||||||
|
lea esi, [ebx+ssh_connection.rx_buffer]
|
||||||
|
stdcall [ebx+ssh_connection.rx_crypt_proc], [ebx+ssh_connection.rx_crypt_ctx_ptr], esi, esi
|
||||||
|
popa
|
||||||
|
@@:
|
||||||
|
|
||||||
mov ebx, [buf]
|
; Check data length
|
||||||
movzx eax, [ebx+ssh_header.padding]
|
mov esi, [ebx+ssh_connection.rx_buffer.packet_length]
|
||||||
mov [padding], eax
|
bswap esi ; convert length to little endian
|
||||||
mov eax, [ebx+ssh_header.length]
|
mov [ebx+ssh_connection.rx_buffer.packet_length], esi
|
||||||
bswap eax ; length to little endian
|
DEBUGF 1, "packet length=%u ", esi
|
||||||
mov [ebx+ssh_header.length], eax
|
cmp esi, BUFFERSIZE
|
||||||
DEBUGF 1, "ssh_recv_packet length = %u\n", eax
|
ja .fail ; packet is too large
|
||||||
|
|
||||||
cmp eax, [size]
|
; Calculate amount of remaining data
|
||||||
ja .fail ;;;;
|
add esi, 4 ; Packet length field itself is not included in the count
|
||||||
|
sub esi, [ebx+ssh_connection.rx_crypt_blocksize] ; Already received this amount of data
|
||||||
|
add esi, [ebx+ssh_connection.rx_mac_length]
|
||||||
|
jz .got_all_data
|
||||||
|
|
||||||
sub eax, [rx_blocksize]
|
; Receive remaining data
|
||||||
add eax, 4
|
lea edx, [ebx+ssh_connection.rx_buffer]
|
||||||
mov [remaining], eax
|
add edx, [ebx+ssh_connection.rx_crypt_blocksize]
|
||||||
add ebx, [rx_blocksize]
|
mov ecx, [ebx+ssh_connection.socketnum]
|
||||||
mov [bufferptr], ebx
|
mov edi, [flags]
|
||||||
.receive_loop:
|
.receive_loop:
|
||||||
mcall recv, [sock], [bufferptr], [remaining], 0
|
mcall recv
|
||||||
DEBUGF 1, "chunk = %u\n", eax
|
DEBUGF 1, "chunk = %u ", eax
|
||||||
cmp eax, 0
|
cmp eax, 0
|
||||||
jbe .fail
|
jbe .fail
|
||||||
add [bufferptr], eax
|
add edx, eax
|
||||||
sub [remaining], eax
|
sub esi, eax
|
||||||
ja .receive_loop
|
jnz .receive_loop
|
||||||
|
|
||||||
; .decrypt_loop:
|
; Decrypt data
|
||||||
; stdcall [decrypt_proc], [rx_context], [buf], [buf]
|
mov ebx, [connection]
|
||||||
; ja .decrypt_loop
|
cmp [ebx+ssh_connection.rx_crypt_proc], 0
|
||||||
|
je .decrypt_complete
|
||||||
|
mov ecx, [ebx+ssh_connection.rx_buffer.packet_length]
|
||||||
|
add ecx, 4 ; Packet_length field itself
|
||||||
|
sub ecx, [ebx+ssh_connection.rx_crypt_blocksize] ; Already decrypted this amount of data
|
||||||
|
jz .decrypt_complete
|
||||||
|
|
||||||
; .hmac_loop:
|
lea esi, [ebx+ssh_connection.rx_buffer]
|
||||||
; TODO
|
add esi, [ebx+ssh_connection.rx_crypt_blocksize]
|
||||||
; ja .hmac_loop
|
.decrypt_loop:
|
||||||
|
pusha
|
||||||
|
stdcall [ebx+ssh_connection.rx_crypt_proc], [ebx+ssh_connection.rx_crypt_ctx_ptr], esi, esi
|
||||||
|
popa
|
||||||
|
add esi, [ebx+ssh_connection.rx_crypt_blocksize]
|
||||||
|
sub ecx, [ebx+ssh_connection.rx_crypt_blocksize]
|
||||||
|
jnz .decrypt_loop
|
||||||
|
.decrypt_complete:
|
||||||
|
|
||||||
; Return usefull data length in eax
|
; Authenticate message
|
||||||
mov eax, [buf]
|
cmp [ebx+ssh_connection.rx_mac_proc], 0
|
||||||
movzx ebx, [eax+ssh_header.padding]
|
je .mac_complete
|
||||||
mov eax, [eax+ssh_header.length]
|
lea esi, [ebx+ssh_connection.rx_seq]
|
||||||
|
mov ecx, [ebx+ssh_connection.rx_buffer.packet_length]
|
||||||
|
add ecx, 8 ; packet_length field itself + sequence number
|
||||||
|
lea eax, [ebx+ssh_connection.rx_mac_ctx]
|
||||||
|
mov edx, [ebx+ssh_connection.rx_buffer.packet_length]
|
||||||
|
bswap edx ; convert length to big endian
|
||||||
|
mov [ebx+ssh_connection.rx_buffer.packet_length], edx
|
||||||
|
stdcall [ebx+ssh_connection.rx_mac_proc], eax, esi, ecx
|
||||||
|
mov edx, [ebx+ssh_connection.rx_buffer.packet_length]
|
||||||
|
bswap edx ; convert length to little endian
|
||||||
|
mov [ebx+ssh_connection.rx_buffer.packet_length], edx
|
||||||
|
|
||||||
|
lea esi, [ebx+ssh_connection.rx_mac_ctx]
|
||||||
|
lea edi, [ebx+ssh_connection.rx_buffer]
|
||||||
|
add edi, [ebx+ssh_connection.rx_buffer.packet_length]
|
||||||
|
add edi, 4
|
||||||
|
mov ecx, [ebx+ssh_connection.rx_mac_length]
|
||||||
|
shr ecx, 2
|
||||||
|
repe cmpsd
|
||||||
|
jne .mac_failed
|
||||||
|
.mac_complete:
|
||||||
|
inc byte[ebx+ssh_connection.rx_seq+3] ; Update sequence counter
|
||||||
|
jnc @f
|
||||||
|
inc byte[ebx+ssh_connection.rx_seq+2]
|
||||||
|
jnc @f
|
||||||
|
inc byte[ebx+ssh_connection.rx_seq+1]
|
||||||
|
jnc @f
|
||||||
|
inc byte[ebx+ssh_connection.rx_seq+0]
|
||||||
|
@@:
|
||||||
|
|
||||||
|
; Return useful data length to the caller via eax register
|
||||||
|
.got_all_data:
|
||||||
|
mov eax, [ebx+ssh_connection.rx_buffer.packet_length]
|
||||||
|
movzx ebx, [ebx+ssh_connection.rx_buffer.padding_length]
|
||||||
sub eax, ebx
|
sub eax, ebx
|
||||||
DEBUGF 1, "ssh_recv_packet complete, usefull data length=%u\n", eax
|
DEBUGF 1, "useful data length=%u\n", eax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.fail:
|
.fail:
|
||||||
DEBUGF 1, "ssh_recv_packet failed!\n"
|
DEBUGF 3, "ssh_recv_packet failed!\n"
|
||||||
|
mov eax, -1
|
||||||
|
ret
|
||||||
|
|
||||||
|
.mac_failed:
|
||||||
|
DEBUGF 3, "ssh_recv_packet MAC failed!\n"
|
||||||
mov eax, -1
|
mov eax, -1
|
||||||
ret
|
ret
|
||||||
|
|
||||||
endp
|
endp
|
||||||
|
|
||||||
|
|
||||||
proc ssh_send_packet sock, buf, payloadsize, flags
|
proc ssh_send_packet connection, buf, payload_size, flags
|
||||||
|
|
||||||
locals
|
locals
|
||||||
size dd ?
|
packet_size dd ?
|
||||||
endl
|
endl
|
||||||
DEBUGF 1, "ssh_send_packet: size=%u\n", [payloadsize]
|
DEBUGF 2, "< "
|
||||||
|
|
||||||
mov eax, [payloadsize]
|
; Pad the packet with random data
|
||||||
|
mov eax, [payload_size]
|
||||||
inc eax ; padding length byte
|
inc eax ; padding length byte
|
||||||
|
lea edx, [eax+4] ; total packet size (without padding and MAC)
|
||||||
lea edx, [eax+4] ; total packet size (without padding)
|
mov [packet_size], edx
|
||||||
mov [size], edx
|
mov ecx, [connection]
|
||||||
mov ebx, [tx_blocksize]
|
mov ebx, [ecx+ssh_connection.tx_crypt_blocksize]
|
||||||
dec ebx
|
dec ebx
|
||||||
and edx, ebx
|
and edx, ebx
|
||||||
neg edx
|
neg edx
|
||||||
add edx, [tx_blocksize]
|
add edx, [ecx+ssh_connection.tx_crypt_blocksize]
|
||||||
cmp edx, 4 ; minimum padding size
|
cmp edx, 4 ; minimum padding size
|
||||||
jae @f
|
jae @f
|
||||||
add edx, [tx_blocksize]
|
add edx, [ecx+ssh_connection.tx_crypt_blocksize]
|
||||||
@@:
|
@@:
|
||||||
DEBUGF 1, "Padding %u bytes\n", edx
|
DEBUGF 1, "padding %u bytes ", edx
|
||||||
add [size], edx
|
add [packet_size], edx
|
||||||
|
|
||||||
add eax, edx
|
add eax, edx
|
||||||
DEBUGF 1, "Total size: %u\n", eax
|
DEBUGF 1, "total size: %u ", eax
|
||||||
bswap eax
|
bswap eax
|
||||||
mov edi, tx_buffer
|
lea edi, [ecx+ssh_connection.tx_buffer]
|
||||||
stosd
|
stosd ; packet_length
|
||||||
mov al, dl
|
mov al, dl
|
||||||
stosb
|
stosb ; padding_length
|
||||||
mov esi, [buf]
|
mov esi, [buf]
|
||||||
; cmp esi, edi
|
mov ecx, [payload_size]
|
||||||
; je @f
|
|
||||||
mov ecx, [payloadsize]
|
|
||||||
rep movsb
|
rep movsb
|
||||||
; @@:
|
|
||||||
|
|
||||||
mov ebx, edx
|
mov ebx, edx
|
||||||
mov esi, edx
|
mov esi, edx
|
||||||
@ -146,8 +207,59 @@ endl
|
|||||||
dec esi
|
dec esi
|
||||||
jnz @r
|
jnz @r
|
||||||
|
|
||||||
mcall send, [sock], tx_buffer, [size], [flags]
|
; Message authentication
|
||||||
|
mov edx, [connection]
|
||||||
|
cmp [edx+ssh_connection.tx_mac_proc], 0
|
||||||
|
je .mac_complete
|
||||||
|
; DEBUGF 1, "MAC sequence number: 0x%x\n", [edx+ssh_connection.tx_seq]
|
||||||
|
lea esi, [edx+ssh_connection.tx_seq]
|
||||||
|
mov ecx, [packet_size]
|
||||||
|
add ecx, 4 ; Sequence number length
|
||||||
|
lea eax, [edx+ssh_connection.tx_mac_ctx]
|
||||||
|
stdcall [edx+ssh_connection.tx_mac_proc], eax, esi, ecx
|
||||||
|
|
||||||
|
lea esi, [edx+ssh_connection.tx_mac_ctx]
|
||||||
|
lea edi, [edx+ssh_connection.tx_buffer]
|
||||||
|
add edi, [packet_size]
|
||||||
|
mov ecx, [edx+ssh_connection.tx_mac_length]
|
||||||
|
shr ecx, 2
|
||||||
|
rep movsd
|
||||||
|
.mac_complete:
|
||||||
|
inc byte[edx+ssh_connection.tx_seq+3] ; Update sequence counter
|
||||||
|
jnc @f
|
||||||
|
inc byte[edx+ssh_connection.tx_seq+2]
|
||||||
|
jnc @f
|
||||||
|
inc byte[edx+ssh_connection.tx_seq+1]
|
||||||
|
jnc @f
|
||||||
|
inc byte[edx+ssh_connection.tx_seq+0]
|
||||||
|
@@:
|
||||||
|
|
||||||
|
; Encrypt data
|
||||||
|
cmp [edx+ssh_connection.tx_crypt_proc], 0
|
||||||
|
je .encrypt_complete
|
||||||
|
lea esi, [edx+ssh_connection.tx_buffer]
|
||||||
|
mov ecx, [packet_size]
|
||||||
|
.encrypt_loop:
|
||||||
|
pusha
|
||||||
|
stdcall [edx+ssh_connection.tx_crypt_proc], [edx+ssh_connection.tx_crypt_ctx_ptr], esi, esi
|
||||||
|
popa
|
||||||
|
add esi, [edx+ssh_connection.tx_crypt_blocksize]
|
||||||
|
sub ecx, [edx+ssh_connection.tx_crypt_blocksize]
|
||||||
|
jnz .encrypt_loop
|
||||||
|
.encrypt_complete:
|
||||||
|
|
||||||
|
; Send the packet
|
||||||
|
mov ebx, [connection]
|
||||||
|
mov ecx, [ebx+ssh_connection.socketnum]
|
||||||
|
lea edx, [ebx+ssh_connection.tx_buffer]
|
||||||
|
mov esi, [packet_size]
|
||||||
|
add esi, [ebx+ssh_connection.tx_mac_length]
|
||||||
|
mov edi, [flags]
|
||||||
|
mcall send
|
||||||
|
|
||||||
|
DEBUGF 1, "\n"
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
endp
|
endp
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user