Subversion Repositories Kolibri OS

Rev

Rev 6469 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. ;    ssh_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. struct  ssh_packet_header
  20.         packet_length   dd ?    ; The length of the packet in bytes, not including 'mac' or the
  21.                                 ; 'packet_length' field itself.
  22.         padding_length  db ?    ; Length of 'random padding' (bytes).
  23.  
  24.         message_code    db ?    ; First byte of payload
  25. ends
  26.  
  27.  
  28. proc ssh_recv_packet connection, flags
  29.  
  30. locals
  31.         data_length     dd ?    ; Total length of packet without MAC
  32.         socket_error    dd ?
  33. endl
  34.  
  35.         DEBUGF  2, "> "
  36. ; Receive first block (Read length, padding length, message code)
  37.         mov     ebx, [connection]
  38.         mov     ecx, [ebx+ssh_connection.socketnum]
  39.         mov     esi, [ebx+ssh_connection.rx_crypt_blocksize]
  40.         lea     edx, [ebx+ssh_connection.rx_buffer]
  41.         mov     edi, [flags]
  42.         mcall   recv
  43.         mov     [socket_error], ebx
  44.         DEBUGF  1, "chunk = %u ", eax
  45.         mov     ebx, [connection]
  46.         cmp     eax, [ebx+ssh_connection.rx_crypt_blocksize]
  47.         jne     .fail
  48.  
  49. ; Decrypt first block
  50.         cmp     [ebx+ssh_connection.rx_crypt_proc], 0
  51.         je      @f
  52.         pusha
  53.         lea     esi, [ebx+ssh_connection.rx_buffer]
  54.         stdcall [ebx+ssh_connection.rx_crypt_proc], [ebx+ssh_connection.rx_crypt_ctx_ptr], esi, esi
  55.         popa
  56.   @@:
  57.  
  58. ; Check data length
  59.         mov     esi, [ebx+ssh_connection.rx_buffer.packet_length]
  60.         bswap   esi                                             ; convert length to little endian
  61.         mov     [ebx+ssh_connection.rx_buffer.packet_length], esi
  62.         DEBUGF  1, "packet length=%u ", esi
  63.         cmp     esi, BUFFERSIZE
  64.         ja      .fail                                           ; packet is too large
  65.  
  66. ; Calculate amount of remaining data
  67.         add     esi, 4                                          ; Packet length field itself is not included in the count
  68.         sub     esi, [ebx+ssh_connection.rx_crypt_blocksize]    ; Already received this amount of data
  69.         add     esi, [ebx+ssh_connection.rx_mac_length]
  70.         jz      .got_all_data
  71.  
  72. ; Receive remaining data
  73.         lea     edx, [ebx+ssh_connection.rx_buffer]
  74.         add     edx, [ebx+ssh_connection.rx_crypt_blocksize]
  75.         mov     ecx, [ebx+ssh_connection.socketnum]
  76.         mov     edi, [flags]
  77.   .receive_loop:
  78.         mcall   recv
  79.         DEBUGF  1, "chunk = %u ", eax
  80.         cmp     eax, 0
  81.         jbe     .fail
  82.         add     edx, eax
  83.         sub     esi, eax
  84.         jnz     .receive_loop
  85.  
  86. ; Decrypt data
  87.         mov     ebx, [connection]
  88.         cmp     [ebx+ssh_connection.rx_crypt_proc], 0
  89.         je      .decrypt_complete
  90.         mov     ecx, [ebx+ssh_connection.rx_buffer.packet_length]
  91.         add     ecx, 4                                          ; Packet_length field itself
  92.         sub     ecx, [ebx+ssh_connection.rx_crypt_blocksize]    ; Already decrypted this amount of data
  93.         jz      .decrypt_complete
  94.  
  95.         lea     esi, [ebx+ssh_connection.rx_buffer]
  96.         add     esi, [ebx+ssh_connection.rx_crypt_blocksize]
  97.   .decrypt_loop:
  98.         pusha
  99.         stdcall [ebx+ssh_connection.rx_crypt_proc], [ebx+ssh_connection.rx_crypt_ctx_ptr], esi, esi
  100.         popa
  101.         add     esi, [ebx+ssh_connection.rx_crypt_blocksize]
  102.         sub     ecx, [ebx+ssh_connection.rx_crypt_blocksize]
  103.         jnz     .decrypt_loop
  104.   .decrypt_complete:
  105.  
  106. ; Authenticate message
  107.         cmp     [ebx+ssh_connection.rx_mac_proc], 0
  108.         je      .mac_complete
  109.         lea     esi, [ebx+ssh_connection.rx_seq]
  110.         mov     ecx, [ebx+ssh_connection.rx_buffer.packet_length]
  111.         add     ecx, 8                                          ; packet_length field itself + sequence number
  112.         lea     eax, [ebx+ssh_connection.rx_mac_ctx]
  113.         mov     edx, [ebx+ssh_connection.rx_buffer.packet_length]
  114.         bswap   edx                                             ; convert length to big endian
  115.         mov     [ebx+ssh_connection.rx_buffer.packet_length], edx
  116.         stdcall [ebx+ssh_connection.rx_mac_proc], eax, esi, ecx
  117.         mov     edx, [ebx+ssh_connection.rx_buffer.packet_length]
  118.         bswap   edx                                             ; convert length to little endian
  119.         mov     [ebx+ssh_connection.rx_buffer.packet_length], edx
  120.  
  121.         lea     esi, [ebx+ssh_connection.rx_mac_ctx]
  122.         lea     edi, [ebx+ssh_connection.rx_buffer]
  123.         add     edi, [ebx+ssh_connection.rx_buffer.packet_length]
  124.         add     edi, 4
  125.         mov     ecx, [ebx+ssh_connection.rx_mac_length]
  126.         shr     ecx, 2
  127.         repe cmpsd
  128.         jne     .mac_failed
  129.   .mac_complete:
  130.         inc     byte[ebx+ssh_connection.rx_seq+3]               ; Update sequence counter
  131.         jnc     @f
  132.         inc     byte[ebx+ssh_connection.rx_seq+2]
  133.         jnc     @f
  134.         inc     byte[ebx+ssh_connection.rx_seq+1]
  135.         jnc     @f
  136.         inc     byte[ebx+ssh_connection.rx_seq+0]
  137.   @@:
  138.  
  139. ; Return useful data length to the caller via eax register
  140.   .got_all_data:
  141.         mov     eax, [ebx+ssh_connection.rx_buffer.packet_length]
  142.         movzx   ebx, [ebx+ssh_connection.rx_buffer.padding_length]
  143.         sub     eax, ebx
  144.         DEBUGF  1, "useful data length=%u\n", eax
  145.         ret
  146.  
  147.   .fail:
  148.         DEBUGF  3, "ssh_recv_packet failed!\n"
  149.         mov     eax, -1
  150.         mov     ebx, [socket_error]
  151.         ret
  152.  
  153.   .mac_failed:
  154.         DEBUGF  3, "ssh_recv_packet MAC failed!\n"
  155.         mov     eax, -2
  156.         mov     ebx, [socket_error]
  157.         ret
  158.  
  159. endp
  160.  
  161.  
  162. proc ssh_send_packet connection, buf, payload_size, flags
  163.  
  164. locals
  165.         packet_size    dd ?
  166. endl
  167.         DEBUGF  2, "< "
  168.  
  169. ; Pad the packet with random data
  170.         mov     eax, [payload_size]
  171.         inc     eax                     ; padding length byte
  172.         lea     edx, [eax+4]            ; total packet size (without padding and MAC)
  173.         mov     [packet_size], edx
  174.         mov     ecx, [connection]
  175.         mov     ebx, [ecx+ssh_connection.tx_padsize]
  176.         dec     ebx
  177.         and     edx, ebx
  178.         neg     edx
  179.         add     edx, [ecx+ssh_connection.tx_padsize]
  180.         cmp     edx, 4                  ; minimum padding size
  181.         jae     @f
  182.         add     edx, [ecx+ssh_connection.tx_padsize]
  183.   @@:
  184.         DEBUGF  1, "padding %u bytes ", edx
  185.         add     [packet_size], edx
  186.  
  187.         add     eax, edx
  188.         DEBUGF  1, "total size: %u ", eax
  189.         bswap   eax
  190.         lea     edi, [ecx+ssh_connection.tx_buffer]
  191.         stosd                           ; packet_length
  192.         mov     al, dl
  193.         stosb                           ; padding_length
  194.         mov     esi, [buf]
  195.         mov     ecx, [payload_size]
  196.         rep movsb
  197.  
  198.         mov     ebx, edx
  199.         mov     esi, edx
  200.         and     ebx, 3
  201.         jz      @f
  202.         call    MBRandom
  203.         mov     dword[edi], eax
  204.         add     edi, ebx
  205.   @@:
  206.  
  207.         shr     esi, 2
  208.   @@:
  209.         call    MBRandom
  210.         stosd
  211.         dec     esi
  212.         jnz     @r
  213.  
  214. ; Message authentication
  215.         mov     edx, [connection]
  216.         cmp     [edx+ssh_connection.tx_mac_proc], 0
  217.         je      .mac_complete
  218. ;        DEBUGF  1, "MAC sequence number: 0x%x\n", [edx+ssh_connection.tx_seq]
  219.         lea     esi, [edx+ssh_connection.tx_seq]
  220.         mov     ecx, [packet_size]
  221.         add     ecx, 4                                          ; Sequence number length
  222.         lea     eax, [edx+ssh_connection.tx_mac_ctx]
  223.         stdcall [edx+ssh_connection.tx_mac_proc], eax, esi, ecx
  224.  
  225.         lea     esi, [edx+ssh_connection.tx_mac_ctx]
  226.         lea     edi, [edx+ssh_connection.tx_buffer]
  227.         add     edi, [packet_size]
  228.         mov     ecx, [edx+ssh_connection.tx_mac_length]
  229.         shr     ecx, 2
  230.         rep movsd
  231.   .mac_complete:
  232.         inc     byte[edx+ssh_connection.tx_seq+3]               ; Update sequence counter
  233.         jnc     @f
  234.         inc     byte[edx+ssh_connection.tx_seq+2]
  235.         jnc     @f
  236.         inc     byte[edx+ssh_connection.tx_seq+1]
  237.         jnc     @f
  238.         inc     byte[edx+ssh_connection.tx_seq+0]
  239.   @@:
  240.  
  241. ; Encrypt data
  242.         cmp     [edx+ssh_connection.tx_crypt_proc], 0
  243.         je      .encrypt_complete
  244.         lea     esi, [edx+ssh_connection.tx_buffer]
  245.         mov     ecx, [packet_size]
  246.   .encrypt_loop:
  247.         pusha
  248.         stdcall [edx+ssh_connection.tx_crypt_proc], [edx+ssh_connection.tx_crypt_ctx_ptr], esi, esi
  249.         popa
  250.         add     esi, [edx+ssh_connection.tx_crypt_blocksize]
  251.         sub     ecx, [edx+ssh_connection.tx_crypt_blocksize]
  252.         jnz     .encrypt_loop
  253.   .encrypt_complete:
  254.  
  255. ; Send the packet
  256.         mov     ebx, [connection]
  257.         mov     ecx, [ebx+ssh_connection.socketnum]
  258.         lea     edx, [ebx+ssh_connection.tx_buffer]
  259.         mov     esi, [packet_size]
  260.         add     esi, [ebx+ssh_connection.tx_mac_length]
  261.         mov     edi, [flags]
  262.         mcall   send
  263.  
  264.         DEBUGF  1, "\n"
  265.  
  266.         ret
  267.  
  268. endp
  269.  
  270.