Subversion Repositories Kolibri OS

Rev

Rev 9987 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;    sshlib_transport.inc - SSH transport layer
  2. ;
  3. ;    Copyright (C) 2016-2024 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. iglobal
  19.  
  20. align 16
  21. null_bytes:    times 64 db 0
  22.  
  23. endg
  24.  
  25.  
  26. align 16
  27. proc sshlib_recv_packet_poly1305chacha20 con_ptr, flags
  28.  
  29. locals
  30.         data_length     dd ?    ; Total length of packet without MAC
  31.         mac_otk         rb 64   ;256/8
  32.         iv              rd 4
  33. endl
  34.  
  35.         DEBUGF  3, "> "
  36. ; Receive first block (Read length)
  37.         mov     ebx, [con_ptr]
  38.         mov     ecx, [ebx+sshlib_connection.socketnum]
  39.         mov     esi, 4
  40.         lea     edx, [ebx+sshlib_connection.rx_buffer]
  41.         mov     edi, [flags]
  42.         mcall   recv
  43.         cmp     eax, 0
  44.         jle     .sock_fail
  45.         sub     [ssh_chan.rcv_wnd], eax  ;;; FIXME
  46.         DEBUGF  1, "chunk = %u ", eax
  47.         mov     ebx, [con_ptr]
  48.         cmp     eax, 4
  49.         jne     .proto_fail     ; TODO: handle receives of 1, 2, and 3 bytes correctly
  50.  
  51. ; Decrypt data length
  52.         mov     ebx, [con_ptr]
  53.  
  54.         lea     eax, [iv]
  55.         mov     dword[eax+0], 0
  56.         mov     dword[eax+4], 0
  57.         mov     dword[eax+8], 0
  58.         push    [ebx+sshlib_connection.rx_mac_seqnr]
  59.         pop     dword[eax+12]
  60.  
  61.         lea     ecx, [ebx+sshlib_connection.rx_crypt_ctx]
  62.         lea     edx, [ebx+sshlib_connection.rx_enc_key+256/8]
  63.         lea     esi, [ebx+sshlib_connection.rx_buffer]
  64.         lea     edi, [data_length]
  65.         invoke  chacha20.oneshot, ecx, edx, eax, 0, esi, 4, edi
  66.  
  67.         mov     eax, [data_length]
  68.         bswap   eax
  69.         mov     [data_length], eax
  70.         DEBUGF  2, "decrypted packet length=%u\n", [data_length]
  71.  
  72.         cmp     eax, BUFFERSIZE-4-128/8
  73.         ja      .proto_fail
  74.  
  75. ; Receive remaining data
  76.         lea     edx, [ebx+sshlib_connection.rx_buffer+4]
  77.         mov     ecx, [ebx+sshlib_connection.socketnum]
  78.         mov     edi, [flags]
  79.         lea     esi, [eax + 128/8]                              ; We already got 4 bytes but they are not counted, MAC is also not counted so add that
  80.   .recv_loop:
  81.         DEBUGF  3, "want %u bytes.. ", esi
  82.         mcall   recv
  83.         cmp     eax, 0
  84.         jle     .sock_fail
  85.         sub     [ssh_chan.rcv_wnd], eax             ;;; FIXME
  86.         DEBUGF  3, "got %u bytes\n", eax
  87.         add     edx, eax
  88.         sub     esi, eax
  89.         jnz     .recv_loop
  90.  
  91. ; Calculate the OTK
  92.         mov     ebx, [con_ptr]
  93.         lea     eax, [ebx+sshlib_connection.rx_crypt_ctx]
  94.         lea     esi, [ebx+sshlib_connection.rx_enc_key]
  95.         lea     edx, [mac_otk]
  96.         lea     ecx, [iv]
  97.         invoke  chacha20.oneshot, eax, esi, ecx, 0, null_bytes, 64, edx
  98.  
  99. ; Calculate the MAC
  100.         lea     esi, [ebx+sshlib_connection.rx_mac_ctx]
  101.         lea     edi, [ebx+sshlib_connection.rx_buffer]
  102.         mov     ecx, [data_length]
  103.         add     ecx, 4
  104.         lea     edx, [mac_otk]
  105.         push    ecx
  106.         invoke  poly1305.oneshot, esi, edi, ecx, edx, 256/8
  107.         pop     ecx
  108.  
  109. ; Compare in constant time
  110.         add     edi, ecx
  111.         cmpsd
  112.         lahf
  113.         mov     edx, eax
  114.         cmpsd
  115.         lahf
  116.         and     edx, eax
  117.         cmpsd
  118.         lahf
  119.         and     edx, eax
  120.         cmpsd
  121.         lahf
  122.         and     eax, edx
  123.         sahf
  124.         jne     .mac_fail
  125.  
  126. ; Decrypt the payload
  127.         lea     eax, [ebx+sshlib_connection.rx_crypt_ctx]
  128.         lea     edi, [ebx+sshlib_connection.rx_buffer+4]
  129.         invoke  chacha20.update, eax, edi, [data_length], edi
  130.  
  131. ; Put decrypted length in rx buffer
  132.         push    [data_length]
  133.         pop     dword[ebx+sshlib_connection.rx_buffer]
  134.  
  135. ; Update sequence counter
  136.         add     byte[ebx+sshlib_connection.rx_mac_seqnr+3], 1
  137.         adc     byte[ebx+sshlib_connection.rx_mac_seqnr+2], 0
  138.         adc     byte[ebx+sshlib_connection.rx_mac_seqnr+1], 0
  139.         adc     byte[ebx+sshlib_connection.rx_mac_seqnr+0], 0
  140.  
  141. ; Return useful data length to the caller via eax register
  142. ;;;  .packet_complete:
  143.         mov     eax, [ebx+sshlib_connection.rx_buffer.packet_length]
  144.         movzx   ebx, [ebx+sshlib_connection.rx_buffer.padding_length]
  145.         sub     eax, ebx
  146.         DEBUGF  1, "useful data length=%u\n", eax
  147.         ret
  148.  
  149.   .sock_fail:
  150.         DEBUGF  3, "ssh_recv_packet failed!\n"
  151.         mov     eax, SSHLIB_ERR_SOCKET
  152.         ret
  153.  
  154.   .mac_fail:
  155.         DEBUGF  3, "ssh_recv_packet message authentication failed!\n"
  156.         mov     eax, SSHLIB_ERR_MAC_VERIFY_FAIL
  157.         xor     ebx, ebx
  158.         ret
  159.  
  160.   .proto_fail:
  161.         DEBUGF  3, "ssh_recv_packet protocol failure!\n"
  162.         mov     eax, SSHLIB_ERR_PROTOCOL
  163.         xor     ebx, ebx
  164.         ret
  165.  
  166. endp
  167.  
  168.  
  169. align 16
  170. proc sshlib_send_packet_poly1305chacha20 con_ptr, buf, payload_size, flags
  171.  
  172. locals
  173.         packet_size     dd ?
  174.         mac_otk         rb 64   ;256/8
  175.         iv              rd 4
  176. endl
  177.         DEBUGF  2, "< "
  178.  
  179. ; Check how many bytes we should pad
  180.         mov     eax, [payload_size]
  181.         inc     eax                     ; padding length byte
  182.         lea     edx, [eax+4]            ; total packet size without padding and MAC
  183.         mov     [packet_size], edx
  184.  
  185.         mov     ecx, [con_ptr]
  186.         mov     edx, eax
  187.         mov     ebx, [ecx+sshlib_connection.tx_pad_size]
  188.         dec     ebx
  189.         and     edx, ebx
  190.         neg     edx
  191.         add     edx, [ecx+sshlib_connection.tx_pad_size]
  192.         add     edx, [ecx+sshlib_connection.tx_pad_size]
  193.         DEBUGF  2, "padding %u bytes ", edx
  194.         add     [packet_size], edx      ; total packet size with padding, without MAC
  195.  
  196. ; Start building the packet
  197. ; First comes the packet length, in network byte order ofcourse.
  198.         add     eax, edx
  199.         DEBUGF  2, "total size: %u ", eax
  200.         bswap   eax
  201.         lea     edi, [ecx+sshlib_connection.tx_buffer]
  202.         stosd
  203. ; Then the padding length
  204.         mov     al, dl
  205.         stosb
  206. ;;; And the actual payload bytes
  207.         mov     esi, [buf]
  208.         mov     ecx, [payload_size]
  209.         rep movsb
  210.  
  211. ; Append the packet with #edx padding bytes.
  212. ; Since we must pad at least 8 bytes, we can always use DWORD writes.
  213. ; First do an (unaligned) write exactly following the data
  214.         dec     edx
  215.         mov     esi, edx
  216.         shr     esi, 2          ; number dwords
  217.         mov     ebx, edx
  218.         and     ebx, 3
  219.         inc     ebx             ; number bytes in first write (1-4)
  220.         mov     edx, [con_ptr]
  221.         call    MBRandom
  222.         mov     dword[edi], eax
  223.         add     edi, ebx
  224. ; Then, do as many aligned writes as nescessary
  225.         mov     ebx, [con_ptr]
  226.   @@:
  227.         call    MBRandom
  228.         stosd
  229.         dec     esi
  230.         jnz     @r
  231.  
  232. ; Encrypt data length
  233.         lea     eax, [iv]
  234.         mov     dword[eax+0], 0
  235.         mov     dword[eax+4], 0
  236.         mov     dword[eax+8], 0
  237.         push    [ebx+sshlib_connection.tx_mac_seqnr]
  238.         pop     dword[eax+12]
  239.  
  240.         lea     esi, [ebx+sshlib_connection.tx_crypt_ctx]
  241.         lea     edx, [ebx+sshlib_connection.tx_enc_key+256/8]
  242.         lea     edi, [ebx+sshlib_connection.tx_buffer]
  243.         invoke  chacha20.oneshot, esi, edx, eax, 0, edi, 4, edi
  244.  
  245. ; Calculate the OTK
  246.         lea     eax, [iv]
  247.         lea     edx, [ebx+sshlib_connection.tx_enc_key]
  248.         lea     edi, [mac_otk]
  249.         invoke  chacha20.oneshot, esi, edx, eax, 0, null_bytes, 64, edi
  250.  
  251. ; Encrypt the payload
  252.         lea     edi, [ebx+sshlib_connection.tx_buffer+4]
  253.         mov     eax, [packet_size]
  254.         sub     eax, 4
  255.         invoke  chacha20.update, esi, edi, eax, edi
  256.  
  257. ; Calculate the MAC
  258.         lea     esi, [ebx+sshlib_connection.tx_mac_ctx]
  259.         lea     edi, [ebx+sshlib_connection.tx_buffer]
  260.         lea     edx, [mac_otk]
  261.         invoke  poly1305.oneshot, esi, edi, [packet_size], edx, 256/8
  262.  
  263. ; Write it to the send buffer
  264.         add     edi, [packet_size]
  265.         movsd
  266.         movsd
  267.         movsd
  268.         movsd
  269.  
  270. ; Update sequence counter
  271.         add     byte[ebx+sshlib_connection.tx_mac_seqnr+3], 1
  272.         adc     byte[ebx+sshlib_connection.tx_mac_seqnr+2], 0
  273.         adc     byte[ebx+sshlib_connection.tx_mac_seqnr+1], 0
  274.         adc     byte[ebx+sshlib_connection.tx_mac_seqnr+0], 0
  275.  
  276. ; Send the packet
  277. ;        mov     ebx, [con_ptr]
  278.         mov     ecx, [ebx+sshlib_connection.socketnum]
  279.         lea     edx, [ebx+sshlib_connection.tx_buffer]
  280.         mov     esi, [packet_size]
  281.         add     esi, 16 ;[ebx+sshlib_connection.tx_mac_length]
  282.         mov     edi, [flags]
  283.         mcall   send
  284.  
  285.         DEBUGF  2, "\n"
  286.  
  287.         ret
  288.  
  289. endp
  290.  
  291.