Subversion Repositories Kolibri OS

Rev

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