/programs/network/ssh/aes256-ctr.inc |
---|
File deleted |
\ No newline at end of file |
/programs/network/ssh/blowfish-ctr.inc |
---|
File deleted |
\ No newline at end of file |
/programs/network/ssh/hmac_md5.inc |
---|
File deleted |
/programs/network/ssh/aes256-cbc.inc |
---|
File deleted |
\ No newline at end of file |
/programs/network/ssh/hmac_sha256.inc |
---|
File deleted |
/programs/network/ssh/hmac_sha1.inc |
---|
File deleted |
/programs/network/ssh/aes256.inc |
---|
File deleted |
\ No newline at end of file |
/programs/network/ssh/blowfish-cbc.inc |
---|
File deleted |
\ No newline at end of file |
/programs/network/ssh/blowfish.inc |
---|
File deleted |
\ No newline at end of file |
/programs/network/ssh/ssh.asm |
---|
1,6 → 1,6 |
; ssh.asm - SSH client for KolibriOS |
; |
; Copyright (C) 2015-2021 Jeffrey Amelynck |
; Copyright (C) 2015-2024 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 |
104,22 → 104,12 |
include 'seed.inc' |
include 'random.inc' |
include 'aes256.inc' |
include 'aes256-ctr.inc' |
include 'aes256-cbc.inc' |
include 'blowfish.inc' |
include 'blowfish-ctr.inc' |
include 'blowfish-cbc.inc' |
include 'hmac_sha256.inc' |
include 'hmac_sha1.inc' |
include 'hmac_md5.inc' |
include 'sshlib.inc' |
include 'sshlib_mcodes.inc' |
include 'sshlib_transport.inc' |
include 'sshlib_transport_hmac.inc' |
include 'sshlib_transport_polychacha.inc' |
include 'sshlib_connection.inc' |
include 'sshlib_dh_gex.inc' |
include 'sshlib_host.inc' |
219,7 → 209,7 |
mcall 18, 7 |
push eax |
; Create thread |
mcall 51, 1, con_in_thread, mem - 2048 |
mcall 51, 1, con_in_thread, mem + 2048 |
; Activate window with given ID |
pop ecx |
mcall 18, 3 |
487,7 → 477,7 |
ssh_ident_ha: |
dd_n (ssh_msg_ident.length-2) |
ssh_msg_ident: |
db "SSH-2.0-KolibriOS_SSH_0.09",13,10 |
db "SSH-2.0-KolibriOS_SSH_0.10",13,10 |
.length = $ - ssh_msg_ident |
500,9 → 490,9 |
.server_host_key_algorithms: |
str "rsa-sha2-512,rsa-sha2-256,ssh-rsa" ;,ssh-dss |
.encryption_algorithms_client_to_server: |
str "aes256-ctr" ;,aes256-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se,aes192-ctr,aes192-cbc,aes128-ctr,aes128-cbc,blowfish-ctr,blowfish-cbc,3des-ctr,3des-cbc,arcfour256,arcfour128" |
str "chacha20-poly1305@openssh.com" ;aes256-ctr,aes256-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se,aes192-ctr,aes192-cbc,aes128-ctr,aes128-cbc,blowfish-ctr,blowfish-cbc,3des-ctr,3des-cbc,arcfour256,arcfour128" |
.encryption_algorithms_server_to_client: |
str "aes256-ctr" ;,aes256-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se,aes192-ctr,aes192-cbc,aes128-ctr,aes128-cbc,blowfish-ctr,blowfish-cbc,3des-ctr,3des-cbc,arcfour256,arcfour128" |
str "chacha20-poly1305@openssh.com" ;aes256-ctr,aes256-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se,aes192-ctr,aes192-cbc,aes128-ctr,aes128-cbc,blowfish-ctr,blowfish-cbc,3des-ctr,3des-cbc,arcfour256,arcfour128" |
.mac_algorithms_client_to_server: |
str "hmac-sha2-256" ;,hmac-sha1,hmac-sha1-96,hmac-md5" |
.mac_algorithms_server_to_client: |
630,9 → 620,21 |
sha1_init, 'sha1_init', \ |
sha1_update, 'sha1_update', \ |
sha1_finish, 'sha1_finish', \ |
md5_init, 'md5_init', \ |
md5_update, 'md5_update', \ |
md5_finish, 'md5_finish' |
chacha20_init, 'chacha20_init' , \ |
chacha20_update, 'chacha20_update', \ |
chacha20_oneshot, 'chacha20_oneshot', \ |
poly1305_init, 'poly1305_init', \ |
poly1305_update, 'poly1305_update', \ |
poly1305_finish, 'poly1305_finish', \ |
poly1305_oneshot, 'poly1305_oneshot', \ |
aes256ctr.init, "aes256ctr_init", \ |
aes256ctr.update, "aes256ctr_update", \ |
aes256ctr.finish, "aes256ctr_finish", \ |
aes256ctr.oneshot, "aes256ctr_oneshot", \ |
hmac_sha2_256.init_, "hmac_sha2_256_init", \ |
hmac_sha2_256.update_, "hmac_sha2_256_update", \ |
hmac_sha2_256.finish_, "hmac_sha2_256_finish", \ |
hmac_sha2_256.oneshot, "hmac_sha2_256_oneshot" |
import libini, \ |
ini_get_str, 'ini_get_str', \ |
644,9 → 646,13 |
IncludeUGlobals |
align 16 |
params rb MAX_HOSTNAME_LENGTH |
align 16 |
ssh_con sshlib_connection |
align 16 |
ssh_chan sshlib_channel |
keyb_input rb MAX_INPUT_LENGTH |
/programs/network/ssh/sshlib.inc |
---|
54,19 → 54,20 |
SSHLIB_HOSTKEY_RSA_SHA2_256 = 3 |
SSHLIB_HOSTKEY_RSA_SHA2_512 = 4 |
SSHLIB_CRYPT_BLOWFISH_CTR = 1 |
SSHLIB_CRYPT_BLOWFISH_CBC = 2 |
SSHLIB_CRYPT_AES128_CTR = 3 |
SSHLIB_CRYPT_AES128_CBC = 4 |
SSHLIB_CRYPT_AES192_CTR = 5 |
SSHLIB_CRYPT_AES192_CBC = 6 |
SSHLIB_CRYPT_AES256_CTR = 7 |
SSHLIB_CRYPT_AES256_CBC = 8 |
;SSHLIB_CRYPT_BLOWFISH_CTR = 1 ; blowfish-ctr |
;SSHLIB_CRYPT_BLOWFISH_CBC = 2 ; blowfish-cbc |
;SSHLIB_CRYPT_AES128_CTR = 3 ; aes128-ctr |
;SSHLIB_CRYPT_AES128_CBC = 4 ; aes128-cbc |
;SSHLIB_CRYPT_AES192_CTR = 5 ; aes192-cbc |
;SSHLIB_CRYPT_AES192_CBC = 6 ; aes192-ctr |
SSHLIB_CRYPT_AES256_CTR = 7 ; aes256-ctr |
SSHLIB_CRYPT_AES256_CBC = 8 ; aes256-cbc |
SSHLIB_CRYPT_CHACHA20_POLY1305 = 9 ; chacha20-poly1305@openssh.com" |
SSHLIB_HMAC_MD5 = 1 |
SSHLIB_HMAC_SHA1 = 2 |
SSHLIB_HMAC_SHA1_96 = 3 |
SSHLIB_HMAC_SHA2_256 = 4 |
;SSHLIB_HMAC_MD5 = 1 ; hmac-md5 |
;SSHLIB_HMAC_SHA1 = 2 ; hmac-sha1 |
;SSHLIB_HMAC_SHA1_96 = 3 ; hmac-sha1-96 |
SSHLIB_HMAC_SHA2_256 = 4 ; hmac-sha2-256 |
SSHLIB_COMPR_NONE = 1 |
SSHLIB_COMPR_ZLIB = 2 |
97,31 → 98,39 |
struct sshlib_connection |
status dd ? |
socketnum dd ? |
rx_proc dd ? |
tx_proc dd ? |
rx_mac_ctx rb LIBCRASH_CTX_LEN |
tx_mac_ctx rb LIBCRASH_CTX_LEN |
rx_crypt_ctx rb LIBCRASH_CTX_LEN |
tx_crypt_ctx rb LIBCRASH_CTX_LEN |
rx_crypt_proc dd ? |
tx_crypt_proc dd ? |
rx_crypt_ctx_ptr dd ? |
tx_crypt_ctx_ptr dd ? |
; rx_crypt_ctx_ptr dd ? |
; tx_crypt_ctx_ptr dd ? |
rx_crypt_blocksize dd ? |
tx_crypt_blocksize dd ? |
tx_pad_size dd ? ; = Max(8, tx_crypt_blocksize) |
tx_pad_proc dd ? |
dd ? |
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 ? |
rx_mac_seqnr dd ? ; DO NOT MOVE |
rd 3 ; align |
rx_mac_seqnr dd ? ; DO NOT MOVE (specific place for HMAC) |
rx_buffer ssh_packet_header |
rb BUFFERSIZE-sizeof.ssh_packet_header |
tx_mac_seqnr dd ? ; DO NOT MOVE |
tx_mac_seqnr dd ? ; DO NOT MOVE (specific place for HMAC) |
tx_buffer ssh_packet_header |
rb PACKETSIZE-sizeof.ssh_packet_header |
139,6 → 148,13 |
hostname_sz rb MAX_HOSTNAME_LENGTH |
rx_enc_key rb 2*256/8 |
tx_enc_key rb 2*256/8 |
rx_int_key rb 2*256/8 |
tx_int_key rb 2*256/8 |
rx_iv rb 2*256/8 |
tx_iv rb 2*256/8 |
ends |
; SSH channel structure |
/programs/network/ssh/sshlib_channel.inc |
---|
1,6 → 1,6 |
; sshlib_channel.inc - SSH channel |
; |
; Copyright (C) 2016-2021 Jeffrey Amelynck |
; Copyright (C) 2016-2024 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 |
20,7 → 20,7 |
; >> Open channel |
DEBUGF 2, "SSH: Open channel\n" |
DEBUGF 2, "SSH: Opening channel\n" |
mov [ssh_chan.rcv_wnd], BUFFERSIZE |
mov [ssh_chan.snd_wnd], 0 |
38,9 → 38,11 |
cmp [esi + sshlib_connection.rx_buffer.message_code], SSH_MSG_CHANNEL_OPEN_CONFIRMATION |
jne .err_proto |
DEBUGF 2, "SSH: Channel opened successfully\n" |
; >> Channel request: pty |
DEBUGF 2, "SSH: Request pty\n" |
DEBUGF 2, "SSH: Requesting PTY\n" |
stdcall sshlib_send_packet, [con_ptr], ssh_msg_channel_request, ssh_msg_channel_request.length, 0 |
cmp eax, 0 |
56,9 → 58,11 |
cmp [esi + sshlib_connection.rx_buffer.message_code], SSH_MSG_CHANNEL_SUCCESS |
jne .err_proto |
DEBUGF 2, "SSH: PTY opened successfully\n" |
; >> Channel request: shell |
DEBUGF 2, "SSH: Request shell\n" |
DEBUGF 2, "SSH: Requesting shell\n" |
stdcall sshlib_send_packet, [con_ptr], ssh_msg_shell_request, ssh_msg_shell_request.length, 0 |
cmp eax, 0 |
76,6 → 80,8 |
cmp [esi + sshlib_connection.rx_buffer.message_code], SSH_MSG_CHANNEL_SUCCESS |
jne .wait_success |
DEBUGF 2, "SSH: Shell opened successfully\n" |
xor eax, eax |
.err: |
ret |
/programs/network/ssh/sshlib_connection.inc |
---|
1,6 → 1,6 |
; sshlib_connection.inc - SSH connection |
; |
; Copyright (C) 2016-2021 Jeffrey Amelynck |
; Copyright (C) 2016-2024 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 |
15,6 → 15,8 |
; You should have received a copy of the GNU General Public License |
; along with this program. If not, see <http://www.gnu.org/licenses/>. |
; https://www.ietf.org/rfc/rfc4253.txt |
proc sshlib_connect con_ptr, hostname_sz |
locals |
157,15 → 159,17 |
mov [eax + sshlib_connection.tx_mac_seqnr], 0 |
mov [eax + sshlib_connection.rx_crypt_blocksize], 4 ; minimum blocksize |
mov [eax + sshlib_connection.tx_crypt_blocksize], 4 |
mov [eax + sshlib_connection.rx_crypt_proc], sshlib_crypt_null |
mov [eax + sshlib_connection.tx_crypt_proc], sshlib_crypt_null |
mov [eax + sshlib_connection.rx_crypt_proc], 0 |
mov [eax + sshlib_connection.tx_crypt_proc], 0 |
mov [eax + sshlib_connection.rx_mac_proc], 0 |
mov [eax + sshlib_connection.tx_mac_proc], 0 |
mov [eax + sshlib_connection.rx_mac_length], 0 |
mov [eax + sshlib_connection.tx_mac_length], 0 |
mov [eax + sshlib_connection.tx_pad_size], 8 |
mov [eax + sshlib_connection.tx_pad_proc], sshlib_padd_null |
mov [eax + sshlib_connection.rx_proc], sshlib_recv_packet_clear |
mov [eax + sshlib_connection.tx_proc], sshlib_send_packet_clear |
DEBUGF 2, "Sending KEX init\n" |
mov edi, ssh_msg_kex.cookie |
call MBRandom |
277,6 → 281,45 |
test eax, eax |
jnz .err |
; Set keys and initialize transport subroutines |
DEBUGF 2, "SSH: Setting encryption keys\n" |
mov ebx, [con_ptr] |
; lea ecx, [ebx + sshlib_connection.rx_crypt_ctx] |
; lea edx, [ebx + sshlib_connection.rx_enc_key] |
; lea esi, [ebx + sshlib_connection.rx_iv] |
; invoke aes256ctr.init, ecx, edx, esi, 0 |
; |
; push [aes256ctr.update] |
; pop [ebx + sshlib_connection.rx_crypt_proc] |
; mov [ebx + sshlib_connection.rx_crypt_blocksize], 16 ; AES_BLOCKSIZE |
; |
; push [hmac_sha2_256.oneshot] |
; pop [ebx + sshlib_connection.rx_mac_proc] |
; mov [ebx + sshlib_connection.rx_mac_length], SHA2_256_LEN |
; |
; lea ecx, [ebx + sshlib_connection.tx_crypt_ctx] |
; lea edx, [ebx + sshlib_connection.tx_enc_key] |
; lea esi, [ebx + sshlib_connection.tx_iv] |
; invoke aes256ctr.init, ecx, edx, esi, 0 |
; |
; push [aes256ctr.update] |
; pop [ebx + sshlib_connection.tx_crypt_proc] |
; mov [ebx + sshlib_connection.tx_crypt_blocksize], 16 ; AES_BLOCKSIZE |
; mov [ebx + sshlib_connection.tx_pad_size], 16 ; AES_BLOCKSIZE |
; |
; push [hmac_sha2_256.oneshot] |
; pop [ebx + sshlib_connection.tx_mac_proc] |
; mov [ebx + sshlib_connection.tx_mac_length], SHA2_256_LEN |
; |
; mov [ebx + sshlib_connection.rx_proc], sshlib_recv_packet_hmac |
; mov [ebx + sshlib_connection.tx_proc], sshlib_send_packet_hmac |
mov [ebx + sshlib_connection.rx_proc], sshlib_recv_packet_poly1305chacha20 |
mov [ebx + sshlib_connection.tx_proc], sshlib_send_packet_poly1305chacha20 |
; Re-seed RNG for padding bytes |
call create_seed |
327,7 → 370,7 |
mov esi, [con_ptr] |
lea esi, [esi + sshlib_connection.rx_buffer] |
mov al, [esi + ssh_packet_header.message_code] |
inc esi |
add esi, sizeof.ssh_packet_header |
cmp al, SSH_MSG_DISCONNECT |
je .disc |
346,6 → 389,8 |
cmp al, SSH_MSG_CHANNEL_CLOSE |
je .chan_close |
DEBUGF 3, "SSH: Message type: %u\n", al |
.ret: |
ret |
364,7 → 409,8 |
jmp .recv |
.glob_req: |
DEBUGF 3, "SSH: Global MSG received\n" |
add esi, 4 |
DEBUGF 3, "SSH: Global MSG received: %s\n", esi |
;TODO |
jmp .recv |
/programs/network/ssh/sshlib_dh_gex.inc |
---|
34,14 → 34,6 |
temp_ctx dd ? |
H dd ? ; exchange hash |
rx_iv dd ? ; Rx initialisation vector |
tx_iv dd ? ; Tx initialisation vector |
rx_enc_key dd ? ; Rx encryption key |
tx_enc_key dd ? ; Tx encryption key |
rx_int_key dd ? ; Rx integrity key |
tx_int_key dd ? ; Tx integrity key |
K_length dd ? |
session_id_x rb SHA2_256_LEN+1 |
54,7 → 46,7 |
; Allocate memory for temp variables |
mov ecx, 7*(MAX_BITS/8+4) + 7*SHA2_256_LEN + 2*LIBCRASH_CTX_LEN |
mov ecx, 7*(MAX_BITS/8+4) + 2*LIBCRASH_CTX_LEN + 1*SHA2_256_LEN |
mcall 68, 12 |
test eax, eax |
jz .err_nomem |
83,18 → 75,6 |
mov [H], eax |
add eax, SHA2_256_LEN |
mov [rx_iv], eax |
add eax, SHA2_256_LEN |
mov [tx_iv], eax |
add eax, SHA2_256_LEN |
mov [rx_enc_key], eax |
add eax, SHA2_256_LEN |
mov [tx_enc_key], eax |
add eax, SHA2_256_LEN |
mov [rx_int_key], eax |
add eax, SHA2_256_LEN |
mov [tx_int_key], eax |
; add eax, SHA2_256_LEN |
; Copy the partial exchange hash to our temporary one |
297,7 → 277,26 |
mov ecx, SHA2_256_LEN/4 |
rep movsd |
;------------------------------------- |
; << Parse Diffie-Hellman New Keys MSG |
stdcall sshlib_recv_packet, [con_ptr], 0 |
cmp eax, 0 |
jl .err |
mov ebx, [con_ptr] |
cmp [ebx + sshlib_connection.rx_buffer.message_code], SSH_MSG_NEWKEYS |
jne .err_proto |
DEBUGF 2, "Received New Keys\n" |
;---------------------------------------------------- |
; >> Reply with New Keys message (Using the old keys) |
stdcall sshlib_send_packet, [con_ptr], ssh_msg_new_keys, ssh_msg_new_keys.length, 0 |
cmp eax, 0 |
jl .err |
;--------------- |
; Calculate keys |
321,14 → 320,12 |
mov byte[edx], 'A' |
invoke sha2_256_update, [temp_ctx], edx, SHA2_256_LEN+1 |
invoke sha2_256_finish, [temp_ctx] |
mov edi, [tx_iv] |
mov ebx, [con_ptr] |
lea edi, [ebx + sshlib_connection.tx_iv] |
mov esi, [temp_ctx] |
mov ecx, SHA2_256_LEN/4 |
rep movsd |
DEBUGF 1, "Remote IV: " |
stdcall dump_hex, [tx_iv], SHA2_256_LEN/4 |
;--------------------------------------------------------------- |
; Initial IV server to client: HASH(K || H || "B" || session_id) |
340,14 → 337,12 |
mov byte[edx], 'B' |
invoke sha2_256_update, [temp_ctx], edx, SHA2_256_LEN+1 |
invoke sha2_256_finish, [temp_ctx] |
mov edi, [rx_iv] |
mov ebx, [con_ptr] |
lea edi, [ebx + sshlib_connection.rx_iv] |
mov esi, [temp_ctx] |
mov ecx, SHA2_256_LEN/4 |
rep movsd |
DEBUGF 1, "Local IV: " |
stdcall dump_hex, [rx_iv], SHA2_256_LEN/4 |
;------------------------------------------------------------------- |
; Encryption key client to server: HASH(K || H || "C" || session_id) |
359,14 → 354,28 |
mov byte[edx], 'C' |
invoke sha2_256_update, [temp_ctx], edx, SHA2_256_LEN+1 |
invoke sha2_256_finish, [temp_ctx] |
mov edi, [tx_enc_key] |
mov ebx, [con_ptr] |
lea edi, [ebx+sshlib_connection.tx_enc_key] |
mov esi, [temp_ctx] |
mov ecx, SHA2_256_LEN/4 |
rep movsd |
DEBUGF 1, "Remote key: " |
stdcall dump_hex, [tx_enc_key], SHA2_256_LEN/4 |
mov esi, [k_h_ctx] |
mov edi, [temp_ctx] |
mov ecx, LIBCRASH_CTX_LEN/4 |
rep movsd |
mov ebx, [con_ptr] |
lea edi, [ebx+sshlib_connection.tx_enc_key] |
invoke sha2_256_update, [temp_ctx], edi, SHA2_256_LEN |
invoke sha2_256_finish, [temp_ctx] |
mov ebx, [con_ptr] |
add edi, 256/8 |
mov esi, [temp_ctx] |
mov ecx, SHA2_256_LEN/4 |
rep movsd |
;------------------------------------------------------------------- |
; Encryption key server to client: HASH(K || H || "D" || session_id) |
378,14 → 387,28 |
mov byte[edx], 'D' |
invoke sha2_256_update, [temp_ctx], edx, SHA2_256_LEN+1 |
invoke sha2_256_finish, [temp_ctx] |
mov edi, [rx_enc_key] |
mov ebx, [con_ptr] |
lea edi, [ebx+sshlib_connection.rx_enc_key] |
mov esi, [temp_ctx] |
mov ecx, SHA2_256_LEN/4 |
rep movsd |
DEBUGF 1, "Local key: " |
stdcall dump_hex, [rx_enc_key], SHA2_256_LEN/4 |
mov esi, [k_h_ctx] |
mov edi, [temp_ctx] |
mov ecx, LIBCRASH_CTX_LEN/4 |
rep movsd |
mov ebx, [con_ptr] |
lea edi, [ebx+sshlib_connection.rx_enc_key] |
invoke sha2_256_update, [temp_ctx], edi, SHA2_256_LEN |
invoke sha2_256_finish, [temp_ctx] |
mov ebx, [con_ptr] |
add edi, 256/8 |
mov esi, [temp_ctx] |
mov ecx, SHA2_256_LEN/4 |
rep movsd |
;------------------------------------------------------------------ |
; Integrity key client to server: HASH(K || H || "E" || session_id) |
397,14 → 420,12 |
mov byte[edx], 'E' |
invoke sha2_256_update, [temp_ctx], edx, SHA2_256_LEN+1 |
invoke sha2_256_finish, [temp_ctx] |
mov edi, [tx_int_key] |
mov ebx, [con_ptr] |
lea edi, [ebx + sshlib_connection.tx_int_key] |
mov esi, [temp_ctx] |
mov ecx, SHA2_256_LEN/4 |
rep movsd |
DEBUGF 1, "Remote Integrity key: " |
stdcall dump_hex, [tx_int_key], SHA2_256_LEN/4 |
;------------------------------------------------------------------ |
; Integrity key server to client: HASH(K || H || "F" || session_id) |
416,69 → 437,13 |
mov byte[edx], 'F' |
invoke sha2_256_update, [temp_ctx], edx, SHA2_256_LEN+1 |
invoke sha2_256_finish, [temp_ctx] |
mov edi, [rx_int_key] |
mov ebx, [con_ptr] |
lea edi, [ebx + sshlib_connection.rx_int_key] |
mov esi, [temp_ctx] |
mov ecx, SHA2_256_LEN/4 |
rep movsd |
DEBUGF 1, "Local Integrity key: " |
stdcall dump_hex, [rx_int_key] , SHA2_256_LEN/4 |
;------------------------------------- |
; << Parse Diffie-Hellman New Keys MSG |
stdcall sshlib_recv_packet, [con_ptr], 0 |
cmp eax, 0 |
jl .err |
mov ebx, [con_ptr] |
cmp [ebx + sshlib_connection.rx_buffer.message_code], SSH_MSG_NEWKEYS |
jne .err_proto |
DEBUGF 2, "Received New Keys\n" |
;------------------------------- |
; >> Reply with New Keys message |
stdcall sshlib_send_packet, [con_ptr], ssh_msg_new_keys, ssh_msg_new_keys.length, 0 |
cmp eax, 0 |
jl .err |
;---------------------------------------------- |
; Set keys and initialize transport subroutines |
DEBUGF 2, "SSH: Setting encryption keys\n" |
mov ebx, [con_ptr] |
stdcall aes256_ctr_init, [rx_iv] |
test eax, eax |
jz .err_nomem |
mov [ebx + sshlib_connection.rx_crypt_ctx_ptr], eax |
stdcall aes256_set_encrypt_key, eax, [rx_enc_key] |
mov [ebx + sshlib_connection.rx_crypt_proc], aes256_ctr_crypt |
mov [ebx + sshlib_connection.rx_crypt_blocksize], AES256_BLOCKSIZE |
stdcall aes256_ctr_init, [tx_iv] |
test eax, eax |
jz .err_nomem |
mov [ebx + sshlib_connection.tx_crypt_ctx_ptr], eax |
stdcall aes256_set_encrypt_key, eax, [tx_enc_key] |
mov [ebx + sshlib_connection.tx_crypt_proc], aes256_ctr_crypt |
mov [ebx + sshlib_connection.tx_crypt_blocksize], AES256_BLOCKSIZE |
mov [ebx + sshlib_connection.tx_pad_size], AES256_BLOCKSIZE |
mov [ebx + sshlib_connection.tx_pad_proc], MBRandom |
lea ecx, [ebx + sshlib_connection.rx_mac_ctx] |
stdcall hmac_sha256_setkey, ecx, [rx_int_key], SHA2_256_LEN |
mov [ebx + sshlib_connection.rx_mac_proc], hmac_sha256 |
mov [ebx + sshlib_connection.rx_mac_length], SHA2_256_LEN |
lea ecx, [ebx + sshlib_connection.tx_mac_ctx] |
stdcall hmac_sha256_setkey, ecx, [tx_int_key], SHA2_256_LEN |
mov [ebx + sshlib_connection.tx_mac_proc], hmac_sha256 |
mov [ebx + sshlib_connection.tx_mac_length], SHA2_256_LEN |
mov [ebx + sshlib_connection.status], SSHLIB_CON_STAT_KEX_DONE |
xor eax, eax |
485,7 → 450,7 |
.err: |
push eax |
xor eax, eax |
mov ecx, (7*(MAX_BITS/8+4) + 7*SHA2_256_LEN + 2*LIBCRASH_CTX_LEN)/4 |
mov ecx, (7*(MAX_BITS/8+4) + 2*LIBCRASH_CTX_LEN + 1*SHA2_256_LEN )/4 |
mov edi, [mpint_tmp] |
rep stosd |
/programs/network/ssh/sshlib_mcodes.inc |
---|
30,4 → 30,20 |
SSH_MSG_CHANNEL_CLOSE = 97 |
SSH_MSG_CHANNEL_REQUEST = 98 |
SSH_MSG_CHANNEL_SUCCESS = 99 |
SSH_MSG_CHANNEL_FAILURE = 100 |
SSH_MSG_CHANNEL_FAILURE = 100 |
SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT = 1 |
SSH_DISCONNECT_PROTOCOL_ERROR = 2 |
SSH_DISCONNECT_KEY_EXCHANGE_FAILED = 3 |
SSH_DISCONNECT_RESERVED = 4 |
SSH_DISCONNECT_MAC_ERROR = 5 |
SSH_DISCONNECT_COMPRESSION_ERROR = 6 |
SSH_DISCONNECT_SERVICE_NOT_AVAILABLE = 7 |
SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED = 8 |
SSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE = 9 |
SSH_DISCONNECT_CONNECTION_LOST = 10 |
SSH_DISCONNECT_BY_APPLICATION = 11 |
SSH_DISCONNECT_TOO_MANY_CONNECTIONS = 12 |
SSH_DISCONNECT_AUTH_CANCELLED_BY_USER = 13 |
SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE = 14 |
SSH_DISCONNECT_ILLEGAL_USER_NAME = 15 |
/programs/network/ssh/sshlib_transport.inc |
---|
1,6 → 1,6 |
; sshlib_transport.inc - SSH transport layer |
; |
; Copyright (C) 2016-2021 Jeffrey Amelynck |
; Copyright (C) 2016-2024 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 |
16,23 → 16,22 |
; along with this program. If not, see <http://www.gnu.org/licenses/>. |
proc sshlib_padd_null |
align 16 |
sshlib_recv_packet: ; con_ptr, flags |
xor eax, eax |
ret |
mov eax, [esp+4] |
jmp [eax+sshlib_connection.rx_proc] |
endp |
align 16 |
sshlib_send_packet: ; con_ptr, flags |
proc sshlib_crypt_null ctx, src, dst |
mov eax, [esp+4] |
jmp [eax+sshlib_connection.tx_proc] |
; Assume src == dst ! |
ret |
align 16 |
proc sshlib_recv_packet_clear con_ptr, flags |
endp |
proc sshlib_recv_packet con_ptr, flags |
locals |
data_length dd ? ; Total length of packet without MAC |
endl |
41,7 → 40,7 |
; Receive first block (Read length, padding length, message code) |
mov ebx, [con_ptr] |
mov ecx, [ebx+sshlib_connection.socketnum] |
mov esi, [ebx+sshlib_connection.rx_crypt_blocksize] |
mov esi, 4 |
lea edx, [ebx+sshlib_connection.rx_buffer] |
mov edi, [flags] |
mcall recv |
50,15 → 49,9 |
sub [ssh_chan.rcv_wnd], eax ;;; FIXME |
DEBUGF 1, "chunk = %u ", eax |
mov ebx, [con_ptr] |
cmp eax, [ebx+sshlib_connection.rx_crypt_blocksize] |
cmp eax, 4 |
jne .proto_fail ; TODO: handle receives of 1, 2, and 3 bytes correctly |
; Decrypt first block |
pusha |
lea esi, [ebx+sshlib_connection.rx_buffer] |
stdcall [ebx+sshlib_connection.rx_crypt_proc], [ebx+sshlib_connection.rx_crypt_ctx_ptr], esi, esi |
popa |
; Check data length |
mov esi, [ebx + sshlib_connection.rx_buffer.packet_length] |
bswap esi ; convert length to little endian |
66,16 → 59,12 |
DEBUGF 1, "packet length=%u ", esi |
cmp esi, BUFFERSIZE |
ja .proto_fail ; packet is too large |
test ecx, ecx |
jz .proto_fail |
; Calculate amount of remaining data |
add esi, 4 ; Packet length field itself is not included in the count |
sub esi, [ebx+sshlib_connection.rx_crypt_blocksize] ; Already received this amount of data |
add esi, [ebx+sshlib_connection.rx_mac_length] |
jz .packet_complete |
; Receive remaining data |
lea edx, [ebx+sshlib_connection.rx_buffer] |
add edx, [ebx+sshlib_connection.rx_crypt_blocksize] |
add edx, 4 |
mov ecx, [ebx+sshlib_connection.socketnum] |
mov edi, [flags] |
.receive_loop: |
88,60 → 77,21 |
add edx, eax |
sub esi, eax |
jnz .receive_loop |
.packet_complete: |
; Decrypt data |
; Return useful data length to the caller via eax register |
mov ebx, [con_ptr] |
mov ecx, [ebx + sshlib_connection.rx_buffer.packet_length] |
add ecx, 4 ; Packet_length field itself |
sub ecx, [ebx+sshlib_connection.rx_crypt_blocksize] ; Already decrypted this amount of data |
jz .decrypt_complete |
mov eax, [ebx + sshlib_connection.rx_buffer.packet_length] |
movzx ebx, [ebx + sshlib_connection.rx_buffer.padding_length] |
sub eax, ebx |
lea esi, [ebx+sshlib_connection.rx_buffer] |
add esi, [ebx+sshlib_connection.rx_crypt_blocksize] |
.decrypt_loop: |
pusha |
stdcall [ebx+sshlib_connection.rx_crypt_proc], [ebx+sshlib_connection.rx_crypt_ctx_ptr], esi, esi |
popa |
add esi, [ebx+sshlib_connection.rx_crypt_blocksize] |
sub ecx, [ebx+sshlib_connection.rx_crypt_blocksize] |
jnz .decrypt_loop |
.decrypt_complete: |
; Authenticate message |
cmp [ebx+sshlib_connection.rx_mac_proc], 0 |
je .mac_complete |
lea esi, [ebx+sshlib_connection.rx_mac_seqnr] |
mov ecx, [ebx+sshlib_connection.rx_buffer.packet_length] |
add ecx, 8 ; packet_length field itself + sequence number |
lea eax, [ebx+sshlib_connection.rx_mac_ctx] |
; push [ebx+sshlib_connection.rx_buffer.packet_length] |
mov edx, [ebx+sshlib_connection.rx_buffer.packet_length] |
bswap edx ; convert length to big endian |
mov [ebx+sshlib_connection.rx_buffer.packet_length], edx |
stdcall [ebx+sshlib_connection.rx_mac_proc], eax, esi, ecx |
; pop [ebx+sshlib_connection.rx_buffer.packet_length] |
mov edx, [ebx+sshlib_connection.rx_buffer.packet_length] |
bswap edx ; convert length to little endian |
mov [ebx+sshlib_connection.rx_buffer.packet_length], edx |
lea esi, [ebx+sshlib_connection.rx_mac_ctx] |
lea edi, [ebx+sshlib_connection.rx_buffer+4] |
add edi, [ebx+sshlib_connection.rx_buffer.packet_length] |
mov ecx, [ebx+sshlib_connection.rx_mac_length] |
shr ecx, 2 |
repe cmpsd |
jne .mac_fail |
.mac_complete: |
add byte[ebx+sshlib_connection.rx_mac_seqnr+3], 1 ; Update sequence counter |
; Update sequence counter |
mov ebx, [con_ptr] |
add byte[ebx + sshlib_connection.rx_mac_seqnr+3], 1 |
adc byte[ebx+sshlib_connection.rx_mac_seqnr+2], 0 |
adc byte[ebx+sshlib_connection.rx_mac_seqnr+1], 0 |
adc byte[ebx+sshlib_connection.rx_mac_seqnr+0], 0 |
; Return useful data length to the caller via eax register |
.packet_complete: |
mov eax, [ebx+sshlib_connection.rx_buffer.packet_length] |
movzx ebx, [ebx+sshlib_connection.rx_buffer.padding_length] |
sub eax, ebx |
DEBUGF 1, "useful data length=%u\n", eax |
ret |
150,12 → 100,6 |
mov eax, SSHLIB_ERR_SOCKET |
ret |
.mac_fail: |
DEBUGF 3, "ssh_recv_packet message authentication failed!\n" |
mov eax, SSHLIB_ERR_MAC_VERIFY_FAIL |
xor ebx, ebx |
ret |
.proto_fail: |
DEBUGF 3, "ssh_recv_packet protocol failure!\n" |
mov eax, SSHLIB_ERR_PROTOCOL |
165,7 → 109,8 |
endp |
proc sshlib_send_packet con_ptr, buf, payload_size, flags |
align 16 |
proc sshlib_send_packet_clear con_ptr, buf, payload_size, flags |
locals |
packet_size dd ? |
191,7 → 136,7 |
; Start building the packet |
; First comes the packet length, in network byte order ofcourse. |
add eax, edx |
DEBUGF 1, "total size: %u ", eax |
DEBUGF 2, "total size: %u ", eax |
bswap eax |
lea edi, [ecx+sshlib_connection.tx_buffer] |
stosd |
212,63 → 157,32 |
mov ebx, edx |
and ebx, 3 |
inc ebx ; number bytes in first write (1-4) |
mov edx, [con_ptr] |
call [edx+sshlib_connection.tx_pad_proc] |
mov dword[edi], eax |
mov dword[edi], 0 |
add edi, ebx |
; Then, do as many aligned writes as nescessary |
mov ebx, [con_ptr] |
xor eax, eax |
@@: |
call [ebx+sshlib_connection.tx_pad_proc] |
stosd |
dec esi |
jnz @r |
; Append the packet with Message Authentication Code |
mov edx, [con_ptr] |
cmp [edx+sshlib_connection.tx_mac_proc], 0 |
je .mac_complete |
DEBUGF 1, "MAC sequence number: 0x%x\n", [edx+sshlib_connection.tx_mac_seqnr] |
lea esi, [edx+sshlib_connection.tx_mac_seqnr] |
mov ecx, [packet_size] |
add ecx, 4 ; Sequence number length |
lea eax, [edx+sshlib_connection.tx_mac_ctx] |
stdcall [edx+sshlib_connection.tx_mac_proc], eax, esi, ecx |
lea esi, [edx+sshlib_connection.tx_mac_ctx] |
lea edi, [edx+sshlib_connection.tx_buffer] |
add edi, [packet_size] |
mov ecx, [edx+sshlib_connection.tx_mac_length] |
shr ecx, 2 |
rep movsd |
.mac_complete: |
add byte[edx+sshlib_connection.tx_mac_seqnr+3], 1 ; Update sequence counter |
adc byte[edx+sshlib_connection.tx_mac_seqnr+2], 0 |
adc byte[edx+sshlib_connection.tx_mac_seqnr+1], 0 |
adc byte[edx+sshlib_connection.tx_mac_seqnr+0], 0 |
; Now, encrypt everything but MAC |
lea esi, [edx+sshlib_connection.tx_buffer] |
mov ecx, [packet_size] |
.encrypt_loop: |
pusha |
stdcall [edx+sshlib_connection.tx_crypt_proc], [edx+sshlib_connection.tx_crypt_ctx_ptr], esi, esi |
popa |
add esi, [edx+sshlib_connection.tx_crypt_blocksize] |
sub ecx, [edx+sshlib_connection.tx_crypt_blocksize] |
jnz .encrypt_loop |
; Send the packet |
mov ebx, [con_ptr] |
mov ecx, [ebx+sshlib_connection.socketnum] |
lea edx, [ebx+sshlib_connection.tx_buffer] |
mov esi, [packet_size] |
add esi, [ebx+sshlib_connection.tx_mac_length] |
mov edi, [flags] |
mcall send |
DEBUGF 1, "\n" |
; Update sequence counter |
mov ebx, [con_ptr] |
add byte[ebx + sshlib_connection.tx_mac_seqnr+3], 1 |
adc byte[ebx + sshlib_connection.tx_mac_seqnr+2], 0 |
adc byte[ebx + sshlib_connection.tx_mac_seqnr+1], 0 |
adc byte[ebx + sshlib_connection.tx_mac_seqnr+0], 0 |
DEBUGF 2, "\n" |
ret |
endp |
/programs/network/ssh/sshlib_transport_hmac.inc |
---|
0,0 → 1,257 |
; sshlib_transport.inc - SSH transport layer |
; |
; Copyright (C) 2016-2024 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/>. |
align 16 |
proc sshlib_recv_packet_hmac con_ptr, flags |
locals |
data_length dd ? ; Total length of packet without MAC |
endl |
DEBUGF 3, "> " |
; Receive first block |
mov ebx, [con_ptr] |
mov ecx, [ebx + sshlib_connection.socketnum] |
mov esi, [ebx + sshlib_connection.rx_crypt_blocksize] |
lea edx, [ebx + sshlib_connection.rx_buffer] |
mov edi, [flags] |
mcall recv |
cmp eax, 0 |
jle .sock_fail |
sub [ssh_chan.rcv_wnd], eax ;;; FIXME |
DEBUGF 2, "chunk = %u ", eax |
mov ebx, [con_ptr] |
cmp eax, [ebx + sshlib_connection.rx_crypt_blocksize] |
jne .proto_fail ; TODO: handle receives of 1, 2, and 3 bytes correctly |
; Decrypt first block |
pusha |
lea esi, [ebx + sshlib_connection.rx_buffer] |
lea ecx, [ebx + sshlib_connection.rx_crypt_ctx] |
stdcall [ebx + sshlib_connection.rx_crypt_proc], ecx, esi, eax, esi |
popa |
; Check data length |
mov esi, [ebx + sshlib_connection.rx_buffer.packet_length] |
bswap esi ; convert length to little endian |
mov [ebx + sshlib_connection.rx_buffer.packet_length], esi |
DEBUGF 2, "packet length=%u ", esi |
cmp esi, BUFFERSIZE |
ja .proto_fail ; packet is too large |
; Calculate amount of remaining data |
add esi, 4 ; Packet length field itself is not included in the count |
sub esi, [ebx + sshlib_connection.rx_crypt_blocksize] ; Already received this amount of data |
add esi, [ebx + sshlib_connection.rx_mac_length] |
jz .packet_complete |
; Receive remaining data |
lea edx, [ebx + sshlib_connection.rx_buffer] |
add edx, [ebx + sshlib_connection.rx_crypt_blocksize] |
mov ecx, [ebx + sshlib_connection.socketnum] |
mov edi, [flags] |
.receive_loop: |
DEBUGF 3, "want %d bytes.. ", esi |
mcall recv |
cmp eax, 0 |
jle .sock_fail |
sub [ssh_chan.rcv_wnd], eax ;;; FIXME |
DEBUGF 3, "got %d bytes\n", eax |
add edx, eax |
sub esi, eax |
jnz .receive_loop |
.packet_complete: |
; Decrypt data |
mov ebx, [con_ptr] |
mov ecx, [ebx + sshlib_connection.rx_buffer.packet_length] |
add ecx, 4 ; Packet_length field itself |
sub ecx, [ebx + sshlib_connection.rx_crypt_blocksize] ; Already decrypted this amount of data |
jz .decrypt_complete |
lea esi, [ebx + sshlib_connection.rx_buffer] |
add esi, [ebx + sshlib_connection.rx_crypt_blocksize] |
pusha |
lea eax, [ebx + sshlib_connection.rx_crypt_ctx] |
stdcall [ebx + sshlib_connection.rx_crypt_proc], eax, esi, ecx, esi |
popa |
.decrypt_complete: |
; Authenticate message |
lea esi, [ebx + sshlib_connection.rx_mac_seqnr] |
mov ecx, [ebx + sshlib_connection.rx_buffer.packet_length] |
add ecx, 8 ; packet_length field itself + sequence number |
lea eax, [ebx + sshlib_connection.rx_mac_ctx] |
mov edx, [ebx + sshlib_connection.rx_buffer.packet_length] |
bswap edx ; convert length to big endian |
mov [ebx + sshlib_connection.rx_buffer.packet_length], edx |
lea edx, [ebx + sshlib_connection.rx_int_key] |
stdcall [ebx + sshlib_connection.rx_mac_proc], eax, esi, ecx, edx, SHA2_256_LEN |
mov edx, [ebx + sshlib_connection.rx_buffer.packet_length] |
bswap edx ; convert length to little endian |
mov [ebx + sshlib_connection.rx_buffer.packet_length], edx |
lea esi, [ebx + sshlib_connection.rx_mac_ctx] |
lea edi, [ebx + sshlib_connection.rx_buffer+4] |
add edi, [ebx + sshlib_connection.rx_buffer.packet_length] |
mov ecx, [ebx + sshlib_connection.rx_mac_length] |
shr ecx, 2 |
repe cmpsd ; TODO: constant time |
jne .mac_fail |
; Return useful data length to the caller via eax register |
mov eax, [ebx + sshlib_connection.rx_buffer.packet_length] |
movzx ebx, [ebx + sshlib_connection.rx_buffer.padding_length] |
sub eax, ebx |
; Update sequence counter |
mov ebx, [con_ptr] |
add byte[ebx + sshlib_connection.rx_mac_seqnr+3], 1 |
adc byte[ebx + sshlib_connection.rx_mac_seqnr+2], 0 |
adc byte[ebx + sshlib_connection.rx_mac_seqnr+1], 0 |
adc byte[ebx + sshlib_connection.rx_mac_seqnr+0], 0 |
DEBUGF 1, "useful data length=%u\n", eax |
ret |
.sock_fail: |
DEBUGF 3, "ssh_recv_packet failed!\n" |
mov eax, SSHLIB_ERR_SOCKET |
ret |
.mac_fail: |
DEBUGF 3, "ssh_recv_packet message authentication failed!\n" |
mov eax, SSHLIB_ERR_MAC_VERIFY_FAIL |
xor ebx, ebx |
ret |
.proto_fail: |
DEBUGF 3, "ssh_recv_packet protocol failure!\n" |
mov eax, SSHLIB_ERR_PROTOCOL |
xor ebx, ebx |
ret |
endp |
align 16 |
proc sshlib_send_packet_hmac con_ptr, buf, payload_size, flags |
locals |
packet_size dd ? |
endl |
DEBUGF 2, "< " |
; Check how many bytes we should pad |
mov eax, [payload_size] |
inc eax ; padding length byte |
lea edx, [eax+4] ; total packet size (without padding and MAC) |
mov [packet_size], edx |
mov ecx, [con_ptr] |
; mov edx, eax;;;;;;;;;;;;;;; |
mov ebx, [ecx+sshlib_connection.tx_pad_size] |
dec ebx |
and edx, ebx |
neg edx |
add edx, [ecx+sshlib_connection.tx_pad_size] |
add edx, [ecx+sshlib_connection.tx_pad_size] |
DEBUGF 1, "padding %u bytes ", edx |
add [packet_size], edx ; total packet size with padding |
; Start building the packet |
; First comes the packet length, in network byte order ofcourse. |
add eax, edx |
DEBUGF 2, "total size: %u ", eax |
bswap eax |
lea edi, [ecx+sshlib_connection.tx_buffer] |
stosd |
; Then the padding length |
mov al, dl |
stosb |
; And the actual payload bytes |
mov esi, [buf] |
mov ecx, [payload_size] |
rep movsb |
; Append the packet with #edx padding bytes. |
; Since we must pad at least 8 bytes, we can always use DWORD writes. |
; First do an (unaligned) write exactly following the data |
dec edx |
mov esi, edx |
shr esi, 2 ; number dwords |
mov ebx, edx |
and ebx, 3 |
inc ebx ; number bytes in first write (1-4) |
call MBRandom |
mov dword[edi], eax |
add edi, ebx |
; Then, do as many aligned writes as nescessary |
@@: |
call MBRandom |
stosd |
dec esi |
jnz @r |
; Append the packet with Message Authentication Code |
mov ebx, [con_ptr] |
DEBUGF 1, "MAC sequence number: 0x%x\n", [ebx + sshlib_connection.tx_mac_seqnr] |
lea esi, [ebx + sshlib_connection.tx_mac_seqnr] |
mov ecx, [packet_size] |
add ecx, 4 ; Sequence number length |
lea eax, [ebx + sshlib_connection.tx_mac_ctx] |
lea edx, [ebx + sshlib_connection.tx_int_key] |
stdcall [ebx + sshlib_connection.tx_mac_proc], eax, esi, ecx, edx, SHA2_256_LEN |
mov ebx, [con_ptr] |
lea esi, [ebx + sshlib_connection.tx_mac_ctx] |
lea edi, [ebx + sshlib_connection.tx_buffer] |
add edi, [packet_size] |
mov ecx, [ebx + sshlib_connection.tx_mac_length] |
shr ecx, 2 |
rep movsd |
; Now, encrypt everything but MAC |
lea esi, [ebx + sshlib_connection.tx_buffer] |
lea eax, [ebx + sshlib_connection.tx_crypt_ctx] |
stdcall [ebx + sshlib_connection.tx_crypt_proc], eax, esi, [packet_size], esi |
; Send the packet |
mov ebx, [con_ptr] |
mov ecx, [ebx + sshlib_connection.socketnum] |
lea edx, [ebx + sshlib_connection.tx_buffer] |
mov esi, [packet_size] |
add esi, [ebx + sshlib_connection.tx_mac_length] |
mov edi, [flags] |
mcall send |
; Update sequence counter |
mov ebx, [con_ptr] |
add byte[ebx + sshlib_connection.tx_mac_seqnr+3], 1 |
adc byte[ebx + sshlib_connection.tx_mac_seqnr+2], 0 |
adc byte[ebx + sshlib_connection.tx_mac_seqnr+1], 0 |
adc byte[ebx + sshlib_connection.tx_mac_seqnr+0], 0 |
DEBUGF 2, "\n" |
ret |
endp |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/programs/network/ssh/sshlib_transport_polychacha.inc |
---|
0,0 → 1,290 |
; sshlib_transport.inc - SSH transport layer |
; |
; Copyright (C) 2016-2024 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/>. |
iglobal |
align 16 |
null_bytes: times 64 db 0 |
endg |
align 16 |
proc sshlib_recv_packet_poly1305chacha20 con_ptr, flags |
locals |
data_length dd ? ; Total length of packet without MAC |
mac_otk rb 64 ;256/8 |
iv rd 4 |
endl |
DEBUGF 3, "> " |
; Receive first block (Read length) |
mov ebx, [con_ptr] |
mov ecx, [ebx+sshlib_connection.socketnum] |
mov esi, 4 |
lea edx, [ebx+sshlib_connection.rx_buffer] |
mov edi, [flags] |
mcall recv |
cmp eax, 0 |
jle .sock_fail |
sub [ssh_chan.rcv_wnd], eax ;;; FIXME |
DEBUGF 1, "chunk = %u ", eax |
mov ebx, [con_ptr] |
cmp eax, 4 |
jne .proto_fail ; TODO: handle receives of 1, 2, and 3 bytes correctly |
; Decrypt data length |
mov ebx, [con_ptr] |
lea eax, [iv] |
mov dword[eax+0], 0 |
mov dword[eax+4], 0 |
mov dword[eax+8], 0 |
push [ebx+sshlib_connection.rx_mac_seqnr] |
pop dword[eax+12] |
lea ecx, [ebx+sshlib_connection.rx_crypt_ctx] |
lea edx, [ebx+sshlib_connection.rx_enc_key+256/8] |
lea esi, [ebx+sshlib_connection.rx_buffer] |
lea edi, [data_length] |
invoke chacha20_oneshot, ecx, edx, eax, 0, esi, 4, edi |
mov eax, [data_length] |
bswap eax |
mov [data_length], eax |
DEBUGF 2, "decrypted packet length=%u\n", [data_length] |
cmp eax, BUFFERSIZE-4-128/8 |
ja .proto_fail |
; Receive remaining data |
lea edx, [ebx+sshlib_connection.rx_buffer+4] |
mov ecx, [ebx+sshlib_connection.socketnum] |
mov edi, [flags] |
lea esi, [eax + 128/8] ; We already got 4 bytes but they are not counted, MAC is also not counted so add that |
.recv_loop: |
DEBUGF 3, "want %u bytes.. ", esi |
mcall recv |
cmp eax, 0 |
jle .sock_fail |
sub [ssh_chan.rcv_wnd], eax ;;; FIXME |
DEBUGF 3, "got %u bytes\n", eax |
add edx, eax |
sub esi, eax |
jnz .recv_loop |
; Calculate the OTK |
mov ebx, [con_ptr] |
lea eax, [ebx+sshlib_connection.rx_crypt_ctx] |
lea esi, [ebx+sshlib_connection.rx_enc_key] |
lea edx, [mac_otk] |
lea ecx, [iv] |
invoke chacha20_oneshot, eax, esi, ecx, 0, null_bytes, 64, edx |
; Calculate the MAC |
lea esi, [ebx+sshlib_connection.rx_mac_ctx] |
lea edi, [ebx+sshlib_connection.rx_buffer] |
mov ecx, [data_length] |
add ecx, 4 |
lea edx, [mac_otk] |
push ecx |
invoke poly1305_oneshot, esi, edi, ecx, edx, 256/8 |
pop ecx |
; Compare in constant time |
add edi, ecx |
cmpsd |
lahf |
mov edx, eax |
cmpsd |
lahf |
and edx, eax |
cmpsd |
lahf |
and edx, eax |
cmpsd |
lahf |
and eax, edx |
sahf |
jne .mac_fail |
; Decrypt the payload |
lea eax, [ebx+sshlib_connection.rx_crypt_ctx] |
lea edi, [ebx+sshlib_connection.rx_buffer+4] |
invoke chacha20_update, eax, edi, [data_length], edi |
; Put decrypted length in rx buffer |
push [data_length] |
pop dword[ebx+sshlib_connection.rx_buffer] |
; Update sequence counter |
add byte[ebx+sshlib_connection.rx_mac_seqnr+3], 1 |
adc byte[ebx+sshlib_connection.rx_mac_seqnr+2], 0 |
adc byte[ebx+sshlib_connection.rx_mac_seqnr+1], 0 |
adc byte[ebx+sshlib_connection.rx_mac_seqnr+0], 0 |
; Return useful data length to the caller via eax register |
;;; .packet_complete: |
mov eax, [ebx+sshlib_connection.rx_buffer.packet_length] |
movzx ebx, [ebx+sshlib_connection.rx_buffer.padding_length] |
sub eax, ebx |
DEBUGF 1, "useful data length=%u\n", eax |
ret |
.sock_fail: |
DEBUGF 3, "ssh_recv_packet failed!\n" |
mov eax, SSHLIB_ERR_SOCKET |
ret |
.mac_fail: |
DEBUGF 3, "ssh_recv_packet message authentication failed!\n" |
mov eax, SSHLIB_ERR_MAC_VERIFY_FAIL |
xor ebx, ebx |
ret |
.proto_fail: |
DEBUGF 3, "ssh_recv_packet protocol failure!\n" |
mov eax, SSHLIB_ERR_PROTOCOL |
xor ebx, ebx |
ret |
endp |
align 16 |
proc sshlib_send_packet_poly1305chacha20 con_ptr, buf, payload_size, flags |
locals |
packet_size dd ? |
mac_otk rb 64 ;256/8 |
iv rd 4 |
endl |
DEBUGF 2, "< " |
; Check how many bytes we should pad |
mov eax, [payload_size] |
inc eax ; padding length byte |
lea edx, [eax+4] ; total packet size without padding and MAC |
mov [packet_size], edx |
mov ecx, [con_ptr] |
mov edx, eax |
mov ebx, [ecx+sshlib_connection.tx_pad_size] |
dec ebx |
and edx, ebx |
neg edx |
add edx, [ecx+sshlib_connection.tx_pad_size] |
add edx, [ecx+sshlib_connection.tx_pad_size] |
DEBUGF 2, "padding %u bytes ", edx |
add [packet_size], edx ; total packet size with padding, without MAC |
; Start building the packet |
; First comes the packet length, in network byte order ofcourse. |
add eax, edx |
DEBUGF 2, "total size: %u ", eax |
bswap eax |
lea edi, [ecx+sshlib_connection.tx_buffer] |
stosd |
; Then the padding length |
mov al, dl |
stosb |
;;; And the actual payload bytes |
mov esi, [buf] |
mov ecx, [payload_size] |
rep movsb |
; Append the packet with #edx padding bytes. |
; Since we must pad at least 8 bytes, we can always use DWORD writes. |
; First do an (unaligned) write exactly following the data |
dec edx |
mov esi, edx |
shr esi, 2 ; number dwords |
mov ebx, edx |
and ebx, 3 |
inc ebx ; number bytes in first write (1-4) |
mov edx, [con_ptr] |
call MBRandom |
mov dword[edi], eax |
add edi, ebx |
; Then, do as many aligned writes as nescessary |
mov ebx, [con_ptr] |
@@: |
call MBRandom |
stosd |
dec esi |
jnz @r |
; Encrypt data length |
lea eax, [iv] |
mov dword[eax+0], 0 |
mov dword[eax+4], 0 |
mov dword[eax+8], 0 |
push [ebx+sshlib_connection.tx_mac_seqnr] |
pop dword[eax+12] |
lea esi, [ebx+sshlib_connection.tx_crypt_ctx] |
lea edx, [ebx+sshlib_connection.tx_enc_key+256/8] |
lea edi, [ebx+sshlib_connection.tx_buffer] |
invoke chacha20_oneshot, esi, edx, eax, 0, edi, 4, edi |
; Calculate the OTK |
lea eax, [iv] |
lea edx, [ebx+sshlib_connection.tx_enc_key] |
lea edi, [mac_otk] |
invoke chacha20_oneshot, esi, edx, eax, 0, null_bytes, 64, edi |
; Encrypt the payload |
lea edi, [ebx+sshlib_connection.tx_buffer+4] |
mov eax, [packet_size] |
sub eax, 4 |
invoke chacha20_update, esi, edi, eax, edi |
; Calculate the MAC |
lea esi, [ebx+sshlib_connection.tx_mac_ctx] |
lea edi, [ebx+sshlib_connection.tx_buffer] |
lea edx, [mac_otk] |
invoke poly1305_oneshot, esi, edi, [packet_size], edx, 256/8 |
; Write it to the send buffer |
add edi, [packet_size] |
movsd |
movsd |
movsd |
movsd |
; Update sequence counter |
add byte[ebx+sshlib_connection.tx_mac_seqnr+3], 1 |
adc byte[ebx+sshlib_connection.tx_mac_seqnr+2], 0 |
adc byte[ebx+sshlib_connection.tx_mac_seqnr+1], 0 |
adc byte[ebx+sshlib_connection.tx_mac_seqnr+0], 0 |
; Send the packet |
; mov ebx, [con_ptr] |
mov ecx, [ebx+sshlib_connection.socketnum] |
lea edx, [ebx+sshlib_connection.tx_buffer] |
mov esi, [packet_size] |
add esi, 16 ;[ebx+sshlib_connection.tx_mac_length] |
mov edi, [flags] |
mcall send |
DEBUGF 2, "\n" |
ret |
endp |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |