Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
6419 hidnplayr 1
;    ssh_transport.inc - SSH transport layer
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
 
19
struct  ssh_packet_header
20
        packet_length   dd ?    ; The length of the packet in bytes, not including 'mac' or the
21
                                ; 'packet_length' field itself.
22
        padding_length  db ?    ; Length of 'random padding' (bytes).
23
 
24
        message_code    db ?    ; First byte of payload
6419 hidnplayr 25
ends
26
 
9071 hidnplayr 27
proc padding_zero
6419 hidnplayr 28
 
9071 hidnplayr 29
        xor     eax, eax
30
        ret
31
 
32
endp
33
 
6469 hidnplayr 34
proc ssh_recv_packet connection, flags
6419 hidnplayr 35
 
36
locals
6469 hidnplayr 37
        data_length     dd ?    ; Total length of packet without MAC
9070 hidnplayr 38
        socket_error    dd ?
6419 hidnplayr 39
endl
40
 
6469 hidnplayr 41
        DEBUGF  2, "> "
6419 hidnplayr 42
; Receive first block (Read length, padding length, message code)
6469 hidnplayr 43
        mov     ebx, [connection]
44
        mov     ecx, [ebx+ssh_connection.socketnum]
45
        mov     esi, [ebx+ssh_connection.rx_crypt_blocksize]
46
        lea     edx, [ebx+ssh_connection.rx_buffer]
47
        mov     edi, [flags]
48
        mcall   recv
9070 hidnplayr 49
        mov     [socket_error], ebx
6469 hidnplayr 50
        DEBUGF  1, "chunk = %u ", eax
51
        mov     ebx, [connection]
52
        cmp     eax, [ebx+ssh_connection.rx_crypt_blocksize]
53
        jne     .fail
6419 hidnplayr 54
 
6469 hidnplayr 55
; Decrypt first block
56
        cmp     [ebx+ssh_connection.rx_crypt_proc], 0
57
        je      @f
58
        pusha
59
        lea     esi, [ebx+ssh_connection.rx_buffer]
60
        stdcall [ebx+ssh_connection.rx_crypt_proc], [ebx+ssh_connection.rx_crypt_ctx_ptr], esi, esi
61
        popa
62
  @@:
6419 hidnplayr 63
 
6469 hidnplayr 64
; Check data length
65
        mov     esi, [ebx+ssh_connection.rx_buffer.packet_length]
66
        bswap   esi                                             ; convert length to little endian
67
        mov     [ebx+ssh_connection.rx_buffer.packet_length], esi
68
        DEBUGF  1, "packet length=%u ", esi
69
        cmp     esi, BUFFERSIZE
70
        ja      .fail                                           ; packet is too large
6419 hidnplayr 71
 
6469 hidnplayr 72
; Calculate amount of remaining data
73
        add     esi, 4                                          ; Packet length field itself is not included in the count
74
        sub     esi, [ebx+ssh_connection.rx_crypt_blocksize]    ; Already received this amount of data
75
        add     esi, [ebx+ssh_connection.rx_mac_length]
76
        jz      .got_all_data
6419 hidnplayr 77
 
6469 hidnplayr 78
; Receive remaining data
79
        lea     edx, [ebx+ssh_connection.rx_buffer]
80
        add     edx, [ebx+ssh_connection.rx_crypt_blocksize]
81
        mov     ecx, [ebx+ssh_connection.socketnum]
82
        mov     edi, [flags]
6419 hidnplayr 83
  .receive_loop:
6469 hidnplayr 84
        mcall   recv
85
        DEBUGF  1, "chunk = %u ", eax
6419 hidnplayr 86
        cmp     eax, 0
87
        jbe     .fail
6469 hidnplayr 88
        add     edx, eax
89
        sub     esi, eax
90
        jnz     .receive_loop
6419 hidnplayr 91
 
6469 hidnplayr 92
; Decrypt data
93
        mov     ebx, [connection]
94
        cmp     [ebx+ssh_connection.rx_crypt_proc], 0
95
        je      .decrypt_complete
96
        mov     ecx, [ebx+ssh_connection.rx_buffer.packet_length]
97
        add     ecx, 4                                          ; Packet_length field itself
98
        sub     ecx, [ebx+ssh_connection.rx_crypt_blocksize]    ; Already decrypted this amount of data
99
        jz      .decrypt_complete
6419 hidnplayr 100
 
6469 hidnplayr 101
        lea     esi, [ebx+ssh_connection.rx_buffer]
102
        add     esi, [ebx+ssh_connection.rx_crypt_blocksize]
103
  .decrypt_loop:
104
        pusha
