Subversion Repositories Kolibri OS

Rev

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

  1. ;    sshlib_transport.inc - SSH transport layer
  2. ;
  3. ;    Copyright (C) 2016-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.  
  19. proc sshlib_padd_null
  20.  
  21.         xor     eax, eax
  22.         ret
  23.  
  24. endp
  25.  
  26. proc sshlib_crypt_null ctx, src, dst
  27.  
  28. ; Assume src == dst !
  29.  
  30.         ret
  31.  
  32. endp
  33.  
  34. proc sshlib_recv_packet con_ptr, flags
  35.  
  36. locals
  37.         data_length     dd ?    ; Total length of packet without MAC
  38. endl
  39.  
  40.         DEBUGF  3, "> "
  41. ; Receive first block (Read length, padding length, message code)
  42.         mov     ebx, [con_ptr]
  43.         mov     ecx, [ebx+sshlib_connection.socketnum]
  44.         mov     esi, [ebx+sshlib_connection.rx_crypt_blocksize]
  45.         lea     edx, [ebx+sshlib_connection.rx_buffer]
  46.         mov     edi, [flags]
  47.         mcall   recv
  48.         cmp     eax, 0
  49.         jle     .sock_fail
  50.         sub     [ssh_chan.rcv_wnd], eax  ;;; FIXME
  51.         DEBUGF  1, "chunk = %u ", eax
  52.         mov     ebx, [con_ptr]
  53.         cmp     eax, [ebx+sshlib_connection.rx_crypt_blocksize]
  54.         jne     .proto_fail     ; TODO: handle receives of 1, 2, and 3 bytes correctly
  55.  
  56. ; Decrypt first block
  57.         pusha
  58.         lea     esi, [ebx+sshlib_connection.rx_buffer]
  59.         stdcall [ebx+sshlib_connection.rx_crypt_proc], [ebx+sshlib_connection.rx_crypt_ctx_ptr], esi, esi
  60.         popa
  61.  
  62. ; Check data length
  63.         mov     esi, [ebx + sshlib_connection.rx_buffer.packet_length]
  64.         bswap   esi                                             ; convert length to little endian
  65.         mov     [ebx+sshlib_connection.rx_buffer.packet_length], esi
  66.         DEBUGF  1, "packet length=%u ", esi
  67.         cmp     esi, BUFFERSIZE
  68.         ja      .proto_fail                                     ; packet is too large
  69.  
  70. ; Calculate amount of remaining data
  71.         add     esi, 4                                          ; Packet length field itself is not included in the count
  72.         sub     esi, [ebx+sshlib_connection.rx_crypt_blocksize]    ; Already received this amount of data
  73.         add     esi, [ebx+sshlib_connection.rx_mac_length]
  74.         jz      .packet_complete
  75.  
  76. ; Receive remaining data
  77.         lea     edx, [ebx+sshlib_connection.rx_buffer]
  78.         add     edx, [ebx+sshlib_connection.rx_crypt_blocksize]
  79.         mov     ecx, [ebx+sshlib_connection.socketnum]
  80.         mov     edi, [flags]
  81.   .receive_loop:
  82.         DEBUGF  3, "want %d bytes.. ", esi
  83.         mcall   recv
  84.         cmp     eax, 0
  85.         jle     .sock_fail
  86.         sub     [ssh_chan.rcv_wnd], eax             ;;; FIXME
  87.         DEBUGF  3, "got %d bytes\n", eax
  88.         add     edx, eax
  89.         sub     esi, eax
  90.         jnz     .receive_loop
  91.  
  92. ; Decrypt data
  93.         mov     ebx, [con_ptr]
  94.         mov     ecx, [ebx + sshlib_connection.rx_buffer.packet_length]
  95.         add     ecx, 4                                          ; Packet_length field itself
  96.         sub     ecx, [ebx+sshlib_connection.rx_crypt_blocksize]    ; Already decrypted this amount of data
  97.         jz      .decrypt_complete
  98.  
  99.         lea     esi, [ebx+sshlib_connection.rx_buffer]
  100.         add     esi, [ebx+sshlib_connection.rx_crypt_blocksize]
  101.   .decrypt_loop:
  102.         pusha
  103.         stdcall [ebx+sshlib_connection.rx_crypt_proc], [ebx+sshlib_connection.rx_crypt_ctx_ptr], esi, esi
  104.         popa
  105.         add     esi, [ebx+sshlib_connection.rx_crypt_blocksize]
  106.         sub     ecx, [ebx+sshlib_connection.rx_crypt_blocksize]
  107.         jnz     .decrypt_loop
  108.   .decrypt_complete:
  109.  
  110. ; Authenticate message
  111.         cmp     [ebx+sshlib_connection.rx_mac_proc], 0
  112.         je      .mac_complete
  113.         lea     esi, [ebx+sshlib_connection.rx_mac_seqnr]
  114.         mov     ecx, [ebx+sshlib_connection.rx_buffer.packet_length]
  115.         add     ecx, 8                                          ; packet_length field itself + sequence number
  116.         lea     eax, [ebx+sshlib_connection.rx_mac_ctx]
  117. ;        push    [ebx+sshlib_connection.rx_buffer.packet_length]
  118.         mov     edx, [ebx+sshlib_connection.rx_buffer.packet_length]
  119.         bswap   edx                                             ; convert length to big endian
  120.         mov     [ebx+sshlib_connection.rx_buffer.packet_length], edx
  121.         stdcall [ebx+sshlib_connection.rx_mac_proc], eax, esi, ecx
  122. ;        pop     [ebx+sshlib_connection.rx_buffer.packet_length]
  123.         mov     edx, [ebx+sshlib_connection.rx_buffer.packet_length]
  124.         bswap   edx                                             ; convert length to little endian
  125.         mov     [ebx+sshlib_connection.rx_buffer.packet_length], edx
  126.  
  127.         lea     esi, [ebx+sshlib_connection.rx_mac_ctx]
  128.         lea     edi, [ebx+sshlib_connection.rx_buffer+4]
  129.         add     edi, [ebx+sshlib_connection.rx_buffer.packet_length]
  130.         mov     ecx, [ebx+sshlib_connection.rx_mac_length]
  131.         shr     ecx, 2
  132.         repe cmpsd
  133.         jne     .mac_fail
  134.   .mac_complete:
  135.         add     byte[ebx+sshlib_connection.rx_mac_seqnr+3], 1      ; Update sequence counter
  136.         adc     byte[ebx+sshlib_connection.rx_mac_seqnr+2], 0
  137.         adc     byte[ebx+sshlib_connection.rx_mac_seqnr+1], 0
  138.         adc     byte[ebx+sshlib_connection.rx_mac_seqnr+0], 0
  139.  
  140. ; Return useful data length to the caller via eax register
  141.   .packet_complete:
  142.         mov     eax, [ebx+sshlib_connection.rx_buffer.packet_length]
  143.         movzx   ebx, [ebx+sshlib_connection.rx_buffer.padding_length]
  144.         sub     eax, ebx
  145.         DEBUGF  1, "useful data length=%u\n", eax
  146.         ret
  147.  
  148.   .sock_fail:
  149.         DEBUGF  3, "ssh_recv_packet failed!\n"
  150.         mov     eax, SSHLIB_ERR_SOCKET
  151.         ret
  152.  
  153.   .mac_fail:
  154.         DEBUGF  3, "ssh_recv_packet message authentication failed!\n"
  155.         mov     eax, SSHLIB_ERR_MAC_VERIFY_FAIL
  156.         xor     ebx, ebx
  157.         ret
  158.  
  159.   .proto_fail:
  160.         DEBUGF  3, "ssh_recv_packet protocol failure!\n"
  161.         mov     eax, SSHLIB_ERR_PROTOCOL
  162.         xor     ebx, ebx
  163.         ret
  164.  
  165. endp
  166.  
  167.  
  168. proc sshlib_send_packet con_ptr, buf, payload_size, flags
  169.  
  170. locals
  171.         packet_size    dd ?
  172. endl
  173.         DEBUGF  2, "< "
  174.  
  175. ; Check how many bytes we should pad
  176.         mov     eax, [payload_size]
  177.         inc     eax                     ; padding length byte
  178.         lea     edx, [eax+4]            ; total packet size (without padding and MAC)
  179.         mov     [packet_size], edx
  180.  
  181.         mov     ecx, [con_ptr]
  182.         mov     ebx, [ecx+sshlib_connection.tx_pad_size]
  183.         dec     ebx
  184.         and     edx, ebx
  185.         neg     edx
  186.         add     edx, [ecx+sshlib_connection.tx_pad_size]
  187.         add     edx, [ecx+sshlib_connection.tx_pad_size]
  188.         DEBUGF  1, "padding %u bytes ", edx
  189.         add     [packet_size], edx      ; total packet size with padding
  190.  
  191. ; Start building the packet
  192. ; First comes the packet length, in network byte order ofcourse.
  193.         add     eax, edx
  194.         DEBUGF  1, "total size: %u ", eax
  195.         bswap   eax
  196.         lea     edi, [ecx+sshlib_connection.tx_buffer]
  197.         stosd
  198. ; Then the padding length
  199.         mov     al, dl
  200.         stosb
  201. ; And the actual payload bytes
  202.         mov     esi, [buf]
  203.         mov     ecx, [payload_size]
  204.         rep movsb
  205.  
  206. ; Append the packet with #edx padding bytes.
  207. ; Since we must pad at least 8 bytes, we can always use DWORD writes.
  208. ; First do an (unaligned) write exactly following the data
  209.         dec     edx
  210.         mov     esi, edx
  211.         shr     esi, 2          ; number dwords
  212.         mov     ebx, edx
  213.         and     ebx, 3
  214.         inc     ebx             ; number bytes in first write (1-4)
  215.         mov     edx, [con_ptr]
  216.         call    [edx+sshlib_connection.tx_pad_proc]
  217.         mov     dword[edi], eax
  218.         add     edi, ebx
  219. ; Then, do as many aligned writes as nescessary
  220.         mov     ebx, [con_ptr]
  221.   @@:
  222.         call    [ebx+sshlib_connection.tx_pad_proc]
  223.         stosd
  224.         dec     esi
  225.         jnz     @r
  226.  
  227. ; Append the packet with Message Authentication Code
  228.         mov     edx, [con_ptr]
  229.         cmp     [edx+sshlib_connection.tx_mac_proc], 0
  230.         je      .mac_complete
  231.         DEBUGF  1, "MAC sequence number: 0x%x\n", [edx+sshlib_connection.tx_mac_seqnr]
  232.         lea     esi, [edx+sshlib_connection.tx_mac_seqnr]
  233.         mov     ecx, [packet_size]
  234.         add     ecx, 4                                          ; Sequence number length
  235.         lea     eax, [edx+sshlib_connection.tx_mac_ctx]
  236.         stdcall [edx+sshlib_connection.tx_mac_proc], eax, esi, ecx
  237.  
  238.         lea     esi, [edx+sshlib_connection.tx_mac_ctx]
  239.         lea     edi, [edx+sshlib_connection.tx_buffer]
  240.         add     edi, [packet_size]
  241.         mov     ecx, [edx+sshlib_connection.tx_mac_length]
  242.         shr     ecx, 2
  243.         rep movsd
  244.   .mac_complete:
  245.         add     byte[edx+sshlib_connection.tx_mac_seqnr+3], 1      ; Update sequence counter
  246.         adc     byte[edx+sshlib_connection.tx_mac_seqnr+2], 0
  247.         adc     byte[edx+sshlib_connection.tx_mac_seqnr+1], 0
  248.         adc     byte[edx+sshlib_connection.tx_mac_seqnr+0], 0
  249.  
  250. ; Now, encrypt everything but MAC
  251.         lea     esi, [edx+sshlib_connection.tx_buffer]
  252.         mov     ecx, [packet_size]
  253.   .encrypt_loop:
  254.         pusha
  255.         stdcall [edx+sshlib_connection.tx_crypt_proc], [edx+sshlib_connection.tx_crypt_ctx_ptr], esi, esi
  256.         popa
  257.         add     esi, [edx+sshlib_connection.tx_crypt_blocksize]
  258.         sub     ecx, [edx+sshlib_connection.tx_crypt_blocksize]
  259.         jnz     .encrypt_loop
  260.  
  261. ; Send the packet
  262.         mov     ebx, [con_ptr]
  263.         mov     ecx, [ebx+sshlib_connection.socketnum]
  264.         lea     edx, [ebx+sshlib_connection.tx_buffer]
  265.         mov     esi, [packet_size]
  266.         add     esi, [ebx+sshlib_connection.tx_mac_length]
  267.         mov     edi, [flags]
  268.         mcall   send
  269.  
  270.         DEBUGF  1, "\n"
  271.  
  272.         ret
  273.  
  274. endp
  275.  
  276.