Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
9106 hidnplayr 1
;    sshlib_host.inc - SSH remote host authentication
2
;
3
;    Copyright (C) 2021 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
; https://datatracker.ietf.org/doc/html/rfc4253#section-6.6
19
; https://datatracker.ietf.org/doc/html/rfc3447
9112 hidnplayr 20
; https://datatracker.ietf.org/doc/html/rfc4716
9113 hidnplayr 21
; https://datatracker.ietf.org/doc/html/rfc8017
9112 hidnplayr 22
 
9106 hidnplayr 23
proc sshlib_host_verify  con_ptr, str_host_key, str_signature, message, message_len
24
 
25
locals
9112 hidnplayr 26
        current_hkb64           rb MAX_PUBLIC_KEY_SIZE*4        ; Current Host key in Base64
27
        cached_hkb64            rb MAX_PUBLIC_KEY_SIZE*4        ; Cached Host key in Base64
28
        key_name_sz             dd ?
29
        hostname_sz             dd ?
30
        current_hk64_end        dd ?
9106 hidnplayr 31
endl
32
 
33
        mov     eax, [con_ptr]
9112 hidnplayr 34
        lea     ebx, [eax + sshlib_connection.hostname_sz]
35
        mov     [hostname_sz], ebx
9106 hidnplayr 36
        cmp     [eax+sshlib_connection.algo_hostkey], SSHLIB_HOSTKEY_RSA
37
        je      .rsa
38
        ; ..add more here
39
        mov     eax, SSHLIB_ERR_HKEY_NO_ALGO
40
        ret
41
 
42
  .rsa:
43
        stdcall sshlib_host_verify_rsa, [str_host_key], [str_signature], [message], [message_len]
44
        test    eax, eax
45
        jnz     .err
9112 hidnplayr 46
        mov     [key_name_sz], ssh_rsa_sz
9106 hidnplayr 47
 
48
  .lookup:
9112 hidnplayr 49
; Convert the current host key to base64
50
        mov     esi, [str_host_key]
51
        mov     ecx, [esi]
52
        bswap   ecx
53
        add     esi, 4
54
        lea     edi, [current_hkb64]
55
        call    base64_encode
56
        mov     [current_hk64_end], edi
9106 hidnplayr 57
 
9112 hidnplayr 58
; Try to read the cached key for this host and key type
59
        lea     edi, [cached_hkb64]
60
        invoke  ini_get_str, known_hostsfile, [hostname_sz], [key_name_sz], edi, MAX_PUBLIC_KEY_SIZE*4, 0
61
        test    eax, eax
62
        jnz     .unknown
63
; If the cached key is empty, return SSHLIB_HOSTKEY_PROBLEM_UNKNOWN
64
        lea     esi, [cached_hkb64]
65
        cmp     byte[esi], 0
66
        je      .unknown
67
; Else, compare it to the current one
68
        lea     edi, [current_hkb64]
69
        mov     ecx, MAX_PUBLIC_KEY_SIZE*4
70
  .cmploop:
71
        lodsb
72
        scasb
73
        jne     .mismatch
74
        test    al, al
75
        jz      .match
76
        dec     ecx
77
        jnz     .cmploop
78
        jmp     .mismatch
9106 hidnplayr 79
 
9112 hidnplayr 80
  .match:
9106 hidnplayr 81
        xor     eax, eax
82
        ret
83
 
84
  .mismatch:
9112 hidnplayr 85
int3
86
        lea     eax, [current_hkb64]
9106 hidnplayr 87
        stdcall sshlib_callback_hostkey_problem, [con_ptr], SSHLIB_HOSTKEY_PROBLEM_MISMATCH, eax
88
        cmp     eax, SSHLIB_HOSTKEY_ACCEPT
89
        je      .store
90
        ret
91
 
92
  .unknown:
9112 hidnplayr 93
        lea     eax, [current_hkb64]
9106 hidnplayr 94
        stdcall sshlib_callback_hostkey_problem, [con_ptr], SSHLIB_HOSTKEY_PROBLEM_UNKNOWN, eax
95
        cmp     eax, SSHLIB_HOSTKEY_ACCEPT
96
        je      .store
97
        ret
98
 
99
  .store:
9112 hidnplayr 100
        lea     esi, [current_hkb64]
101
        mov     ecx, [current_hk64_end]
102
        sub     ecx, esi
103
        invoke  ini_set_str, known_hostsfile, [hostname_sz], [key_name_sz], esi, ecx
104
        xor     eax, eax
9106 hidnplayr 105
        ret
106
 
107
  .err:
108
        ret
109
 
110
endp
111
 
112
 
113
; https://datatracker.ietf.org/doc/html/rfc3447#section-8.2.2
114
; RSASSA-PKCS1-V1_5-VERIFY
115
proc sshlib_host_verify_rsa str_host_key, str_signature, M, message_len
116
 