105
        stdcall [ebx+ssh_connection.rx_crypt_proc], [ebx+ssh_connection.rx_crypt_ctx_ptr], esi, esi
106
        popa
107
        add     esi, [ebx+ssh_connection.rx_crypt_blocksize]
108
        sub     ecx, [ebx+ssh_connection.rx_crypt_blocksize]
109
        jnz     .decrypt_loop
110
  .decrypt_complete:
6419 hidnplayr 111
 
6469 hidnplayr 112
; Authenticate message
113
        cmp     [ebx+ssh_connection.rx_mac_proc], 0
114
        je      .mac_complete
115
        lea     esi, [ebx+ssh_connection.rx_seq]
116
        mov     ecx, [ebx+ssh_connection.rx_buffer.packet_length]
117
        add     ecx, 8                                          ; packet_length field itself + sequence number
118
        lea     eax, [ebx+ssh_connection.rx_mac_ctx]
119
        mov     edx, [ebx+ssh_connection.rx_buffer.packet_length]
120
        bswap   edx                                             ; convert length to big endian
121
        mov     [ebx+ssh_connection.rx_buffer.packet_length], edx
122
        stdcall [ebx+ssh_connection.rx_mac_proc], eax, esi, ecx
123
        mov     edx, [ebx+ssh_connection.rx_buffer.packet_length]
124
        bswap   edx                                             ; convert length to little endian
125
        mov     [ebx+ssh_connection.rx_buffer.packet_length], edx
126
 
127
        lea     esi, [ebx+ssh_connection.rx_mac_ctx]
128
        lea     edi, [ebx+ssh_connection.rx_buffer]
129
        add     edi, [ebx+ssh_connection.rx_buffer.packet_length]
130
        add     edi, 4
131
        mov     ecx, [ebx+ssh_connection.rx_mac_length]
132
        shr     ecx, 2
133
        repe cmpsd
134
        jne     .mac_failed
135
  .mac_complete:
9071 hidnplayr 136
        add     byte[ebx+ssh_connection.rx_seq+3], 1            ; Update sequence counter
137
        adc     byte[ebx+ssh_connection.rx_seq+2], 0
138
        adc     byte[ebx+ssh_connection.rx_seq+1], 0
139
        adc     byte[ebx+ssh_connection.rx_seq+0], 0
6469 hidnplayr 140
 
141
; Return useful data length to the caller via eax register
142
  .got_all_data:
143
        mov     eax, [ebx+ssh_connection.rx_buffer.packet_length]
144
        movzx   ebx, [ebx+ssh_connection.rx_buffer.padding_length]
6419 hidnplayr 145
        sub     eax, ebx
6469 hidnplayr 146
        DEBUGF  1, "useful data length=%u\n", eax
6419 hidnplayr 147
        ret
148
 
149
  .fail:
6469 hidnplayr 150
        DEBUGF  3, "ssh_recv_packet failed!\n"
6419 hidnplayr 151
        mov     eax, -1
9070 hidnplayr 152
        mov     ebx, [socket_error]
6419 hidnplayr 153
        ret
154
 
6469 hidnplayr 155
  .mac_failed:
156
        DEBUGF  3, "ssh_recv_packet MAC failed!\n"
9070 hidnplayr 157
        mov     eax, -2
158
        mov     ebx, [socket_error]
6469 hidnplayr 159
        ret
160
 
6419 hidnplayr 161
endp
162
 
163
 
6469 hidnplayr 164
proc ssh_send_packet connection, buf, payload_size, flags
6419 hidnplayr 165
 
166
locals
6469 hidnplayr 167
        packet_size    dd ?
6419 hidnplayr 168
endl
6469 hidnplayr 169
        DEBUGF  2, "< "
6419 hidnplayr 170
 
9071 hidnplayr 171
; Check how many bytes we should pad
6469 hidnplayr 172
        mov     eax, [payload_size]
173
        inc     eax                     ; padding length byte
174
        lea     edx, [eax+4]            ; total packet size (without padding and MAC)
175
        mov     [packet_size], edx
9071 hidnplayr 176
 
6469 hidnplayr 177
        mov     ecx, [connection]
9071 hidnplayr 178
        mov     ebx, [ecx+ssh_connection.tx_pad_size]
6419 hidnplayr 179
        dec     ebx
180
        and     edx, ebx
181
        neg     edx
9071 hidnplayr 182
        add     edx, [ecx+ssh_connection.tx_pad_size]
183
        add     edx, [ecx+ssh_connection.tx_pad_size]
6469 hidnplayr 184
        DEBUGF  1, "padding %u bytes ", edx
9071 hidnplayr 185
        add     [packet_size], edx      ; total packet size with padding
6419 hidnplayr 186
 
