Subversion Repositories Kolibri OS

Rev

Rev 9071 | Rev 9987 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
9106 hidnplayr 1
;    sshlib_transport.inc - SSH transport layer
6419 hidnplayr 2
;
9070 hidnplayr 3
;    Copyright (C) 2016-2021 Jeffrey Amelynck
6419 hidnplayr 4
;
5
;    This program is free software: you can redistribute it and/or modify
6
;    it under the terms of the GNU General Public License as published by
7
;    the Free Software Foundation, either version 3 of the License, or
8
;    (at your option) any later version.
9
;
10
;    This program is distributed in the hope that it will be useful,
11
;    but WITHOUT ANY WARRANTY; without even the implied warranty of
12
;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
;    GNU General Public License for more details.
14
;
15
;    You should have received a copy of the GNU General Public License
16
;    along with this program.  If not, see .
17
 
6469 hidnplayr 18
 
9106 hidnplayr 19
proc sshlib_padd_null
6469 hidnplayr 20
 
9106 hidnplayr 21
        xor     eax, eax
22
        ret
6419 hidnplayr 23
 
9106 hidnplayr 24
endp
6419 hidnplayr 25
 
9106 hidnplayr 26
proc sshlib_crypt_null ctx, src, dst
27
 
28
; Assume src == dst !
29
 
9071 hidnplayr 30
        ret
31
 
32
endp
33
 
9106 hidnplayr 34
proc sshlib_recv_packet con_ptr, flags
6419 hidnplayr 35
 
36
locals
6469 hidnplayr 37
        data_length     dd ?    ; Total length of packet without MAC
6419 hidnplayr 38
endl
39
 
9106 hidnplayr 40
        DEBUGF  3, "> "
6419 hidnplayr 41
; Receive first block (Read length, padding length, message code)
9106 hidnplayr 42
        mov     ebx, [con_ptr]
43
        mov     ecx, [ebx+sshlib_connection.socketnum]
44
        mov     esi, [ebx+sshlib_connection.rx_crypt_blocksize]
45
        lea     edx, [ebx+sshlib_connection.rx_buffer]
6469 hidnplayr 46
        mov     edi, [flags]
47
        mcall   recv
9106 hidnplayr 48
        cmp     eax, 0
49
        jle     .sock_fail
50
        sub     [ssh_chan.rcv_wnd], eax  ;;; FIXME
6469 hidnplayr 51
        DEBUGF  1, "chunk = %u ", eax
9106 hidnplayr 52
        mov     ebx, [con_ptr]
53
        cmp     eax, [ebx+sshlib_connection.rx_crypt_blocksize]
54
        jne     .proto_fail     ; TODO: handle receives of 1, 2, and 3 bytes correctly
6419 hidnplayr 55
 
6469 hidnplayr 56
; Decrypt first block
57
        pusha
9106 hidnplayr 58
        lea     esi, [ebx+sshlib_connection.rx_buffer]
59
        stdcall [ebx+sshlib_connection.rx_crypt_proc], [ebx+sshlib_connection.rx_crypt_ctx_ptr], esi, esi
6469 hidnplayr 60
        popa
6419 hidnplayr 61
 
6469 hidnplayr 62
; Check data length
9106 hidnplayr 63
        mov     esi, [ebx + sshlib_connection.rx_buffer.packet_length]
6469 hidnplayr 64
        bswap   esi                                             ; convert length to little endian
9106 hidnplayr 65
        mov     [ebx+sshlib_connection.rx_buffer.packet_length], esi
6469 hidnplayr 66
        DEBUGF  1, "packet length=%u ", esi
67
        cmp     esi, BUFFERSIZE
9106 hidnplayr 68
        ja      .proto_fail                                     ; packet is too large
6419 hidnplayr 69
 
6469 hidnplayr 70
; Calculate amount of remaining data
71
        add     esi, 4                                          ; Packet length field itself is not included in the count
9106 hidnplayr 72
        sub     esi, [ebx+sshlib_connection.rx_crypt_blocksize]    ; Already received this amount of data
73
        add     esi, [ebx+sshlib_connection.rx_mac_length]
74
        jz      .packet_complete
6419 hidnplayr 75
 
