Subversion Repositories Kolibri OS

Rev

Rev 9987 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
9987 hidnplayr 1
;    sshlib_transport.inc - SSH transport layer
2
;
3
;    Copyright (C) 2016-2024 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
 
18
iglobal
19
 
20
align 16
21
null_bytes:    times 64 db 0
22
 
23
endg
24
 
25
 
26
align 16
27
proc sshlib_recv_packet_poly1305chacha20 con_ptr, flags
28
 
29
locals
30
        data_length     dd ?    ; Total length of packet without MAC
31
        mac_otk         rb 64   ;256/8
32
        iv              rd 4
33
endl
34
 
35
        DEBUGF  3, "> "
36
; Receive first block (Read length)
37
        mov     ebx, [con_ptr]
38
        mov     ecx, [ebx+sshlib_connection.socketnum]
39
        mov     esi, 4
40
        lea     edx, [ebx+sshlib_connection.rx_buffer]
41
        mov     edi, [flags]
42
        mcall   recv
43
        cmp     eax, 0
44
        jle     .sock_fail
45
        sub     [ssh_chan.rcv_wnd], eax  ;;; FIXME
46
        DEBUGF  1, "chunk = %u ", eax
47
        mov     ebx, [con_ptr]
48
        cmp     eax, 4
49
        jne     .proto_fail     ; TODO: handle receives of 1, 2, and 3 bytes correctly
50
 
51
; Decrypt data length
52
        mov     ebx, [con_ptr]
53
 
54
        lea     eax, [iv]
55
        mov     dword[eax+0], 0
56
        mov     dword[eax+4], 0
57
        mov     dword[eax+8], 0
58
        push    [ebx+sshlib_connection.rx_mac_seqnr]
59
        pop     dword[eax+12]
60
 
61
        lea     ecx, [ebx+sshlib_connection.rx_crypt_ctx]
62
        lea     edx, [ebx+sshlib_connection.rx_enc_key+256/8]
63
        lea     esi, [ebx+sshlib_connection.rx_buffer]
64
        lea     edi, [data_length]
9990 hidnplayr 65
        invoke  chacha20.oneshot, ecx, edx, eax, 0, esi, 4, edi
9987 hidnplayr 66
 
67
        mov     eax, [data_length]
68
        bswap   eax
69
        mov     [data_length], eax
70
        DEBUGF  2, "decrypted packet length=%u\n", [data_length]
71
 
72
        cmp     eax, BUFFERSIZE-4-128/8
73
        ja      .proto_fail
74
 
75
; Receive remaining data
76
        lea     edx, [ebx+sshlib_connection.rx_buffer+4]
77
        mov     ecx, [ebx+sshlib_connection.socketnum]
78
        mov     edi, [flags]
79
        lea     esi, [eax + 128/8]                              ; We already got 4 bytes but they are not counted, MAC is also not counted so add that
80
  .recv_loop:
81
        DEBUGF  3, "want %u bytes.. ", esi
82
        mcall   recv
83
        cmp     eax, 0
84
        jle     .sock_fail
85
        sub     [ssh_chan.rcv_wnd], eax             ;;; FIXME
86
        DEBUGF  3, "got %u bytes\n", eax
87
        add     edx, eax
88
        sub     esi, eax
89
        jnz     .recv_loop
90
 
91
; Calculate the OTK
92
        mov     ebx, [con_ptr]
93
        lea     eax, [ebx+sshlib_connection.rx_crypt_ctx]
94
        lea     esi, [ebx+sshlib_connection.rx_enc_key]
95
        lea     edx, [mac_otk]
96
        lea     ecx, [iv]
9990 hidnplayr 97
        invoke  chacha20.oneshot, eax, esi, ecx, 0, null_bytes, 64, edx
9987 hidnplayr 98
 
99
; Calculate the MAC
100
        lea     esi, [ebx+sshlib_connection.rx_mac_ctx]
101
        lea     edi, [ebx+sshlib_connection.rx_buffer]