9071 hidnplayr 187
; Start building the packet
188
; First comes the packet length, in network byte order ofcourse.
6419 hidnplayr 189
        add     eax, edx
6469 hidnplayr 190
        DEBUGF  1, "total size: %u ", eax
6419 hidnplayr 191
        bswap   eax
6469 hidnplayr 192
        lea     edi, [ecx+ssh_connection.tx_buffer]
9071 hidnplayr 193
        stosd
194
; Then the padding length
6419 hidnplayr 195
        mov     al, dl
9071 hidnplayr 196
        stosb
197
; And the actual payload bytes
6419 hidnplayr 198
        mov     esi, [buf]
6469 hidnplayr 199
        mov     ecx, [payload_size]
6419 hidnplayr 200
        rep movsb
201
 
9071 hidnplayr 202
; Append the packet with #edx padding bytes.
203
; Since we must pad at least 8 bytes, we can always use DWORD writes.
204
; First do an (unaligned) write exactly following the data
205
        dec     edx
206
        mov     esi, edx
207
        shr     esi, 2          ; number dwords
6419 hidnplayr 208
        mov     ebx, edx
209
        and     ebx, 3
9071 hidnplayr 210
        inc     ebx             ; number bytes in first write (1-4)
211
        mov     edx, [connection]
212
        call    [edx+ssh_connection.tx_pad_proc]
6419 hidnplayr 213
        mov     dword[edi], eax
214
        add     edi, ebx
9071 hidnplayr 215
; Then, do as many aligned writes as nescessary
216
        mov     ebx, [connection]
6419 hidnplayr 217
  @@:
9071 hidnplayr 218
        call    [ebx+ssh_connection.tx_pad_proc]
6419 hidnplayr 219
        stosd
220
        dec     esi
221
        jnz     @r
222
 
9071 hidnplayr 223
; Append the packet with Message Authentication Code
6469 hidnplayr 224
        mov     edx, [connection]
225
        cmp     [edx+ssh_connection.tx_mac_proc], 0
226
        je      .mac_complete
9071 hidnplayr 227
        DEBUGF  1, "MAC sequence number: 0x%x\n", [edx+ssh_connection.tx_seq]
6469 hidnplayr 228
        lea     esi, [edx+ssh_connection.tx_seq]
229
        mov     ecx, [packet_size]
230
        add     ecx, 4                                          ; Sequence number length
231
        lea     eax, [edx+ssh_connection.tx_mac_ctx]
232
        stdcall [edx+ssh_connection.tx_mac_proc], eax, esi, ecx
6419 hidnplayr 233
 
6469 hidnplayr 234
        lea     esi, [edx+ssh_connection.tx_mac_ctx]
235
        lea     edi, [edx+ssh_connection.tx_buffer]
236
        add     edi, [packet_size]
237
        mov     ecx, [edx+ssh_connection.tx_mac_length]
238
        shr     ecx, 2
239
        rep movsd
240
  .mac_complete:
9071 hidnplayr 241
        add     byte[edx+ssh_connection.tx_seq+3], 1            ; Update sequence counter
242
        adc     byte[edx+ssh_connection.tx_seq+2], 0
243
        adc     byte[edx+ssh_connection.tx_seq+1], 0
244
        adc     byte[edx+ssh_connection.tx_seq+0], 0
6469 hidnplayr 245
 
9071 hidnplayr 246
; Now, encrypt everything but MAC
6469 hidnplayr 247
        cmp     [edx+ssh_connection.tx_crypt_proc], 0
248
        je      .encrypt_complete
249
        lea     esi, [edx+ssh_connection.tx_buffer]
250
        mov     ecx, [packet_size]
251
  .encrypt_loop:
252
        pusha
253
        stdcall [edx+ssh_connection.tx_crypt_proc], [edx+ssh_connection.tx_crypt_ctx_ptr], esi, esi
254
        popa
255
        add     esi, [edx+ssh_connection.tx_crypt_blocksize]
256
        sub     ecx, [edx+ssh_connection.tx_crypt_blocksize]
257
        jnz     .encrypt_loop
258
  .encrypt_complete:
259
 
260
; Send the packet
261
        mov     ebx, [connection]
262
        mov     ecx, [ebx+ssh_connection.socketnum]
263
        lea     edx, [ebx+ssh_connection.tx_buffer]
264
        mov     esi, [packet_size]
265
        add     esi, [ebx+ssh_connection.tx_mac_length]
266
        mov     edi, [flags]
267
        mcall   send
268
 
269
        DEBUGF  1, "\n"
270
 
6419 hidnplayr 271
        ret
272
 
6469 hidnplayr 273
endp
274