Subversion Repositories Kolibri OS

Rev

Rev 9114 | Rev 9216 | 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
 
9126 hidnplayr 131
        k                       dd ?    ; Key length
9106 hidnplayr 132
 
133
endl
134
 
135
        DEBUGF  3, "SSH: Performing RSA verification\n"
136
 
137
        mcall   68, 12, sizeof.crash_ctx + 5*(MAX_BITS/8+4)
138
        test    eax, eax
139
        jz      .err_nomem
140
        mov     [h_ctx], eax
141
        add     eax, sizeof.crash_ctx
142
        mov     [mpint_e], eax
143
        add     eax, MAX_BITS/8+4
144
        mov     [mpint_n], eax
145
        add     eax, MAX_BITS/8+4
146
        mov     [mpint_m], eax
147
        add     eax, MAX_BITS/8+4
148
        mov     [EM], eax
149
        add     eax, MAX_BITS/8+4
150
        mov     [EM_accent], eax
151
        add     eax, MAX_BITS/8+4
152
        mov     [mpint_s], eax
153
;        add     eax, MAX_BITS/8+4
154
 
155
; Host key
156
        mov     esi, [str_host_key]
157
        mov     ecx, [esi]
158
        bswap   ecx
159
        cmp     ecx, MAX_PUBLIC_KEY_SIZE
160
        ja      .err_key
161
; Host key type (string)
162
        cmp     dword[esi+4], 0x07000000
163
        jne     .err_key
164
        cmp     dword[esi+8], 'ssh-'
165
        jne     .err_key
166
        cmp     dword[esi+11], '-rsa'
167
        jne     .err_key
168
        add     esi, 4+4+7
169
; mpint e
170
        stdcall mpint_to_little_endian, [mpint_e], esi
171
        add     esi, eax
172
        add     esi, 4
173
; mpint n
174
        stdcall mpint_to_little_endian, [mpint_n], esi
9126 hidnplayr 175
        and     eax, not (32-1)         ; CHECKME
176
        mov     [k], eax
9106 hidnplayr 177
 
178
; Signature
179
        mov     esi, [str_signature]
180
        mov     ecx, [esi]
9126 hidnplayr 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
9114 hidnplayr 200
        cmp     dword[esi+16], '-512'
201
        je      .sha2_512
9113 hidnplayr 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
9126 hidnplayr 221
        mov     ecx, [k]
222
        sub     ecx, (rsa_sha1_T.len + 3 + SHA1_HASH_SIZE)
223
        jl      .err_key
224
        jz      @f
9106 hidnplayr 225
        mov     al, 0xff
226
        rep stosb
9126 hidnplayr 227
  @@:
9106 hidnplayr 228
        mov     al, 0x00
229
        stosb
9113 hidnplayr 230
        mov     esi, rsa_sha1_T
231
        mov     ecx, rsa_sha1_T.len
9106 hidnplayr 232
        rep movsb
233
        mov     esi, [h_ctx]
234
        mov     ecx, SHA1_HASH_SIZE
235
        rep movsb
236
 
9113 hidnplayr 237
        pop     esi
238
        jmp     .rsa
239
 
240
  .sha2_256:
241
        DEBUGF  3, "SSH: Using RSA with SHA2-256 hash\n"
242
        add     esi, 4+4+12
243
        push    esi
244
 
245
; EMSA-PKCS1-v1_5
246
        invoke  sha256_init, [h_ctx]
247
        invoke  sha256_update, [h_ctx], [M], [message_len]
248
        invoke  sha256_final, [h_ctx]
249
 
250
        mov     edi, [EM_accent]
251
        mov     al, 0x00
252
        stosb
253
        mov     al, 0x01
254
        stosb
9126 hidnplayr 255
        mov     ecx, [k]
256
        sub     ecx, (rsa_sha256_T.len + 3 + SHA256_HASH_SIZE)
257
        jl      .err_key
258
        jz      @f
9113 hidnplayr 259
        mov     al, 0xff
260
        rep stosb
9126 hidnplayr 261
  @@:
9113 hidnplayr 262
        mov     al, 0x00
263
        stosb
264
        mov     esi, rsa_sha256_T
265
        mov     ecx, rsa_sha256_T.len
266
        rep movsb
267
        mov     esi, [h_ctx]
268
        mov     ecx, SHA256_HASH_SIZE
269
        rep movsb
270
 
271
        pop     esi
272
        jmp     .rsa
273
 
9114 hidnplayr 274
  .sha2_512:
275
        DEBUGF  3, "SSH: Using RSA with SHA2-512 hash\n"
276
        add     esi, 4+4+12
277
        push    esi
278
 
279
; EMSA-PKCS1-v1_5
280
        invoke  sha512_init, [h_ctx]
281
        invoke  sha512_update, [h_ctx], [M], [message_len]
282
        invoke  sha512_final, [h_ctx]
283
 
284
        mov     edi, [EM_accent]
