Subversion Repositories Kolibri OS

Rev

Rev 9106 | Rev 9113 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  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 <http://www.gnu.org/licenses/>.
  17.  
  18. ; https://datatracker.ietf.org/doc/html/rfc4253#section-6.6
  19. ; https://datatracker.ietf.org/doc/html/rfc3447
  20.  
  21. ; https://datatracker.ietf.org/doc/html/rfc4716
  22.  
  23. proc sshlib_host_verify  con_ptr, str_host_key, str_signature, message, message_len
  24.  
  25. locals
  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 ?
  31. endl
  32.  
  33.         mov     eax, [con_ptr]
  34.         lea     ebx, [eax + sshlib_connection.hostname_sz]
  35.         mov     [hostname_sz], ebx
  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
  46.         mov     [key_name_sz], ssh_rsa_sz
  47.  
  48.   .lookup:
  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
  57.  
  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
  79.  
  80.   .match:
  81.         xor     eax, eax
  82.         ret
  83.  
  84.   .mismatch:
  85. int3
  86.         lea     eax, [current_hkb64]
  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:
  93.         lea     eax, [current_hkb64]
  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:
  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
  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
  182. ; Host key type (string)
  183.         cmp     dword[esi+4], 0x07000000
  184.         jne     .err_signature
  185.         cmp     dword[esi+8], 'ssh-'
  186.         jne     .err_signature
  187.         cmp     dword[esi+11], '-rsa'
  188.         jne     .err_signature
  189.         add     esi, 4+4+7
  190. ; RSA signature blob
  191.         stdcall mpint_to_little_endian, [mpint_s], esi
  192. ;        cmp     eax, [k]
  193.  ;;;       jne     .err_signature
  194.  
  195. ; RSAVP1
  196.         stdcall mpint_modexp, [mpint_m], [mpint_s], [mpint_e], [mpint_n]
  197. ; I2OSP
  198.         stdcall mpint_shrink, [mpint_m]
  199.         stdcall mpint_grow, [mpint_m], 256
  200.         stdcall mpint_to_big_endian, [EM], [mpint_m]
  201.  
  202. ; EMSA-PKCS1-v1_5
  203.         invoke  sha1_init, [h_ctx]
  204.         invoke  sha1_update, [h_ctx], [M], [message_len]
  205.         invoke  sha1_final, [h_ctx]
  206.  
  207.         mov     edi, [EM_accent]
  208.         mov     al, 0x00
  209.         stosb
  210.         mov     al, 0x01
  211.         stosb
  212.         mov     ecx, 256 - (rsa_sha1_t.len + 3 + SHA1_HASH_SIZE)
  213.         mov     al, 0xff
  214.         rep stosb
  215.         mov     al, 0x00
  216.         stosb
  217.         mov     esi, rsa_sha1_t
  218.         mov     ecx, rsa_sha1_t.len
  219.         rep movsb
  220.         mov     esi, [h_ctx]
  221.         mov     ecx, SHA1_HASH_SIZE
  222.         rep movsb
  223.  
  224. ; Compare EM with EM_accent
  225.         mov     esi, [EM]
  226.         add     esi, 4
  227.         mov     edi, [EM_accent]
  228.         mov     ecx, 256/4
  229.         xor     eax, eax
  230.   .ct_cmp_loop:
  231.         mov     ebx, [esi]
  232.         xor     ebx, [edi]
  233.         or      eax, ebx
  234.         lea     esi, [esi+4]
  235.         lea     edi, [edi+4]
  236.         dec     ecx
  237.         jnz     .ct_cmp_loop
  238.  
  239.         push    eax
  240.         mcall   68, 13, [h_ctx]
  241.         pop     eax
  242.  
  243.         test    eax, eax
  244.         jnz     .fail
  245.  
  246.         DEBUGF  3, "SSH: RSA verification OK!\n"
  247.  
  248.         ret
  249.  
  250.   .fail:
  251.         DEBUGF  3, "SSH: RSA verification failed!\n"
  252.         mov     eax, SSHLIB_ERR_HKEY_VERIFY_FAIL
  253.         ret
  254.  
  255.   .err_nomem:
  256.         mov     eax, SSHLIB_ERR_NOMEM
  257.         ret
  258.  
  259.   .err_signature:
  260.         mov     eax, SSHLIB_ERR_HKEY_SIGNATURE
  261.         ret
  262.  
  263.   .err_key:
  264.         mov     eax, SSHLIB_ERR_HKEY_PUBLIC_KEY
  265.         ret
  266.  
  267. endp
  268.  
  269.  
  270. base64_encode:
  271.  
  272.         xor     ebx, ebx
  273.   .loop:
  274.         lodsb
  275.         call    .byte
  276.         dec     ecx
  277.         jnz     .loop
  278.  
  279.   .final:
  280.         mov     al, 0
  281.         test    ebx, ebx
  282.         jz      .f000
  283.         call    .byte
  284.         test    ebx, ebx
  285.         jz      .f001
  286.         call    .byte
  287.         mov     byte[edi-2], '='
  288.  
  289.   .f001:
  290.         mov     byte[edi-1], '='
  291.  
  292.   .f000:
  293.         mov     byte[edi], 0
  294.         ret
  295.  
  296.   .byte:
  297.         inc     ebx
  298.         shl     edx, 8
  299.         mov     dl, al
  300.         cmp     ebx, 3
  301.         je      .b001
  302.         ret
  303.  
  304.   .b001:
  305.         shl     edx, 8
  306.         inc     ebx
  307.  
  308.   .b002:
  309.         rol     edx, 6
  310.         xor     eax, eax
  311.         xchg    al, dl
  312.         mov     al, [base64_table+eax]
  313.         stosb
  314.         dec     ebx
  315.         jnz     .b002
  316.         ret
  317.  
  318.  
  319.  
  320.  
  321. iglobal
  322.  
  323.         known_hostsfile db '/sys/settings/known_hosts.ini', 0
  324.         base64_table    db 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
  325.         rsa_sha1_t      db 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14
  326.         .len = $ - rsa_sha1_t
  327.         ssh_rsa_sz      db 'ssh-rsa', 0
  328.  
  329. endg
  330.  
  331.