Subversion Repositories Kolibri OS

Rev

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