117
locals
118
        h_ctx                   dd ?
119
 
120
; Signer's RSA public key
121
        mpint_e                 dd ?    ; public exponent
122
        mpint_n                 dd ?    ; modulus
123
 
124
        mpint_m                 dd ?
125
 
126
        EM                      dd ?
127
        EM_accent               dd ?
128
 
129
        mpint_s                 dd ?    ; rsa_signature_blob
130
 
131
 
132
;        k       dd ?    ; length of RSA modulus n
133
 
134
endl
135
 
136
        DEBUGF  3, "SSH: Performing RSA verification\n"
137
 
138
        mcall   68, 12, sizeof.crash_ctx + 5*(MAX_BITS/8+4)
139
        test    eax, eax
140
        jz      .err_nomem
141
        mov     [h_ctx], eax
142
        add     eax, sizeof.crash_ctx
143
        mov     [mpint_e], eax
144
        add     eax, MAX_BITS/8+4
145
        mov     [mpint_n], eax
146
        add     eax, MAX_BITS/8+4
147
        mov     [mpint_m], eax
148
        add     eax, MAX_BITS/8+4
149
        mov     [EM], eax
150
        add     eax, MAX_BITS/8+4
151
        mov     [EM_accent], eax
152
        add     eax, MAX_BITS/8+4
153
        mov     [mpint_s], eax
154
;        add     eax, MAX_BITS/8+4
155
 
156
; Host key
157
        mov     esi, [str_host_key]
158
        mov     ecx, [esi]
159
        bswap   ecx
160
        cmp     ecx, MAX_PUBLIC_KEY_SIZE
161
        ja      .err_key
162
; Host key type (string)
163
        cmp     dword[esi+4], 0x07000000
164
        jne     .err_key
165
        cmp     dword[esi+8], 'ssh-'
166
        jne     .err_key
167
        cmp     dword[esi+11], '-rsa'
168
        jne     .err_key
169
        add     esi, 4+4+7
170
; mpint e
171
        stdcall mpint_to_little_endian, [mpint_e], esi
172
        add     esi, eax
173
        add     esi, 4
174
; mpint n
175
        stdcall mpint_to_little_endian, [mpint_n], esi
176
;        mov     [k], eax             ;; HMMMM FIXME, 0-byte..
177
 
178
; Signature
179
        mov     esi, [str_signature]
180
        mov     ecx, [esi]
181
        bswap   ecx             ; TODO: check length
9113 hidnplayr 182
 
9106 hidnplayr 183
; Host key type (string)
184
        cmp     dword[esi+4], 0x07000000
9113 hidnplayr 185
        jne     .not_ssh_rsa
9106 hidnplayr 186
        cmp     dword[esi+8], 'ssh-'
9113 hidnplayr 187
        jne     .not_ssh_rsa
9106 hidnplayr 188
        cmp     dword[esi+11], '-rsa'
9113 hidnplayr 189
        je      .sha1
190
 
191
  .not_ssh_rsa:
192
        cmp     dword[esi+4], 0x0c000000
193
        jne     .not_sha2
194
        cmp     dword[esi+8], 'rsa-'
195
        jne     .not_sha2
196
        cmp     dword[esi+12], 'sha2'
197
        jne     .not_sha2
198
        cmp     dword[esi+16], '-256'
199
        je      .sha2_256
200
;        cmp     dword[esi+16], '-512'
201
;        je      .sha2_512
202
 
203
  .not_sha2:
204
        jmp     .err_signature
205
 
206
  .sha1:
207
        DEBUGF  3, "SSH: Using RSA with SHA1 hash\n"
9106 hidnplayr 208
        add     esi, 4+4+7
9113 hidnplayr 209
        push    esi
9106 hidnplayr 210
 
211
; EMSA-PKCS1-v1_5
212
        invoke  sha1_init, [h_ctx]
213
        invoke  sha1_update, [h_ctx], [M], [message_len]
214
        invoke  sha1_final, [h_ctx]
215
 
216
        mov     edi, [EM_accent]
217
        mov     al, 0x00
218
        stosb
219
        mov     al, 0x01
220
        stosb
9113 hidnplayr 221
        mov     ecx, 256 - (rsa_sha1_T.len + 3 + SHA1_HASH_SIZE)
9106 hidnplayr 222
        mov     al, 0xff
223
        rep stosb
224
        mov     al, 0x00
225
        stosb
9113 hidnplayr 226
        mov     esi, rsa_sha1_T
227
        mov     ecx, rsa_sha1_T.len
9106 hidnplayr 228
        rep movsb
229
        mov     esi, [h_ctx]
230
        mov     ecx, SHA1_HASH_SIZE
231
        rep movsb
232
 
9113 hidnplayr 233
        pop     esi
234
        jmp     .rsa
235
 
236
  .sha2_256:
