Subversion Repositories Kolibri OS

Rev

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