Subversion Repositories Kolibri OS

Rev

Rev 9112 | Rev 9114 | 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. ; https://datatracker.ietf.org/doc/html/rfc4716
  21. ; https://datatracker.ietf.org/doc/html/rfc8017
  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.  
  183. ; Host key type (string)
  184.         cmp     dword[esi+4], 0x07000000
  185.         jne     .not_ssh_rsa
  186.         cmp     dword[esi+8], 'ssh-'
  187.         jne     .not_ssh_rsa
  188.         cmp     dword[esi+11], '-rsa'
  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"
  208.         add     esi, 4+4+7
  209.         push    esi
  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
  221.         mov     ecx, 256 - (rsa_sha1_T.len + 3 + SHA1_HASH_SIZE)
  222.         mov     al, 0xff
  223.         rep stosb
  224.         mov     al, 0x00
  225.         stosb
  226.         mov     esi, rsa_sha1_T
  227.         mov     ecx, rsa_sha1_T.len
  228.         rep movsb
  229.         mov     esi, [h_ctx]
  230.         mov     ecx, SHA1_HASH_SIZE
  231.         rep movsb
  232.  
  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.  
  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.  
  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.  
  376. iglobal
  377.  
  378.         known_hostsfile db '/sys/settings/known_hosts.ini', 0
  379.         base64_table    db 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
  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
  384.         ssh_rsa_sz      db 'ssh-rsa', 0
  385.  
  386. endg
  387.  
  388.