Subversion Repositories Kolibri OS

Rev

Rev 9114 | Rev 9216 | 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.         k                       dd ?    ; Key length
  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
  175.         and     eax, not (32-1)         ; CHECKME
  176.         mov     [k], eax
  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, [k]
  222.         sub     ecx, (rsa_sha1_T.len + 3 + SHA1_HASH_SIZE)
  223.         jl      .err_key
  224.         jz      @f
  225.         mov     al, 0xff
  226.         rep stosb
  227.   @@:
  228.         mov     al, 0x00
  229.         stosb
  230.         mov     esi, rsa_sha1_T
  231.         mov     ecx, rsa_sha1_T.len
  232.         rep movsb
  233.         mov     esi, [h_ctx]
  234.         mov     ecx, SHA1_HASH_SIZE
  235.         rep movsb
  236.  
  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
  255.         mov     ecx, [k]
  256.         sub     ecx, (rsa_sha256_T.len + 3 + SHA256_HASH_SIZE)
  257.         jl      .err_key
  258.         jz      @f
  259.         mov     al, 0xff
  260.         rep stosb
  261.   @@:
  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.  
  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
  289.         mov     ecx, [k]
  290.         sub     ecx, (rsa_sha512_T.len + 3 + SHA512_HASH_SIZE)
  291.         jl      .err_key
  292.         jz      @f
  293.         mov     al, 0xff
  294.         rep stosb
  295.   @@:
  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.  
  308.   .rsa:
  309. ; RSA signature blob
  310.         stdcall mpint_to_little_endian, [mpint_s], esi
  311. ;        cmp     eax, [k]
  312. ;        jne     .err_signature
  313.  
  314. ; RSAVP1
  315.         stdcall mpint_modexp, [mpint_m], [mpint_s], [mpint_e], [mpint_n]
  316. ; I2OSP
  317.         stdcall mpint_shrink, [mpint_m]
  318.         stdcall mpint_grow, [mpint_m], [k]
  319.         stdcall mpint_to_big_endian, [EM], [mpint_m]
  320.  
  321. ; Compare EM with EM_accent
  322.         mov     esi, [EM]
  323.         add     esi, 4
  324.         mov     edi, [EM_accent]
  325.         mov     ecx, [k]
  326.         shr     ecx, 2
  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.  
  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.  
  419. iglobal
  420.  
  421.         known_hostsfile db '/sys/settings/known_hosts.ini', 0
  422.         base64_table    db 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
  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
  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
  429.         ssh_rsa_sz      db 'ssh-rsa', 0
  430.  
  431. endg
  432.  
  433.