285
        mov     al, 0x00
286
        stosb
287
        mov     al, 0x01
288
        stosb
9126 hidnplayr 289
        mov     ecx, [k]
290
        sub     ecx, (rsa_sha512_T.len + 3 + SHA512_HASH_SIZE)
291
        jl      .err_key
292
        jz      @f
9114 hidnplayr 293
        mov     al, 0xff
294
        rep stosb
9126 hidnplayr 295
  @@:
9114 hidnplayr 296
        mov     al, 0x00
297
        stosb
298
        mov     esi, rsa_sha512_T
299
        mov     ecx, rsa_sha512_T.len
300
        rep movsb
301
        mov     esi, [h_ctx]
302
        mov     ecx, SHA512_HASH_SIZE
303
        rep movsb
304
 
305
        pop     esi
306
        jmp     .rsa
307
 
9113 hidnplayr 308
  .rsa:
309
; RSA signature blob
310
        stdcall mpint_to_little_endian, [mpint_s], esi
311
;        cmp     eax, [k]
9126 hidnplayr 312
;        jne     .err_signature
9113 hidnplayr 313
 
314
; RSAVP1
315
        stdcall mpint_modexp, [mpint_m], [mpint_s], [mpint_e], [mpint_n]
316
; I2OSP
317
        stdcall mpint_shrink, [mpint_m]
9126 hidnplayr 318
        stdcall mpint_grow, [mpint_m], [k]
9113 hidnplayr 319
        stdcall mpint_to_big_endian, [EM], [mpint_m]
320
 
9106 hidnplayr 321
; Compare EM with EM_accent
322
        mov     esi, [EM]
323
        add     esi, 4
324
        mov     edi, [EM_accent]
9126 hidnplayr 325
        mov     ecx, [k]
326
        shr     ecx, 2
9106 hidnplayr 327
        xor     eax, eax
328
  .ct_cmp_loop:
329
        mov     ebx, [esi]
330
        xor     ebx, [edi]
331
        or      eax, ebx
332
        lea     esi, [esi+4]
333
        lea     edi, [edi+4]
334
        dec     ecx
335
        jnz     .ct_cmp_loop
336
 
337
        push    eax
338
        mcall   68, 13, [h_ctx]
339
        pop     eax
340
 
341
        test    eax, eax
342
        jnz     .fail
343
 
344
        DEBUGF  3, "SSH: RSA verification OK!\n"
345
 
346
        ret
347
 
348
  .fail:
349
        DEBUGF  3, "SSH: RSA verification failed!\n"
350
        mov     eax, SSHLIB_ERR_HKEY_VERIFY_FAIL
351
        ret
352
 
353
  .err_nomem:
354
        mov     eax, SSHLIB_ERR_NOMEM
355
        ret
356
 
357
  .err_signature:
358
        mov     eax, SSHLIB_ERR_HKEY_SIGNATURE
359
        ret
360
 
361
  .err_key:
362
        mov     eax, SSHLIB_ERR_HKEY_PUBLIC_KEY
363
        ret
364
 
365
endp
366
 
367
 
9112 hidnplayr 368
base64_encode:
369
 
370
        xor     ebx, ebx
371
  .loop:
372
        lodsb
373
        call    .byte
374
        dec     ecx
375
        jnz     .loop
376
 
377
  .final:
378
        mov     al, 0
379
        test    ebx, ebx
380
        jz      .f000
381
        call    .byte
382
        test    ebx, ebx
383
        jz      .f001
384
        call    .byte
385
        mov     byte[edi-2], '='
386
 
387
  .f001:
388
        mov     byte[edi-1], '='
389
 
390
  .f000:
391
        mov     byte[edi], 0
392
        ret
393
 
394
  .byte:
395
        inc     ebx
396
        shl     edx, 8
397
        mov     dl, al
398
        cmp     ebx, 3
399
        je      .b001
400
        ret
401
 
402
  .b001:
403
        shl     edx, 8
404
        inc     ebx
405
 
406
  .b002:
407
        rol     edx, 6
408
        xor     eax, eax
409
        xchg    al, dl
410
        mov     al, [base64_table+eax]
411
        stosb
412
        dec     ebx
413
        jnz     .b002
414
        ret
415
 
416
 
417
 
418
 
9106 hidnplayr 419
iglobal
420
 
9112 hidnplayr 421
        known_hostsfile db '/sys/settings/known_hosts.ini', 0
422
        base64_table    db 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
9113 hidnplayr 423
        rsa_sha1_T      db 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14
424
        .len = $ - rsa_sha1_T
425
        rsa_sha256_T    db 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
426
        .len = $ - rsa_sha256_T
9114 hidnplayr 427
        rsa_sha512_T    db 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40
428
        .len = $ - rsa_sha512_T
9112 hidnplayr 429
        ssh_rsa_sz      db 'ssh-rsa', 0
9106 hidnplayr 430
 
431
endg
432