; sshlib_host.inc - SSH remote host authentication ; ; Copyright (C) 2021 Jeffrey Amelynck ; ; This program is free software: you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation, either version 3 of the License, or ; (at your option) any later version. ; ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with this program. If not, see . ; https://datatracker.ietf.org/doc/html/rfc4253#section-6.6 ; https://datatracker.ietf.org/doc/html/rfc3447 proc sshlib_host_verify con_ptr, str_host_key, str_signature, message, message_len locals known_key_sz rb MAX_PUBLIC_KEY_SIZE endl mov eax, [con_ptr] cmp [eax+sshlib_connection.algo_hostkey], SSHLIB_HOSTKEY_RSA je .rsa ; ..add more here mov eax, SSHLIB_ERR_HKEY_NO_ALGO ret .rsa: stdcall sshlib_host_verify_rsa, [str_host_key], [str_signature], [message], [message_len] test eax, eax jnz .err .lookup: ; lea eax, [known_key_sz] ; mov ebx, [con_ptr] ; lea ebx, [ebx + sshlib_connection.hostname_sz] ; invoke ini_get_str, known_hosts_file, ebx, ssh_rsa_sz, eax, MAX_PUBLIC_KEY_SIZE, null_sz ; test eax, eax ; jnz .unknown ; TODO: verify cached host key ; jne .mismatch jmp .unknown ; FIXME xor eax, eax ret .mismatch: lea eax, [known_key_sz] stdcall sshlib_callback_hostkey_problem, [con_ptr], SSHLIB_HOSTKEY_PROBLEM_MISMATCH, eax cmp eax, SSHLIB_HOSTKEY_ACCEPT je .store ret .unknown: lea eax, [known_key_sz] stdcall sshlib_callback_hostkey_problem, [con_ptr], SSHLIB_HOSTKEY_PROBLEM_UNKNOWN, eax cmp eax, SSHLIB_HOSTKEY_ACCEPT je .store ret .store: ; TODO: write to know_hosts file and fall-through ret .err: ret endp ; https://datatracker.ietf.org/doc/html/rfc3447#section-8.2.2 ; RSASSA-PKCS1-V1_5-VERIFY proc sshlib_host_verify_rsa str_host_key, str_signature, M, message_len locals h_ctx dd ? ; Signer's RSA public key mpint_e dd ? ; public exponent mpint_n dd ? ; modulus mpint_m dd ? EM dd ? EM_accent dd ? mpint_s dd ? ; rsa_signature_blob ; k dd ? ; length of RSA modulus n endl DEBUGF 3, "SSH: Performing RSA verification\n" mcall 68, 12, sizeof.crash_ctx + 5*(MAX_BITS/8+4) test eax, eax jz .err_nomem mov [h_ctx], eax add eax, sizeof.crash_ctx mov [mpint_e], eax add eax, MAX_BITS/8+4 mov [mpint_n], eax add eax, MAX_BITS/8+4 mov [mpint_m], eax add eax, MAX_BITS/8+4 mov [EM], eax add eax, MAX_BITS/8+4 mov [EM_accent], eax add eax, MAX_BITS/8+4 mov [mpint_s], eax ; add eax, MAX_BITS/8+4 ; Host key mov esi, [str_host_key] mov ecx, [esi] bswap ecx cmp ecx, MAX_PUBLIC_KEY_SIZE ja .err_key ; Host key type (string) cmp dword[esi+4], 0x07000000 jne .err_key cmp dword[esi+8], 'ssh-' jne .err_key cmp dword[esi+11], '-rsa' jne .err_key add esi, 4+4+7 ; mpint e stdcall mpint_to_little_endian, [mpint_e], esi add esi, eax add esi, 4 ; mpint n stdcall mpint_to_little_endian, [mpint_n], esi ; mov [k], eax ;; HMMMM FIXME, 0-byte.. ; Signature mov esi, [str_signature] mov ecx, [esi] bswap ecx ; TODO: check length ; Host key type (string) cmp dword[esi+4], 0x07000000 jne .err_signature cmp dword[esi+8], 'ssh-' jne .err_signature cmp dword[esi+11], '-rsa' jne .err_signature add esi, 4+4+7 ; RSA signature blob stdcall mpint_to_little_endian, [mpint_s], esi ; cmp eax, [k] ;;; jne .err_signature ; RSAVP1 stdcall mpint_modexp, [mpint_m], [mpint_s], [mpint_e], [mpint_n] ; I2OSP stdcall mpint_shrink, [mpint_m] stdcall mpint_grow, [mpint_m], 256 stdcall mpint_to_big_endian, [EM], [mpint_m] ; EMSA-PKCS1-v1_5 invoke sha1_init, [h_ctx] invoke sha1_update, [h_ctx], [M], [message_len] invoke sha1_final, [h_ctx] mov edi, [EM_accent] mov al, 0x00 stosb mov al, 0x01 stosb mov ecx, 256 - (rsa_sha1_t.len + 3 + SHA1_HASH_SIZE) mov al, 0xff rep stosb mov al, 0x00 stosb mov esi, rsa_sha1_t mov ecx, rsa_sha1_t.len rep movsb mov esi, [h_ctx] mov ecx, SHA1_HASH_SIZE rep movsb ; Compare EM with EM_accent mov esi, [EM] add esi, 4 mov edi, [EM_accent] mov ecx, 256/4 xor eax, eax .ct_cmp_loop: mov ebx, [esi] xor ebx, [edi] or eax, ebx lea esi, [esi+4] lea edi, [edi+4] dec ecx jnz .ct_cmp_loop push eax mcall 68, 13, [h_ctx] pop eax test eax, eax jnz .fail DEBUGF 3, "SSH: RSA verification OK!\n" ret .fail: DEBUGF 3, "SSH: RSA verification failed!\n" mov eax, SSHLIB_ERR_HKEY_VERIFY_FAIL ret .err_nomem: mov eax, SSHLIB_ERR_NOMEM ret .err_signature: mov eax, SSHLIB_ERR_HKEY_SIGNATURE ret .err_key: mov eax, SSHLIB_ERR_HKEY_PUBLIC_KEY ret endp iglobal rsa_sha1_t db 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14 .len = $ - rsa_sha1_t endg