6469 hidnplayr 76
; Receive remaining data
9106 hidnplayr 77
        lea     edx, [ebx+sshlib_connection.rx_buffer]
78
        add     edx, [ebx+sshlib_connection.rx_crypt_blocksize]
79
        mov     ecx, [ebx+sshlib_connection.socketnum]
6469 hidnplayr 80
        mov     edi, [flags]
6419 hidnplayr 81
  .receive_loop:
9106 hidnplayr 82
        DEBUGF  3, "want %d bytes.. ", esi
6469 hidnplayr 83
        mcall   recv
6419 hidnplayr 84
        cmp     eax, 0
9106 hidnplayr 85
        jle     .sock_fail
86
        sub     [ssh_chan.rcv_wnd], eax             ;;; FIXME
87
        DEBUGF  3, "got %d bytes\n", eax
6469 hidnplayr 88
        add     edx, eax
89
        sub     esi, eax
90
        jnz     .receive_loop
6419 hidnplayr 91
 
6469 hidnplayr 92
; Decrypt data
9106 hidnplayr 93
        mov     ebx, [con_ptr]
94
        mov     ecx, [ebx + sshlib_connection.rx_buffer.packet_length]
6469 hidnplayr 95
        add     ecx, 4                                          ; Packet_length field itself
9106 hidnplayr 96
        sub     ecx, [ebx+sshlib_connection.rx_crypt_blocksize]    ; Already decrypted this amount of data
6469 hidnplayr 97
        jz      .decrypt_complete
6419 hidnplayr 98
 
9106 hidnplayr 99
        lea     esi, [ebx+sshlib_connection.rx_buffer]
100
        add     esi, [ebx+sshlib_connection.rx_crypt_blocksize]
6469 hidnplayr 101
  .decrypt_loop:
102
        pusha
9106 hidnplayr 103
        stdcall [ebx+sshlib_connection.rx_crypt_proc], [ebx+sshlib_connection.rx_crypt_ctx_ptr], esi, esi
6469 hidnplayr 104
        popa
9106 hidnplayr 105
        add     esi, [ebx+sshlib_connection.rx_crypt_blocksize]
106
        sub     ecx, [ebx+sshlib_connection.rx_crypt_blocksize]
6469 hidnplayr 107
        jnz     .decrypt_loop
108
  .decrypt_complete:
6419 hidnplayr 109
 
6469 hidnplayr 110
; Authenticate message
9106 hidnplayr 111
        cmp     [ebx+sshlib_connection.rx_mac_proc], 0
6469 hidnplayr 112
        je      .mac_complete
9106 hidnplayr 113
        lea     esi, [ebx+sshlib_connection.rx_mac_seqnr]
114
        mov     ecx, [ebx+sshlib_connection.rx_buffer.packet_length]
6469 hidnplayr 115
        add     ecx, 8                                          ; packet_length field itself + sequence number
9106 hidnplayr 116
        lea     eax, [ebx+sshlib_connection.rx_mac_ctx]
117
;        push    [ebx+sshlib_connection.rx_buffer.packet_length]
118
        mov     edx, [ebx+sshlib_connection.rx_buffer.packet_length]
6469 hidnplayr 119
        bswap   edx                                             ; convert length to big endian
9106 hidnplayr 120
        mov     [ebx+sshlib_connection.rx_buffer.packet_length], edx
121
        stdcall [ebx+sshlib_connection.rx_mac_proc], eax, esi, ecx
122
;        pop     [ebx+sshlib_connection.rx_buffer.packet_length]
123
        mov     edx, [ebx+sshlib_connection.rx_buffer.packet_length]
6469 hidnplayr 124
        bswap   edx                                             ; convert length to little endian
9106 hidnplayr 125
        mov     [ebx+sshlib_connection.rx_buffer.packet_length], edx
6469 hidnplayr 126
 
9106 hidnplayr 127
        lea     esi, [ebx+sshlib_connection.rx_mac_ctx]
128
        lea     edi, [ebx+sshlib_connection.rx_buffer+4]
129
        add     edi, [ebx+sshlib_connection.rx_buffer.packet_length]
130
        mov     ecx, [ebx+sshlib_connection.rx_mac_length]
6469 hidnplayr 131
        shr     ecx, 2
