Subversion Repositories Kolibri OS

Rev

Rev 9106 | 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 SHA2_256_LEN+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*SHA2_256_LEN + 2*LIBCRASH_CTX_LEN
  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, LIBCRASH_CTX_LEN
  81.         mov     [temp_ctx], eax
  82.         add     eax, LIBCRASH_CTX_LEN
  83.  
  84.         mov     [H], eax
  85.         add     eax, SHA2_256_LEN
  86.         mov     [rx_iv], eax
  87.         add     eax, SHA2_256_LEN
  88.         mov     [tx_iv], eax
  89.         add     eax, SHA2_256_LEN
  90.         mov     [rx_enc_key], eax
  91.         add     eax, SHA2_256_LEN
  92.         mov     [tx_enc_key], eax
  93.         add     eax, SHA2_256_LEN
  94.         mov     [rx_int_key], eax
  95.         add     eax, SHA2_256_LEN
  96.         mov     [tx_int_key], eax
  97. ;        add     eax, SHA2_256_LEN
  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, LIBCRASH_CTX_LEN/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  sha2_256_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  sha2_256_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  sha2_256_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  sha2_256_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  sha2_256_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  sha2_256_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  sha2_256_update, [temp_ctx], [mpint_K_big], eax
  264.  
  265. ;-------------------------------
  266. ; Finalize the exchange hash (H)
  267.         invoke  sha2_256_finish, [temp_ctx]
  268.         mov     esi, [temp_ctx]
  269.         mov     edi, [H]
  270.         mov     ecx, SHA2_256_LEN/4
  271.         rep movsd
  272.  
  273.         DEBUGF  1, "Exchange hash H: "
  274.         stdcall dump_hex, [H], SHA2_256_LEN/4
  275.  
  276. ;--------------------------
  277. ; Set or get the session id
  278.  
  279.         mov     eax, [con_ptr]
  280.         cmp     [eax + sshlib_connection.status], SSHLIB_CON_STAT_KEX_DONE
  281.         jae     @f
  282.  
  283. ; If first KEX, verify host public key
  284.         stdcall sshlib_host_verify, [con_ptr], [str_K_S], [str_s_of_H], [H], SHA2_256_LEN
  285.         test    eax, eax
  286.         jnz     .err
  287.  
  288.         mov     eax, [con_ptr]
  289.         mov     esi, [H]
  290.         lea     edi, [eax + sshlib_connection.session_id]
  291.         mov     ecx, SHA2_256_LEN/4
  292.         rep movsd
  293.   @@:
  294.  
  295.         lea     esi, [eax + sshlib_connection.session_id]
  296.         lea     edi, [session_id_x+1]
  297.         mov     ecx, SHA2_256_LEN/4
  298.         rep movsd
  299.  
  300.  
  301. ;---------------
  302. ; Calculate keys
  303.  
  304. ; First, calculate partial hash of K and H so we can re-use it for every key.
  305.  
  306.         invoke  sha2_256_init, [k_h_ctx]
  307.  
  308.         mov     ecx, [K_length]
  309.         add     ecx, 4
  310.         invoke  sha2_256_update, [k_h_ctx], [mpint_K_big], ecx
  311.         invoke  sha2_256_update, [k_h_ctx], [H], SHA2_256_LEN
  312.  
  313. ;---------------------------------------------------------------
  314. ; Initial IV client to server: HASH(K || H || "A" || session_id)
  315.  
  316.         mov     esi, [k_h_ctx]
  317.         mov     edi, [temp_ctx]
  318.         mov     ecx, LIBCRASH_CTX_LEN/4
  319.         rep movsd
  320.         lea     edx, [session_id_x]
  321.         mov     byte[edx], 'A'
  322.         invoke  sha2_256_update, [temp_ctx], edx, SHA2_256_LEN+1
  323.         invoke  sha2_256_finish, [temp_ctx]
  324.         mov     edi, [tx_iv]
  325.         mov     esi, [temp_ctx]
  326.         mov     ecx, SHA2_256_LEN/4
  327.         rep movsd
  328.  
  329.         DEBUGF  1, "Remote IV: "
  330.         stdcall dump_hex, [tx_iv], SHA2_256_LEN/4
  331.  
  332. ;---------------------------------------------------------------
  333. ; Initial IV server to client: HASH(K || H || "B" || session_id)
  334.  
  335.         mov     esi, [k_h_ctx]
  336.         mov     edi, [temp_ctx]
  337.         mov     ecx, LIBCRASH_CTX_LEN/4
  338.         rep movsd
  339.         lea     edx, [session_id_x]
  340.         mov     byte[edx], 'B'
  341.         invoke  sha2_256_update, [temp_ctx], edx, SHA2_256_LEN+1
  342.         invoke  sha2_256_finish, [temp_ctx]
  343.         mov     edi, [rx_iv]
  344.         mov     esi, [temp_ctx]
  345.         mov     ecx, SHA2_256_LEN/4
  346.         rep movsd
  347.  
  348.         DEBUGF  1, "Local IV: "
  349.         stdcall dump_hex, [rx_iv], SHA2_256_LEN/4
  350.  
  351. ;-------------------------------------------------------------------
  352. ; Encryption key client to server: HASH(K || H || "C" || session_id)
  353.  
  354.         mov     esi, [k_h_ctx]
  355.         mov     edi, [temp_ctx]
  356.         mov     ecx, LIBCRASH_CTX_LEN/4
  357.         rep movsd
  358.         lea     edx, [session_id_x]
  359.         mov     byte[edx], 'C'
  360.         invoke  sha2_256_update, [temp_ctx], edx, SHA2_256_LEN+1
  361.         invoke  sha2_256_finish, [temp_ctx]
  362.         mov     edi, [tx_enc_key]
  363.         mov     esi, [temp_ctx]
  364.         mov     ecx, SHA2_256_LEN/4
  365.         rep movsd
  366.  
  367.         DEBUGF  1, "Remote key: "
  368.         stdcall dump_hex, [tx_enc_key], SHA2_256_LEN/4
  369.  
  370. ;-------------------------------------------------------------------
  371. ; Encryption key server to client: HASH(K || H || "D" || session_id)
  372.  
  373.         mov     esi, [k_h_ctx]
  374.         mov     edi, [temp_ctx]
  375.         mov     ecx, LIBCRASH_CTX_LEN/4
  376.         rep movsd
  377.         lea     edx, [session_id_x]
  378.         mov     byte[edx], 'D'
  379.         invoke  sha2_256_update, [temp_ctx], edx, SHA2_256_LEN+1
  380.         invoke  sha2_256_finish, [temp_ctx]
  381.         mov     edi, [rx_enc_key]
  382.         mov     esi, [temp_ctx]
  383.         mov     ecx, SHA2_256_LEN/4
  384.         rep movsd
  385.  
  386.         DEBUGF  1, "Local key: "
  387.         stdcall dump_hex, [rx_enc_key], SHA2_256_LEN/4
  388.  
  389. ;------------------------------------------------------------------
  390. ; Integrity key client to server: HASH(K || H || "E" || session_id)
  391.  
  392.         mov     esi, [k_h_ctx]
  393.         mov     edi, [temp_ctx]
  394.         mov     ecx, LIBCRASH_CTX_LEN/4
  395.         rep movsd
  396.         lea     edx, [session_id_x]
  397.         mov     byte[edx], 'E'
  398.         invoke  sha2_256_update, [temp_ctx], edx, SHA2_256_LEN+1
  399.         invoke  sha2_256_finish, [temp_ctx]
  400.         mov     edi, [tx_int_key]
  401.         mov     esi, [temp_ctx]
  402.         mov     ecx, SHA2_256_LEN/4
  403.         rep movsd
  404.  
  405.         DEBUGF  1, "Remote Integrity key: "
  406.         stdcall dump_hex, [tx_int_key], SHA2_256_LEN/4
  407.  
  408. ;------------------------------------------------------------------
  409. ; Integrity key server to client: HASH(K || H || "F" || session_id)
  410.  
  411.         mov     esi, [k_h_ctx]
  412.         mov     edi, [temp_ctx]
  413.         mov     ecx, LIBCRASH_CTX_LEN/4
  414.         rep movsd
  415.         lea     edx, [session_id_x]
  416.         mov     byte[edx], 'F'
  417.         invoke  sha2_256_update, [temp_ctx], edx, SHA2_256_LEN+1
  418.         invoke  sha2_256_finish, [temp_ctx]
  419.         mov     edi, [rx_int_key]
  420.         mov     esi, [temp_ctx]
  421.         mov     ecx, SHA2_256_LEN/4
  422.         rep movsd
  423.  
  424.         DEBUGF  1, "Local Integrity key: "
  425.         stdcall dump_hex, [rx_int_key] , SHA2_256_LEN/4
  426.  
  427. ;-------------------------------------
  428. ; << Parse Diffie-Hellman New Keys MSG
  429.  
  430.         stdcall sshlib_recv_packet, [con_ptr], 0
  431.         cmp     eax, 0
  432.         jl      .err
  433.  
  434.         mov     ebx, [con_ptr]
  435.         cmp     [ebx + sshlib_connection.rx_buffer.message_code], SSH_MSG_NEWKEYS
  436.         jne     .err_proto
  437.  
  438.         DEBUGF  2, "Received New Keys\n"
  439.  
  440. ;-------------------------------
  441. ; >> Reply with New Keys message
  442.  
  443.         stdcall sshlib_send_packet, [con_ptr], ssh_msg_new_keys, ssh_msg_new_keys.length, 0
  444.         cmp     eax, 0
  445.         jl      .err
  446.  
  447. ;----------------------------------------------
  448. ; Set keys and initialize transport subroutines
  449.  
  450.         DEBUGF  2, "SSH: Setting encryption keys\n"
  451.  
  452.         mov     ebx, [con_ptr]
  453.         stdcall aes256_ctr_init, [rx_iv]
  454.         test    eax, eax
  455.         jz      .err_nomem
  456.         mov     [ebx + sshlib_connection.rx_crypt_ctx_ptr], eax
  457.         stdcall aes256_set_encrypt_key, eax, [rx_enc_key]
  458.         mov     [ebx + sshlib_connection.rx_crypt_proc], aes256_ctr_crypt
  459.         mov     [ebx + sshlib_connection.rx_crypt_blocksize], AES256_BLOCKSIZE
  460.  
  461.         stdcall aes256_ctr_init, [tx_iv]
  462.         test    eax, eax
  463.         jz      .err_nomem
  464.         mov     [ebx + sshlib_connection.tx_crypt_ctx_ptr], eax
  465.         stdcall aes256_set_encrypt_key, eax, [tx_enc_key]
  466.         mov     [ebx + sshlib_connection.tx_crypt_proc], aes256_ctr_crypt
  467.         mov     [ebx + sshlib_connection.tx_crypt_blocksize], AES256_BLOCKSIZE
  468.  
  469.         mov     [ebx + sshlib_connection.tx_pad_size], AES256_BLOCKSIZE
  470.         mov     [ebx + sshlib_connection.tx_pad_proc], MBRandom
  471.  
  472.         lea     ecx, [ebx + sshlib_connection.rx_mac_ctx]
  473.         stdcall hmac_sha256_setkey, ecx, [rx_int_key], SHA2_256_LEN
  474.         mov     [ebx + sshlib_connection.rx_mac_proc], hmac_sha256
  475.         mov     [ebx + sshlib_connection.rx_mac_length], SHA2_256_LEN
  476.  
  477.         lea     ecx, [ebx + sshlib_connection.tx_mac_ctx]
  478.         stdcall hmac_sha256_setkey, ecx, [tx_int_key], SHA2_256_LEN
  479.         mov     [ebx + sshlib_connection.tx_mac_proc], hmac_sha256
  480.         mov     [ebx + sshlib_connection.tx_mac_length], SHA2_256_LEN
  481.  
  482.         mov     [ebx + sshlib_connection.status], SSHLIB_CON_STAT_KEX_DONE
  483.         xor     eax, eax
  484.  
  485.   .err:
  486.         push    eax
  487.         xor     eax, eax
  488.         mov     ecx, (7*(MAX_BITS/8+4) + 7*SHA2_256_LEN + 2*LIBCRASH_CTX_LEN)/4
  489.         mov     edi, [mpint_tmp]
  490.         rep stosd
  491.  
  492.         mcall   68, 13, [mpint_tmp]
  493.         pop     eax
  494.         ret
  495.  
  496.   .err_nomem:
  497.         DEBUGF  3, "Out of memory during key exchange!\n"
  498.         mov     eax, SSHLIB_ERR_NOMEM
  499.         ret
  500.  
  501.   .err_proto:
  502.         DEBUGF  3, "Protocol error during key exchange!\n"
  503.         mov     eax, SSHLIB_ERR_PROTOCOL
  504.         jmp     .err
  505.  
  506. endp
  507.