237
        DEBUGF  3, "SSH: Using RSA with SHA2-256 hash\n"
238
        add     esi, 4+4+12
239
        push    esi
240
 
241
; EMSA-PKCS1-v1_5
242
        invoke  sha256_init, [h_ctx]
243
        invoke  sha256_update, [h_ctx], [M], [message_len]
244
        invoke  sha256_final, [h_ctx]
245
 
246
        mov     edi, [EM_accent]
247
        mov     al, 0x00
248
        stosb
249
        mov     al, 0x01
250
        stosb
251
        mov     ecx, 256 - (rsa_sha256_T.len + 3 + SHA256_HASH_SIZE)
252
        mov     al, 0xff
253
        rep stosb
254
        mov     al, 0x00
255
        stosb
256
        mov     esi, rsa_sha256_T
257
        mov     ecx, rsa_sha256_T.len
258
        rep movsb
259
        mov     esi, [h_ctx]
260
        mov     ecx, SHA256_HASH_SIZE
261
        rep movsb
262
 
263
        pop     esi
264
        jmp     .rsa
265
 
266
  .rsa:
267
; RSA signature blob
268
        stdcall mpint_to_little_endian, [mpint_s], esi
269
;        cmp     eax, [k]
270
 ;;;       jne     .err_signature
271
 
272
; RSAVP1
273
        stdcall mpint_modexp, [mpint_m], [mpint_s], [mpint_e], [mpint_n]
274
; I2OSP
275
        stdcall mpint_shrink, [mpint_m]
276
        stdcall mpint_grow, [mpint_m], 256
277
        stdcall mpint_to_big_endian, [EM], [mpint_m]
278
 
9106 hidnplayr 279
; Compare EM with EM_accent
280
        mov     esi, [EM]
281
        add     esi, 4
282
        mov     edi, [EM_accent]
283
        mov     ecx, 256/4
284
        xor     eax, eax
285
  .ct_cmp_loop:
286
        mov     ebx, [esi]
287
        xor     ebx, [edi]
288
        or      eax, ebx
289
        lea     esi, [esi+4]
290
        lea     edi, [edi+4]
291
        dec     ecx
292
        jnz     .ct_cmp_loop
293
 
294
        push    eax
295
        mcall   68, 13, [h_ctx]
296
        pop     eax
297
 
298
        test    eax, eax
299
        jnz     .fail
300
 
301
        DEBUGF  3, "SSH: RSA verification OK!\n"
302
 
303
        ret
304
 
305
  .fail:
306
        DEBUGF  3, "SSH: RSA verification failed!\n"
307
        mov     eax, SSHLIB_ERR_HKEY_VERIFY_FAIL
308
        ret
309
 
310
  .err_nomem:
311
        mov     eax, SSHLIB_ERR_NOMEM
312
        ret
313
 
314
  .err_signature:
315
        mov     eax, SSHLIB_ERR_HKEY_SIGNATURE
316
        ret
317
 
318
  .err_key:
319
        mov     eax, SSHLIB_ERR_HKEY_PUBLIC_KEY
320
        ret
321
 
322
endp
323
 
324
 
9112 hidnplayr 325
base64_encode:
326
 
327
        xor     ebx, ebx
328
  .loop:
329
        lodsb
330
        call    .byte
331
        dec     ecx
332
        jnz     .loop
333
 
334
  .final:
335
        mov     al, 0
336
        test    ebx, ebx
337
        jz      .f000
338
        call    .byte
339
        test    ebx, ebx
340
        jz      .f001
341
        call    .byte
342
        mov     byte[edi-2], '='
343
 
344
  .f001:
345
        mov     byte[edi-1], '='
346
 
347
  .f000:
348
        mov     byte[edi], 0
349
        ret
350
 
351
  .byte:
352
        inc     ebx
353
        shl     edx, 8
354
        mov     dl, al
355
        cmp     ebx, 3
356
        je      .b001
357
        ret
358
 
359
  .b001:
360
        shl     edx, 8
361
        inc     ebx
362
 
363
  .b002:
364
        rol     edx, 6
365
        xor     eax, eax
366
        xchg    al, dl
367
        mov     al, [base64_table+eax]
368
        stosb
369
        dec     ebx
370
        jnz     .b002
371
        ret
372
 
373
 
374
 
375
 
9106 hidnplayr 376
iglobal
377
 
9112 hidnplayr 378
        known_hostsfile db '/sys/settings/known_hosts.ini', 0
379
        base64_table    db 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
9113 hidnplayr 380
        rsa_sha1_T      db 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14
381
        .len = $ - rsa_sha1_T
382
        rsa_sha256_T    db 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
383
        .len = $ - rsa_sha256_T
9112 hidnplayr 384
        ssh_rsa_sz      db 'ssh-rsa', 0
9106 hidnplayr 385
 
386
endg
387