132
        repe cmpsd
9106 hidnplayr 133
        jne     .mac_fail
6469 hidnplayr 134
  .mac_complete:
9106 hidnplayr 135
        add     byte[ebx+sshlib_connection.rx_mac_seqnr+3], 1      ; Update sequence counter
136
        adc     byte[ebx+sshlib_connection.rx_mac_seqnr+2], 0
137
        adc     byte[ebx+sshlib_connection.rx_mac_seqnr+1], 0
138
        adc     byte[ebx+sshlib_connection.rx_mac_seqnr+0], 0
6469 hidnplayr 139
 
140
; Return useful data length to the caller via eax register
9106 hidnplayr 141
  .packet_complete:
142
        mov     eax, [ebx+sshlib_connection.rx_buffer.packet_length]
143
        movzx   ebx, [ebx+sshlib_connection.rx_buffer.padding_length]
6419 hidnplayr 144
        sub     eax, ebx
6469 hidnplayr 145
        DEBUGF  1, "useful data length=%u\n", eax
6419 hidnplayr 146
        ret
147
 
9106 hidnplayr 148
  .sock_fail:
6469 hidnplayr 149
        DEBUGF  3, "ssh_recv_packet failed!\n"
9106 hidnplayr 150
        mov     eax, SSHLIB_ERR_SOCKET
6419 hidnplayr 151
        ret
152
 
9106 hidnplayr 153
  .mac_fail:
154
        DEBUGF  3, "ssh_recv_packet message authentication failed!\n"
155
        mov     eax, SSHLIB_ERR_MAC_VERIFY_FAIL
156
        xor     ebx, ebx
6469 hidnplayr 157
        ret
158
 
9106 hidnplayr 159
  .proto_fail:
160
        DEBUGF  3, "ssh_recv_packet protocol failure!\n"
161
        mov     eax, SSHLIB_ERR_PROTOCOL
162
        xor     ebx, ebx
163
        ret
164
 
6419 hidnplayr 165
endp
166
 
167
 
9106 hidnplayr 168
proc sshlib_send_packet con_ptr, buf, payload_size, flags
6419 hidnplayr 169
 
170
locals
6469 hidnplayr 171
        packet_size    dd ?
6419 hidnplayr 172
endl
6469 hidnplayr 173
        DEBUGF  2, "< "
6419 hidnplayr 174
 
9071 hidnplayr 175
; Check how many bytes we should pad
6469 hidnplayr 176
        mov     eax, [payload_size]
177
        inc     eax                     ; padding length byte
178
        lea     edx, [eax+4]            ; total packet size (without padding and MAC)
179
        mov     [packet_size], edx
9071 hidnplayr 180
 
9106 hidnplayr 181
        mov     ecx, [con_ptr]
182
        mov     ebx, [ecx+sshlib_connection.tx_pad_size]
6419 hidnplayr 183
        dec     ebx
184
        and     edx, ebx
185
        neg     edx
9106 hidnplayr 186
        add     edx, [ecx+sshlib_connection.tx_pad_size]
187
        add     edx, [ecx+sshlib_connection.tx_pad_size]
6469 hidnplayr 188
        DEBUGF  1, "padding %u bytes ", edx
9071 hidnplayr 189
        add     [packet_size], edx      ; total packet size with padding
6419 hidnplayr 190
 
9071 hidnplayr 191
; Start building the packet
192
; First comes the packet length, in network byte order ofcourse.
6419 hidnplayr 193
        add     eax, edx
6469 hidnplayr 194
        DEBUGF  1, "total size: %u ", eax
6419 hidnplayr 195
        bswap   eax
9106 hidnplayr 196
        lea     edi, [ecx+sshlib_connection.tx_buffer]
9071 hidnplayr 197
        stosd
198
; Then the padding length
6419 hidnplayr 199
        mov     al, dl
9071 hidnplayr 200
        stosb
201
; And the actual payload bytes
6419 hidnplayr 202
        mov     esi, [buf]
6469 hidnplayr 203
        mov     ecx, [payload_size]
6419 hidnplayr 204
        rep movsb
205
 