102
        mov     ecx, [data_length]
103
        add     ecx, 4
104
        lea     edx, [mac_otk]
105
        push    ecx
9990 hidnplayr 106
        invoke  poly1305.oneshot, esi, edi, ecx, edx, 256/8
9987 hidnplayr 107
        pop     ecx
108
 
109
; Compare in constant time
110
        add     edi, ecx
111
        cmpsd
112
        lahf
113
        mov     edx, eax
114
        cmpsd
115
        lahf
116
        and     edx, eax
117
        cmpsd
118
        lahf
119
        and     edx, eax
120
        cmpsd
121
        lahf
122
        and     eax, edx
123
        sahf
124
        jne     .mac_fail
125
 
126
; Decrypt the payload
127
        lea     eax, [ebx+sshlib_connection.rx_crypt_ctx]
128
        lea     edi, [ebx+sshlib_connection.rx_buffer+4]
9990 hidnplayr 129
        invoke  chacha20.update, eax, edi, [data_length], edi
9987 hidnplayr 130
 
131
; Put decrypted length in rx buffer
132
        push    [data_length]
133
        pop     dword[ebx+sshlib_connection.rx_buffer]
134
 
135
; Update sequence counter
136
        add     byte[ebx+sshlib_connection.rx_mac_seqnr+3], 1
137
        adc     byte[ebx+sshlib_connection.rx_mac_seqnr+2], 0
138
        adc     byte[ebx+sshlib_connection.rx_mac_seqnr+1], 0
139
        adc     byte[ebx+sshlib_connection.rx_mac_seqnr+0], 0
140
 
141
; Return useful data length to the caller via eax register
142
;;;  .packet_complete:
143
        mov     eax, [ebx+sshlib_connection.rx_buffer.packet_length]
144
        movzx   ebx, [ebx+sshlib_connection.rx_buffer.padding_length]
145
        sub     eax, ebx
146
        DEBUGF  1, "useful data length=%u\n", eax
147
        ret
148
 
149
  .sock_fail:
150
        DEBUGF  3, "ssh_recv_packet failed!\n"
151
        mov     eax, SSHLIB_ERR_SOCKET
152
        ret
153
 
154
  .mac_fail:
155
        DEBUGF  3, "ssh_recv_packet message authentication failed!\n"
156
        mov     eax, SSHLIB_ERR_MAC_VERIFY_FAIL
157
        xor     ebx, ebx
158
        ret
159
 
160
  .proto_fail:
161
        DEBUGF  3, "ssh_recv_packet protocol failure!\n"
162
        mov     eax, SSHLIB_ERR_PROTOCOL
163
        xor     ebx, ebx
164
        ret
165
 
166
endp
167
 
168
 
169
align 16
170
proc sshlib_send_packet_poly1305chacha20 con_ptr, buf, payload_size, flags
171
 
172
locals
173
        packet_size     dd ?
174
        mac_otk         rb 64   ;256/8
175
        iv              rd 4
176
endl
177
        DEBUGF  2, "< "
178
 
179
; Check how many bytes we should pad
180
        mov     eax, [payload_size]
181
        inc     eax                     ; padding length byte
182
        lea     edx, [eax+4]            ; total packet size without padding and MAC
183
        mov     [packet_size], edx
184
 
185
        mov     ecx, [con_ptr]
186
        mov     edx, eax
187
        mov     ebx, [ecx+sshlib_connection.tx_pad_size]
188
        dec     ebx
189
        and     edx, ebx
190
        neg     edx
191
        add     edx, [ecx+sshlib_connection.tx_pad_size]
192
        add     edx, [ecx+sshlib_connection.tx_pad_size]
193
        DEBUGF  2, "padding %u bytes ", edx
194
        add     [packet_size], edx      ; total packet size with padding, without MAC
195
 
196
; Start building the packet
197
; First comes the packet length, in network byte order ofcourse.
198
        add     eax, edx
199
        DEBUGF  2, "total size: %u ", eax
