Subversion Repositories Kolibri OS

Rev

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

  1. ;    sshlib_dh_gex.inc - Diffie Hellman Group exchange
  2. ;
  3. ;    Copyright (C) 2015-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://www.ietf.org/rfc/rfc4419.txt
  19.  
  20. proc sshlib_dh_gex con_ptr
  21.  
  22. locals
  23.  
  24.         mpint_tmp               dd ?
  25.  
  26.         mpint_p                 dd ?
  27.         mpint_g                 dd ?
  28.         mpint_x                 dd ?
  29.         mpint_e                 dd ?
  30.         mpint_f                 dd ?
  31.         mpint_K_big             dd ?
  32.  
  33.         k_h_ctx                 dd ?
  34.         temp_ctx                dd ?
  35.  
  36.         H                       dd ?    ; exchange hash
  37.  
  38.         rx_iv                   dd ?    ; Rx initialisation vector
  39.         tx_iv                   dd ?    ; Tx initialisation vector
  40.         rx_enc_key              dd ?    ; Rx encryption key
  41.         tx_enc_key              dd ?    ; Tx encryption key
  42.         rx_int_key              dd ?    ; Rx integrity key
  43.         tx_int_key              dd ?    ; Tx integrity key
  44.  
  45.         K_length                dd ?
  46.  
  47.         session_id_x            rb SHA256_HASH_SIZE+1
  48.  
  49.         str_K_S                 dd ?    ; server public host key and certificates (K_S)
  50.         mpint_f_big             dd ?    ; pointer to original
  51.         str_s_of_H              dd ?    ; signature of H
  52.  
  53. endl
  54.  
  55. ; Allocate memory for temp variables
  56.  
  57.         mov     ecx, 7*(MAX_BITS/8+4) + 7*SHA256_HASH_SIZE + 2*sizeof.crash_ctx
  58.         mcall   68, 12
  59.         test    eax, eax
  60.         jz      .err_nomem
  61.  
  62. ; Init pointers for temp variables
  63.  
  64.         mov     [mpint_tmp], eax
  65.         add     eax, (MAX_BITS/8+4)
  66.         mov     [mpint_p], eax
  67.         add     eax, (MAX_BITS/8+4)
  68.         mov     [mpint_g], eax
  69.         add     eax, (MAX_BITS/8+4)
  70.         mov     [mpint_x], eax
  71.         add     eax, (MAX_BITS/8+4)
  72.         mov     [mpint_e], eax
  73.         add     eax, (MAX_BITS/8+4)
  74.         mov     [mpint_f], eax
  75.         add     eax, (MAX_BITS/8+4)
  76.         mov     [mpint_K_big], eax
  77.         add     eax, (MAX_BITS/8+4)
  78.  
  79.         mov     [k_h_ctx], eax
  80.         add     eax, sizeof.crash_ctx
  81.         mov     [temp_ctx], eax
  82.         add     eax, sizeof.crash_ctx
  83.  
  84.         mov     [H], eax
  85.         add     eax, SHA256_HASH_SIZE
  86.         mov     [rx_iv], eax
  87.         add     eax, SHA256_HASH_SIZE
  88.         mov     [tx_iv], eax
  89.         add     eax, SHA256_HASH_SIZE
  90.         mov     [rx_enc_key], eax
  91.         add     eax, SHA256_HASH_SIZE
  92.         mov     [tx_enc_key], eax
  93.         add     eax, SHA256_HASH_SIZE
  94.         mov     [rx_int_key], eax
  95.         add     eax, SHA256_HASH_SIZE
  96.         mov     [tx_int_key], eax
  97. ;        add     eax, SHA256_HASH_SIZE
  98.  
  99. ; Copy the partial exchange hash to our temporary one
  100.  
  101.         mov     esi, [con_ptr]
  102.         lea     esi, [esi+sshlib_connection.part_ex_hash_ctx]
  103.         mov     edi, [temp_ctx]
  104.         mov     ecx, sizeof.crash_ctx/4
  105.         rep movsd
  106.  
  107. ;----------------------------------------------
  108. ; >> Send Diffie-Hellman Group Exchange Request
  109.  
  110.         DEBUGF  2, "Sending GEX\n"
  111.         stdcall sshlib_send_packet, [con_ptr], ssh_msg_gex_req, ssh_msg_gex_req.length, 0
  112.         cmp     eax, 0
  113.         jl      .err
  114.  
  115. ;---------------------------------------------
  116. ; << Parse Diffie-Hellman Group Exchange Group
  117.  
  118.         stdcall sshlib_recv_packet, [con_ptr], 0
  119.         cmp     eax, 0
  120.         jl      .err
  121.  
  122.         mov     ebx, [con_ptr]
  123.         cmp     [ebx + sshlib_connection.rx_buffer.message_code], SSH_MSG_KEX_DH_GEX_GROUP
  124.         jne     .err_proto
  125.         DEBUGF  2, "Received GEX group\n"
  126.  
  127.         lea     esi, [ebx + sshlib_connection.rx_buffer + sizeof.ssh_packet_header]
  128.         stdcall mpint_to_little_endian, [mpint_p], esi
  129.         add     esi, 4
  130.         add     esi, eax
  131.         DEBUGM  1, "DH modulus (p): ", [mpint_p]
  132.  
  133.         stdcall mpint_to_little_endian, [mpint_g], esi
  134.         add     esi, 4
  135.         add     esi, eax
  136.         DEBUGM  1, "DH base (g): ", [mpint_g]
  137.  
  138. ;-------------------------------------------
  139. ; >> Send Diffie-Hellman Group Exchange Init
  140.  
  141. ; generate a random number x, where 1 < x < (p-1)/2
  142.         mov     edi, [mpint_x]
  143.         mov     dword[edi], DH_PRIVATE_KEY_SIZE/8
  144.         add     edi, 4
  145.         mov     ecx, DH_PRIVATE_KEY_SIZE/8/4
  146.   @@:
  147.         push    ecx
  148.         call    MBRandom
  149.         pop     ecx
  150.         stosd
  151.         dec     ecx
  152.         jnz     @r
  153.  
  154. ; If the highest bit is set, add a zero byte
  155.         shl     eax, 1
  156.         jnc     @f
  157.         mov     byte[edi], 0
  158.         mov     eax, [mpint_x]
  159.         inc     dword[eax]
  160.   @@:
  161.         DEBUGM  1, "DH private key (x): ", [mpint_x]
  162.  
  163. ; Compute e = g^x mod p
  164.         stdcall mpint_modexp, [mpint_e], [mpint_g], [mpint_x], [mpint_p]
  165.         stdcall mpint_shrink, [mpint_e]
  166.         DEBUGM  1, "DH public key (e): ", [mpint_e]
  167.  
  168. ; Create group exchange init packet
  169.         mov     byte[ebx + sshlib_connection.tx_buffer.message_code], SSH_MSG_KEX_DH_GEX_INIT
  170.         lea     edi, [ebx + sshlib_connection.tx_buffer.message_code+1]
  171.         stdcall mpint_to_big_endian, edi, [mpint_e]
  172.  
  173.         DEBUGF  2, "Sending GEX init\n"
  174.         mov     ecx, dword[ebx + sshlib_connection.tx_buffer.message_code+1]         ;;;; dword[edi]
  175.         bswap   ecx
  176.         add     ecx, 5
  177.         lea     esi, [ebx + sshlib_connection.tx_buffer.message_code]
  178.         stdcall sshlib_send_packet, [con_ptr], esi, ecx, 0
  179.         cmp     eax, 0
  180.         jl      .err
  181.  
  182. ;---------------------------------------------
  183. ; << Parse Diffie-Hellman Group Exchange Reply
  184.  
  185.         stdcall sshlib_recv_packet, [con_ptr], 0
  186.         cmp     eax, 0
  187.         jl      .err
  188.  
  189.         mov     ebx, [con_ptr]
  190.         cmp     [ebx + sshlib_connection.rx_buffer.message_code], SSH_MSG_KEX_DH_GEX_REPLY
  191.         jne     .err_proto
  192.  
  193.         DEBUGF  2, "Received GEX Reply\n"
  194.  
  195. ;--------------------------------
  196. ; HASH: string K_S, the host key
  197.         lea     esi, [ebx + sshlib_connection.rx_buffer + sizeof.ssh_packet_header]
  198.         mov     [str_K_S], esi
  199.         mov     edx, [esi]
  200.         bswap   edx
  201.         add     edx, 4
  202.         lea     eax, [esi+edx]
  203.         mov     [mpint_f_big], eax
  204.         invoke  sha256_update, [temp_ctx], esi, edx
  205.  
  206. ;--------------------------------------------------------------------------
  207. ; HASH: uint32 min, minimal size in bits of an acceptable group
  208. ;       uint32 n, preferred size in bits of the group the server will send
  209. ;       uint32 max, maximal size in bits of an acceptable group
  210.         invoke  sha256_update, [temp_ctx], ssh_msg_gex_req+sizeof.ssh_packet_header-ssh_packet_header.message_code, 12
  211.  
  212. ;----------------------------
  213. ; HASH: mpint p, safe prime
  214.         stdcall mpint_shrink, [mpint_p]
  215.         stdcall mpint_to_big_endian, [mpint_tmp], [mpint_p]
  216.         add     eax, 4
  217.         invoke  sha256_update, [temp_ctx], [mpint_tmp], eax
  218.  
  219. ;----------------------------------------
  220. ; HASH: mpint g, generator for subgroup
  221.         stdcall mpint_shrink, [mpint_g]
  222.         stdcall mpint_to_big_endian, [mpint_tmp], [mpint_g]
  223.         add     eax, 4
  224.         invoke  sha256_update, [temp_ctx], [mpint_tmp], eax
  225.  
  226. ;---------------------------------------------------
  227. ; HASH: mpint e, exchange value sent by the client
  228.         mov     ebx, [con_ptr]
  229.         lea     esi, [ebx + sshlib_connection.tx_buffer + sizeof.ssh_packet_header]
  230.         mov     edx, [esi]
  231.         bswap   edx
  232.         add     edx, 4
  233.         invoke  sha256_update, [temp_ctx], esi, edx
  234.  
  235. ;---------------------------------------------------
  236. ; HASH: mpint f, exchange value sent by the server
  237.         mov     esi, [mpint_f_big]
  238.         mov     edx, [esi]
  239.         bswap   edx
  240.         add     edx, 4
  241.         invoke  sha256_update, [temp_ctx], esi, edx
  242.  
  243.         stdcall mpint_to_little_endian, [mpint_f], [mpint_f_big]
  244.         mov     esi, [mpint_f_big]
  245.         add     esi, eax
  246.         add     esi, 4
  247.         mov     [str_s_of_H], esi
  248.         DEBUGM  1, "DH exchange value (f): ", [mpint_f]
  249.  
  250. ;--------------------------------------
  251. ; Calculate shared secret K = f^x mod p
  252.         stdcall mpint_modexp, [mpint_tmp], [mpint_f], [mpint_x], [mpint_p]
  253.         stdcall mpint_shrink, [mpint_tmp]
  254.         DEBUGM  1, "DH shared secret (K): ", [mpint_tmp]
  255.  
  256. ; We always need it in big endian order, so store it as such.
  257.         stdcall mpint_to_big_endian, [mpint_K_big], [mpint_tmp]
  258.         mov     [K_length], eax
  259.  
  260. ;-----------------------------------
  261. ; HASH: mpint K, the shared secret
  262.         add     eax, 4
  263.         invoke  sha256_update, [temp_ctx], [mpint_K_big], eax
  264.  
  265. ;-------------------------------
  266. ; Finalize the exchange hash (H)
  267.         invoke  sha256_final, [temp_ctx]
  268.         mov     esi, [temp_ctx]
  269.         add     esi, crash_ctx.hash
  270.         mov     edi, [H]
  271.         mov     ecx, SHA256_HASH_SIZE/4
  272.         rep movsd
  273.  
  274.         DEBUGF  1, "Exchange hash H: "
  275.         stdcall dump_hex, [H], SHA256_HASH_SIZE/4
  276.  
  277. ;--------------------------
  278. ; Set or get the session id
  279.  
  280.         mov     eax, [con_ptr]
  281.         cmp     [eax + sshlib_connection.status], SSHLIB_CON_STAT_KEX_DONE
  282.         jae     @f
  283.  
  284. ; If first KEX, verify host public key
  285.         stdcall sshlib_host_verify, [con_ptr], [str_K_S], [str_s_of_H], [H], SHA256_HASH_SIZE
  286.         test    eax, eax
  287.         jnz     .err
  288.  
  289.         mov     eax, [con_ptr]
  290.         mov     esi, [H]
  291.         lea     edi, [eax + sshlib_connection.session_id]
  292.         mov     ecx, SHA256_HASH_SIZE/4
  293.         rep movsd
  294.   @@:
  295.  
  296.         lea     esi, [eax + sshlib_connection.session_id]
  297.         lea     edi, [session_id_x+1]
  298.         mov     ecx, SHA256_HASH_SIZE/4
  299.         rep movsd
  300.  
  301.  
  302. ;---------------
  303. ; Calculate keys
  304.  
  305. ; First, calculate partial hash of K and H so we can re-use it for every key.
  306.  
  307.         invoke  sha256_init, [k_h_ctx]
  308.  
  309.         mov     ecx, [K_length]
  310.         add     ecx, 4
  311.         invoke  sha256_update, [k_h_ctx], [mpint_K_big], ecx
  312.         invoke  sha256_update, [k_h_ctx], [H], SHA256_HASH_SIZE
  313.  
  314. ;---------------------------------------------------------------
  315. ; Initial IV client to server: HASH(K || H || "A" || session_id)
  316.  
  317.         mov     esi, [k_h_ctx]
  318.         mov     edi, [temp_ctx]
  319.         mov     ecx, sizeof.crash_ctx/4
  320.         rep movsd
  321.         lea     edx, [session_id_x]
  322.         mov     byte[edx], 'A'
  323.         invoke  sha256_update, [temp_ctx], edx, SHA256_HASH_SIZE+1
  324.         invoke  sha256_final, [temp_ctx]
  325.         mov     edi, [tx_iv]
  326.         mov     esi, [temp_ctx]
  327.         mov     ecx, SHA256_HASH_SIZE/4
  328.         rep movsd
  329.  
  330.         DEBUGF  1, "Remote IV: "
  331.         stdcall dump_hex, [tx_iv], SHA256_HASH_SIZE/4
  332.  
  333. ;---------------------------------------------------------------
  334. ; Initial IV server to client: HASH(K || H || "B" || session_id)
  335.  
  336.         mov     esi, [k_h_ctx]
  337.         mov     edi, [temp_ctx]
  338.         mov     ecx, sizeof.crash_ctx/4
  339.         rep movsd
  340.         lea     edx, [session_id_x]
  341.         mov     byte[edx], 'B'
  342.         invoke  sha256_update, [temp_ctx], edx, SHA256_HASH_SIZE+1
  343.         invoke  sha256_final, [temp_ctx]
  344.         mov     edi, [rx_iv]
  345.         mov     esi, [temp_ctx]
  346.         mov     ecx, SHA256_HASH_SIZE/4
  347.         rep movsd
  348.  
  349.         DEBUGF  1, "Local IV: "
  350.         stdcall dump_hex, [rx_iv], SHA256_HASH_SIZE/4
  351.  
  352. ;-------------------------------------------------------------------
  353. ; Encryption key client to server: HASH(K || H || "C" || session_id)
  354.  
  355.         mov     esi, [k_h_ctx]
  356.         mov     edi, [temp_ctx]
  357.         mov     ecx, sizeof.crash_ctx/4
  358.         rep movsd
  359.         lea     edx, [session_id_x]
  360.         mov     byte[edx], 'C'
  361.         invoke  sha256_update, [temp_ctx], edx, SHA256_HASH_SIZE+1
  362.         invoke  sha256_final, [temp_ctx]
  363.         mov     edi, [tx_enc_key]
  364.         mov     esi, [temp_ctx]
  365.         mov     ecx, SHA256_HASH_SIZE/4
  366.         rep movsd
  367.  
  368.         DEBUGF  1, "Remote key: "
  369.         stdcall dump_hex, [tx_enc_key], SHA256_HASH_SIZE/4
  370.  
  371. ;-------------------------------------------------------------------
  372. ; Encryption key server to client: HASH(K || H || "D" || session_id)
  373.  
  374.         mov     esi, [k_h_ctx]
  375.         mov     edi, [temp_ctx]
  376.         mov     ecx, sizeof.crash_ctx/4
  377.         rep movsd
  378.         lea     edx, [session_id_x]
  379.         mov     byte[edx], 'D'
  380.         invoke  sha256_update, [temp_ctx], edx, SHA256_HASH_SIZE+1
  381.         invoke  sha256_final, [temp_ctx]
  382.         mov     edi, [rx_enc_key]
  383.         mov     esi, [temp_ctx]
  384.         mov     ecx, SHA256_HASH_SIZE/4
  385.         rep movsd
  386.  
  387.         DEBUGF  1, "Local key: "
  388.         stdcall dump_hex, [rx_enc_key], SHA256_HASH_SIZE/4
  389.  
  390. ;------------------------------------------------------------------
  391. ; Integrity key client to server: HASH(K || H || "E" || session_id)
  392.  
  393.         mov     esi, [k_h_ctx]
  394.         mov     edi, [temp_ctx]
  395.         mov     ecx, sizeof.crash_ctx/4
  396.         rep movsd
  397.         lea     edx, [session_id_x]
  398.         mov     byte[edx], 'E'
  399.         invoke  sha256_update, [temp_ctx], edx, SHA256_HASH_SIZE+1
  400.         invoke  sha256_final, [temp_ctx]
  401.         mov     edi, [tx_int_key]
  402.         mov     esi, [temp_ctx]
  403.         mov     ecx, SHA256_HASH_SIZE/4
  404.         rep movsd
  405.  
  406.         DEBUGF  1, "Remote Integrity key: "
  407.         stdcall dump_hex, [tx_int_key], SHA256_HASH_SIZE/4
  408.  
  409. ;------------------------------------------------------------------
  410. ; Integrity key server to client: HASH(K || H || "F" || session_id)
  411.  
  412.         mov     esi, [k_h_ctx]
  413.         mov     edi, [temp_ctx]
  414.         mov     ecx, sizeof.crash_ctx/4
  415.         rep movsd
  416.         lea     edx, [session_id_x]
  417.         mov     byte[edx], 'F'
  418.         invoke  sha256_update, [temp_ctx], edx, SHA256_HASH_SIZE+1
  419.         invoke  sha256_final, [temp_ctx]
  420.         mov     edi, [rx_int_key]
  421.         mov     esi, [temp_ctx]
  422.         mov     ecx, SHA256_HASH_SIZE/4
  423.         rep movsd
  424.  
  425.         DEBUGF  1, "Local Integrity key: "
  426.         stdcall dump_hex, [rx_int_key] , SHA256_HASH_SIZE/4
  427.  
  428. ;-------------------------------------
  429. ; << Parse Diffie-Hellman New Keys MSG
  430.  
  431.         stdcall sshlib_recv_packet, [con_ptr], 0
  432.         cmp     eax, 0
  433.         jl      .err
  434.  
  435.         mov     ebx, [con_ptr]
  436.         cmp     [ebx + sshlib_connection.rx_buffer.message_code], SSH_MSG_NEWKEYS
  437.         jne     .err_proto
  438.  
  439.         DEBUGF  2, "Received New Keys\n"
  440.  
  441. ;-------------------------------
  442. ; >> Reply with New Keys message
  443.  
  444.         stdcall sshlib_send_packet, [con_ptr], ssh_msg_new_keys, ssh_msg_new_keys.length, 0
  445.         cmp     eax, 0
  446.         jl      .err
  447.  
  448. ;----------------------------------------------
  449. ; Set keys and initialize transport subroutines
  450.  
  451.         DEBUGF  2, "SSH: Setting encryption keys\n"
  452.  
  453.         mov     ebx, [con_ptr]
  454.         stdcall aes256_ctr_init, [rx_iv]
  455.         test    eax, eax
  456.         jz      .err_nomem
  457.         mov     [ebx + sshlib_connection.rx_crypt_ctx_ptr], eax
  458.         stdcall aes256_set_encrypt_key, eax, [rx_enc_key]
  459.         mov     [ebx + sshlib_connection.rx_crypt_proc], aes256_ctr_crypt
  460.         mov     [ebx + sshlib_connection.rx_crypt_blocksize], AES256_BLOCKSIZE
  461.  
  462.         stdcall aes256_ctr_init, [tx_iv]
  463.         test    eax, eax
  464.         jz      .err_nomem
  465.         mov     [ebx + sshlib_connection.tx_crypt_ctx_ptr], eax
  466.         stdcall aes256_set_encrypt_key, eax, [tx_enc_key]
  467.         mov     [ebx + sshlib_connection.tx_crypt_proc], aes256_ctr_crypt
  468.         mov     [ebx + sshlib_connection.tx_crypt_blocksize], AES256_BLOCKSIZE
  469.  
  470.         mov     [ebx + sshlib_connection.tx_pad_size], AES256_BLOCKSIZE
  471.         mov     [ebx + sshlib_connection.tx_pad_proc], MBRandom
  472.  
  473.         lea     ecx, [ebx + sshlib_connection.rx_mac_ctx]
  474.         stdcall hmac_sha256_setkey, ecx, [rx_int_key], SHA256_HASH_SIZE
  475.         mov     [ebx + sshlib_connection.rx_mac_proc], hmac_sha256
  476.         mov     [ebx + sshlib_connection.rx_mac_length], SHA256_HASH_SIZE
  477.  
  478.         lea     ecx, [ebx + sshlib_connection.tx_mac_ctx]
  479.         stdcall hmac_sha256_setkey, ecx, [tx_int_key], SHA256_HASH_SIZE
  480.         mov     [ebx + sshlib_connection.tx_mac_proc], hmac_sha256
  481.         mov     [ebx + sshlib_connection.tx_mac_length], SHA256_HASH_SIZE
  482.  
  483.         mov     [ebx + sshlib_connection.status], SSHLIB_CON_STAT_KEX_DONE
  484.         xor     eax, eax
  485.  
  486.   .err:
  487.         push    eax
  488.         xor     eax, eax
  489.         mov     ecx, (7*(MAX_BITS/8+4) + 7*SHA256_HASH_SIZE + 2*sizeof.crash_ctx)/4
  490.         mov     edi, [mpint_tmp]
  491.         rep stosd
  492.  
  493.         mcall   68, 13, [mpint_tmp]
  494.         pop     eax
  495.         ret
  496.  
  497.   .err_nomem:
  498.         DEBUGF  3, "Out of memory during key exchange!\n"
  499.         mov     eax, SSHLIB_ERR_NOMEM
  500.         ret
  501.  
  502.   .err_proto:
  503.         DEBUGF  3, "Protocol error during key exchange!\n"
  504.         mov     eax, SSHLIB_ERR_PROTOCOL
  505.         jmp     .err
  506.  
  507. endp
  508.