9071 hidnplayr 206
; Append the packet with #edx padding bytes.
207
; Since we must pad at least 8 bytes, we can always use DWORD writes.
208
; First do an (unaligned) write exactly following the data
209
        dec     edx
210
        mov     esi, edx
211
        shr     esi, 2          ; number dwords
6419 hidnplayr 212
        mov     ebx, edx
213
        and     ebx, 3
9071 hidnplayr 214
        inc     ebx             ; number bytes in first write (1-4)
9106 hidnplayr 215
        mov     edx, [con_ptr]
216
        call    [edx+sshlib_connection.tx_pad_proc]
6419 hidnplayr 217
        mov     dword[edi], eax
218
        add     edi, ebx
9071 hidnplayr 219
; Then, do as many aligned writes as nescessary
9106 hidnplayr 220
        mov     ebx, [con_ptr]
6419 hidnplayr 221
  @@:
9106 hidnplayr 222
        call    [ebx+sshlib_connection.tx_pad_proc]
6419 hidnplayr 223
        stosd
224
        dec     esi
225
        jnz     @r
226
 
9071 hidnplayr 227
; Append the packet with Message Authentication Code
9106 hidnplayr 228
        mov     edx, [con_ptr]
229
        cmp     [edx+sshlib_connection.tx_mac_proc], 0
6469 hidnplayr 230
        je      .mac_complete
9106 hidnplayr 231
        DEBUGF  1, "MAC sequence number: 0x%x\n", [edx+sshlib_connection.tx_mac_seqnr]
232
        lea     esi, [edx+sshlib_connection.tx_mac_seqnr]
6469 hidnplayr 233
        mov     ecx, [packet_size]
234
        add     ecx, 4                                          ; Sequence number length
9106 hidnplayr 235
        lea     eax, [edx+sshlib_connection.tx_mac_ctx]
236
        stdcall [edx+sshlib_connection.tx_mac_proc], eax, esi, ecx
6419 hidnplayr 237
 
9106 hidnplayr 238
        lea     esi, [edx+sshlib_connection.tx_mac_ctx]
239
        lea     edi, [edx+sshlib_connection.tx_buffer]
6469 hidnplayr 240
        add     edi, [packet_size]
9106 hidnplayr 241
        mov     ecx, [edx+sshlib_connection.tx_mac_length]
6469 hidnplayr 242
        shr     ecx, 2
243
        rep movsd
244
  .mac_complete:
9106 hidnplayr 245
        add     byte[edx+sshlib_connection.tx_mac_seqnr+3], 1      ; Update sequence counter
246
        adc     byte[edx+sshlib_connection.tx_mac_seqnr+2], 0
247
        adc     byte[edx+sshlib_connection.tx_mac_seqnr+1], 0
248
        adc     byte[edx+sshlib_connection.tx_mac_seqnr+0], 0
6469 hidnplayr 249
 
9071 hidnplayr 250
; Now, encrypt everything but MAC
9106 hidnplayr 251
        lea     esi, [edx+sshlib_connection.tx_buffer]
6469 hidnplayr 252
        mov     ecx, [packet_size]
253
  .encrypt_loop:
254
        pusha
9106 hidnplayr 255
        stdcall [edx+sshlib_connection.tx_crypt_proc], [edx+sshlib_connection.tx_crypt_ctx_ptr], esi, esi
6469 hidnplayr 256
        popa
9106 hidnplayr 257
        add     esi, [edx+sshlib_connection.tx_crypt_blocksize]
258
        sub     ecx, [edx+sshlib_connection.tx_crypt_blocksize]
6469 hidnplayr 259
        jnz     .encrypt_loop
260
 
261
; Send the packet
9106 hidnplayr 262
        mov     ebx, [con_ptr]
263
        mov     ecx, [ebx+sshlib_connection.socketnum]
264
        lea     edx, [ebx+sshlib_connection.tx_buffer]
6469 hidnplayr 265
        mov     esi, [packet_size]
9106 hidnplayr 266
        add     esi, [ebx+sshlib_connection.tx_mac_length]
6469 hidnplayr 267
        mov     edi, [flags]
268
        mcall   send
269
 
270
        DEBUGF  1, "\n"
271
 
6419 hidnplayr 272
        ret
273
 
6469 hidnplayr 274
endp
275