200
        bswap   eax
201
        lea     edi, [ecx+sshlib_connection.tx_buffer]
202
        stosd
203
; Then the padding length
204
        mov     al, dl
205
        stosb
206
;;; And the actual payload bytes
207
        mov     esi, [buf]
208
        mov     ecx, [payload_size]
209
        rep movsb
210
 
211
; Append the packet with #edx padding bytes.
212
; Since we must pad at least 8 bytes, we can always use DWORD writes.
213
; First do an (unaligned) write exactly following the data
214
        dec     edx
215
        mov     esi, edx
216
        shr     esi, 2          ; number dwords
217
        mov     ebx, edx
218
        and     ebx, 3
219
        inc     ebx             ; number bytes in first write (1-4)
220
        mov     edx, [con_ptr]
221
        call    MBRandom
222
        mov     dword[edi], eax
223
        add     edi, ebx
224
; Then, do as many aligned writes as nescessary
225
        mov     ebx, [con_ptr]
226
  @@:
227
        call    MBRandom
228
        stosd
229
        dec     esi
230
        jnz     @r
231
 
232
; Encrypt data length
233
        lea     eax, [iv]
234
        mov     dword[eax+0], 0
235
        mov     dword[eax+4], 0
236
        mov     dword[eax+8], 0
237
        push    [ebx+sshlib_connection.tx_mac_seqnr]
238
        pop     dword[eax+12]
239
 
240
        lea     esi, [ebx+sshlib_connection.tx_crypt_ctx]
241
        lea     edx, [ebx+sshlib_connection.tx_enc_key+256/8]
242
        lea     edi, [ebx+sshlib_connection.tx_buffer]
9990 hidnplayr 243
        invoke  chacha20.oneshot, esi, edx, eax, 0, edi, 4, edi
9987 hidnplayr 244
 
245
; Calculate the OTK
246
        lea     eax, [iv]
247
        lea     edx, [ebx+sshlib_connection.tx_enc_key]
248
        lea     edi, [mac_otk]
9990 hidnplayr 249
        invoke  chacha20.oneshot, esi, edx, eax, 0, null_bytes, 64, edi
9987 hidnplayr 250
 
251
; Encrypt the payload
252
        lea     edi, [ebx+sshlib_connection.tx_buffer+4]
253
        mov     eax, [packet_size]
254
        sub     eax, 4
9990 hidnplayr 255
        invoke  chacha20.update, esi, edi, eax, edi
9987 hidnplayr 256
 
257
; Calculate the MAC
258
        lea     esi, [ebx+sshlib_connection.tx_mac_ctx]
259
        lea     edi, [ebx+sshlib_connection.tx_buffer]
260
        lea     edx, [mac_otk]
9990 hidnplayr 261
        invoke  poly1305.oneshot, esi, edi, [packet_size], edx, 256/8
9987 hidnplayr 262
 
263
; Write it to the send buffer
264
        add     edi, [packet_size]
265
        movsd
266
        movsd
267
        movsd
268
        movsd
269
 
270
; Update sequence counter
271
        add     byte[ebx+sshlib_connection.tx_mac_seqnr+3], 1
272
        adc     byte[ebx+sshlib_connection.tx_mac_seqnr+2], 0
273
        adc     byte[ebx+sshlib_connection.tx_mac_seqnr+1], 0
274
        adc     byte[ebx+sshlib_connection.tx_mac_seqnr+0], 0
275
 
276
; Send the packet
277
;        mov     ebx, [con_ptr]
278
        mov     ecx, [ebx+sshlib_connection.socketnum]
279
        lea     edx, [ebx+sshlib_connection.tx_buffer]
280
        mov     esi, [packet_size]
281
        add     esi, 16 ;[ebx+sshlib_connection.tx_mac_length]
282
        mov     edi, [flags]
283
        mcall   send
284
 
285
        DEBUGF  2, "\n"
286
 
287
        ret
288
 
289
endp
290