Subversion Repositories Kolibri OS

Rev

Rev 6419 | Blame | Last modification | View Log | Download | RSS feed

  1. ;    dh_gex.inc - Diffie Hellman Group exchange
  2. ;
  3. ;    Copyright (C) 2015-2016 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. ; TODO: dont convert mpints to little endian immediately.
  21. ; Or maybe even better, not at all.
  22.  
  23. proc dh_gex
  24.  
  25. ;----------------------------------------------
  26. ; >> Send Diffie-Hellman Group Exchange Request
  27.  
  28.         DEBUGF  2, "Sending GEX\n"
  29.         stdcall ssh_send_packet, con, ssh_gex_req, ssh_gex_req.length, 0
  30.         cmp     eax, -1
  31.         je      .socket_err
  32.  
  33. ;---------------------------------------------
  34. ; << Parse Diffie-Hellman Group Exchange Group
  35.  
  36.         stdcall ssh_recv_packet, con, 0
  37.         cmp     eax, -1
  38.         je      .socket_err
  39.  
  40.         cmp     [con.rx_buffer.message_code], SSH_MSG_KEX_DH_GEX_GROUP
  41.         jne     proto_err
  42.         DEBUGF  2, "Received GEX group\n"
  43.  
  44.         mov     esi, con.rx_buffer+sizeof.ssh_packet_header
  45.         mov     edi, con.dh_p
  46.         DEBUGF  1, "DH modulus (p): "
  47.         call    mpint_to_little_endian
  48.         stdcall mpint_print, con.dh_p
  49.  
  50.         DEBUGF  1, "DH base (g): "
  51.         mov     edi, con.dh_g
  52.         call    mpint_to_little_endian
  53.         stdcall mpint_print, con.dh_g
  54.  
  55. ;-------------------------------------------
  56. ; >> Send Diffie-Hellman Group Exchange Init
  57.  
  58. ; generate a random number x, where 1 < x < (p-1)/2
  59.         mov     edi, con.dh_x+4
  60.         mov     [con.dh_x], DH_PRIVATE_KEY_SIZE/8
  61.         mov     ecx, DH_PRIVATE_KEY_SIZE/8/4
  62.   @@:
  63.         push    ecx
  64.         call    MBRandom
  65.         pop     ecx
  66.         stosd
  67.         dec     ecx
  68.         jnz     @r
  69.  
  70. ; If the highest bit is set, add a zero byte
  71.         shl     eax, 1
  72.         jnc     @f
  73.         mov     byte[edi], 0
  74.         inc     dword[con.dh_x]
  75.   @@:
  76.  
  77. ; Fill remaining bytes with zeros       ; TO BE REMOVED ?
  78. if ((MAX_BITS-DH_PRIVATE_KEY_SIZE) > 0)
  79.         mov     ecx, (MAX_BITS-DH_PRIVATE_KEY_SIZE)/8/4
  80.         xor     eax, eax
  81.         rep stosd
  82. end if
  83.  
  84.         DEBUGF  1, "DH x: "
  85.         stdcall mpint_length, con.dh_x;;;;;;;;;;;;;
  86.         stdcall mpint_print, con.dh_x
  87.  
  88. ; Compute e = g^x mod p
  89.         stdcall mpint_modexp, con.dh_e, con.dh_g, con.dh_x, con.dh_p
  90.         stdcall mpint_length, con.dh_e
  91.  
  92.         DEBUGF  1, "DH e: "
  93.         stdcall mpint_print, con.dh_e
  94.  
  95. ; Create group exchange init packet
  96.         mov     edi, con.tx_buffer.message_code
  97.         mov     al, SSH_MSG_KEX_DH_GEX_INIT
  98.         stosb
  99.         mov     esi, con.dh_e
  100.         call    mpint_to_big_endian
  101.  
  102.         DEBUGF  2, "Sending GEX init\n"
  103.         mov     ecx, dword[con.tx_buffer.message_code+1]
  104.         bswap   ecx
  105.         add     ecx, 5
  106.         stdcall ssh_send_packet, con, con.tx_buffer.message_code, ecx, 0
  107.         cmp     eax, -1
  108.         je      .socket_err
  109.  
  110. ;---------------------------------------------
  111. ; << Parse Diffie-Hellman Group Exchange Reply
  112.  
  113.         stdcall ssh_recv_packet, con, 0
  114.         cmp     eax, -1
  115.         je      .socket_err
  116.  
  117.         cmp     [con.rx_buffer.message_code], SSH_MSG_KEX_DH_GEX_REPLY
  118.         jne     .proto_err
  119.  
  120.         DEBUGF  2, "Received GEX Reply\n"
  121.  
  122. ;--------------------------------
  123. ; HASH: string K_S, the host key
  124.         mov     esi, con.rx_buffer+sizeof.ssh_packet_header
  125.         mov     edx, [esi]
  126.         bswap   edx
  127.         add     edx, 4
  128.         lea     ebx, [esi+edx]
  129.         push    ebx
  130.         invoke  sha256_update, con.temp_ctx, esi, edx
  131.  
  132. ;--------------------------------------------------------------------------
  133. ; HASH: uint32 min, minimal size in bits of an acceptable group
  134. ;       uint32 n, preferred size in bits of the group the server will send
  135. ;       uint32 max, maximal size in bits of an acceptable group
  136.         invoke  sha256_update, con.temp_ctx, ssh_gex_req+sizeof.ssh_packet_header-ssh_packet_header.message_code, 12
  137.  
  138. ;----------------------------
  139. ; HASH: mpint p, safe prime
  140.         mov     esi, con.dh_p
  141.         mov     edi, mpint_tmp
  142.         call    mpint_to_big_endian
  143.         lea     edx, [eax+4]
  144.         invoke  sha256_update, con.temp_ctx, mpint_tmp, edx
  145.  
  146. ;----------------------------------------
  147. ; HASH: mpint g, generator for subgroup
  148.         mov     esi, con.dh_g
  149.         mov     edi, mpint_tmp
  150.         call    mpint_to_big_endian
  151.         lea     edx, [eax+4]
  152.         invoke  sha256_update, con.temp_ctx, mpint_tmp, edx
  153.  
  154. ;---------------------------------------------------
  155. ; HASH: mpint e, exchange value sent by the client
  156.         mov     esi, con.tx_buffer+sizeof.ssh_packet_header
  157.         mov     edx, [esi]
  158.         bswap   edx
  159.         add     edx, 4
  160.         invoke  sha256_update, con.temp_ctx, esi, edx
  161.  
  162. ;---------------------------------------------------
  163. ; HASH: mpint f, exchange value sent by the server
  164.         mov     esi, [esp]
  165.         mov     edx, [esi]
  166.         bswap   edx
  167.         add     edx, 4
  168.         invoke  sha256_update, con.temp_ctx, esi, edx
  169.         pop     esi
  170.  
  171.         mov     edi, con.dh_f
  172.         call    mpint_to_little_endian
  173.  
  174.         DEBUGF  1, "DH f: "
  175.         stdcall mpint_print, con.dh_f
  176.  
  177.         mov     edi, con.dh_signature
  178.         call    mpint_to_little_endian
  179.  
  180.         DEBUGF  1, "DH signature: "
  181.         stdcall mpint_print, con.dh_signature
  182.  
  183. ;--------------------------------------
  184. ; Calculate shared secret K = f^x mod p
  185.         stdcall mpint_modexp, con.rx_buffer, con.dh_f, con.dh_x, con.dh_p
  186.         stdcall mpint_length, con.rx_buffer
  187.  
  188.         DEBUGF  1, "DH K: "
  189.         stdcall mpint_print, con.rx_buffer
  190.  
  191. ; We always need it in big endian order, so store it as such.
  192.         mov     edi, con.dh_K
  193.         mov     esi, con.rx_buffer
  194.         call    mpint_to_big_endian
  195.         mov     [con.dh_K_length], eax
  196.  
  197. ;-----------------------------------
  198. ; HASH: mpint K, the shared secret
  199.         mov     edx, [con.dh_K_length]
  200.         add     edx, 4
  201.         invoke  sha256_update, con.temp_ctx, con.dh_K, edx
  202.  
  203. ;-------------------------------
  204. ; Finalize the exchange hash (H)
  205.         invoke  sha256_final, con.temp_ctx
  206.         mov     esi, con.temp_ctx.hash
  207.         mov     edi, con.dh_H
  208.         mov     ecx, SHA256_HASH_SIZE/4
  209.         rep movsd
  210.  
  211.         DEBUGF  1, "Exchange hash H: "
  212.         stdcall dump_hex, con.dh_H, 8
  213.  
  214. ; TODO: skip this block when re-keying
  215.         mov     esi, con.dh_H
  216.         mov     edi, con.session_id
  217.         mov     ecx, SHA256_HASH_SIZE/4
  218.         rep movsd
  219.  
  220. ;---------------
  221. ; Calculate keys
  222.  
  223. ; First, calculate partial hash of K and H so we can re-use it for every key.
  224.  
  225.         invoke  sha256_init, con.k_h_ctx
  226.  
  227.         mov     edx, [con.dh_K_length]
  228.         add     edx, 4
  229.         invoke  sha256_update, con.k_h_ctx, con.dh_K, edx
  230.         invoke  sha256_update, con.k_h_ctx, con.dh_H, 32
  231.  
  232. ;---------------------------------------------------------------
  233. ; Initial IV client to server: HASH(K || H || "A" || session_id)
  234.  
  235.         mov     esi, con.k_h_ctx
  236.         mov     edi, con.temp_ctx
  237.         mov     ecx, sizeof.ctx_sha224256/4
  238.         rep movsd
  239.         mov     [con.session_id_prefix], 'A'
  240.         invoke  sha256_update, con.temp_ctx, con.session_id_prefix, 32+1
  241.         invoke  sha256_final, con.temp_ctx.hash
  242.         mov     edi, con.tx_iv
  243.         mov     esi, con.temp_ctx
  244.         mov     ecx, SHA256_HASH_SIZE/4
  245.         rep movsd
  246.  
  247.         DEBUGF  1, "Remote IV: "
  248.         stdcall dump_hex, con.tx_iv, 8
  249.  
  250. ;---------------------------------------------------------------
  251. ; Initial IV server to client: HASH(K || H || "B" || session_id)
  252.  
  253.         mov     esi, con.k_h_ctx
  254.         mov     edi, con.temp_ctx
  255.         mov     ecx, sizeof.ctx_sha224256/4
  256.         rep     movsd
  257.         inc     [con.session_id_prefix]
  258.         invoke  sha256_update, con.temp_ctx, con.session_id_prefix, 32+1
  259.         invoke  sha256_final, con.temp_ctx
  260.         mov     edi, con.rx_iv
  261.         mov     esi, con.temp_ctx
  262.         mov     ecx, SHA256_HASH_SIZE/4
  263.         rep movsd
  264.  
  265.         DEBUGF  1, "Local IV: "
  266.         stdcall dump_hex, con.rx_iv, 8
  267.  
  268. ;-------------------------------------------------------------------
  269. ; Encryption key client to server: HASH(K || H || "C" || session_id)
  270.  
  271.         mov     esi, con.k_h_ctx
  272.         mov     edi, con.temp_ctx
  273.         mov     ecx, sizeof.ctx_sha224256/4
  274.         rep     movsd
  275.         inc     [con.session_id_prefix]
  276.         invoke  sha256_update, con.temp_ctx, con.session_id_prefix, 32+1
  277.         invoke  sha256_final, con.temp_ctx
  278.         mov     edi, con.tx_enc_key
  279.         mov     esi, con.temp_ctx
  280.         mov     ecx, SHA256_HASH_SIZE/4
  281.         rep movsd
  282.  
  283.         DEBUGF  1, "Remote key: "
  284.         stdcall dump_hex, con.tx_enc_key, 8
  285.  
  286. ;-------------------------------------------------------------------
  287. ; Encryption key server to client: HASH(K || H || "D" || session_id)
  288.  
  289.         mov     esi, con.k_h_ctx
  290.         mov     edi, con.temp_ctx
  291.         mov     ecx, sizeof.ctx_sha224256/4
  292.         rep     movsd
  293.         inc     [con.session_id_prefix]
  294.         invoke  sha256_update, con.temp_ctx, con.session_id_prefix, 32+1
  295.         invoke  sha256_final, con.temp_ctx
  296.         mov     edi, con.rx_enc_key
  297.         mov     esi, con.temp_ctx
  298.         mov     ecx, SHA256_HASH_SIZE/4
  299.         rep movsd
  300.  
  301.         DEBUGF  1, "Local key: "
  302.         stdcall dump_hex, con.rx_enc_key, 8
  303.  
  304. ;------------------------------------------------------------------
  305. ; Integrity key client to server: HASH(K || H || "E" || session_id)
  306.  
  307.         mov     esi, con.k_h_ctx
  308.         mov     edi, con.temp_ctx
  309.         mov     ecx, sizeof.ctx_sha224256/4
  310.         rep     movsd
  311.         inc     [con.session_id_prefix]
  312.         invoke  sha256_update, con.temp_ctx, con.session_id_prefix, 32+1
  313.         invoke  sha256_final, con.temp_ctx
  314.         mov     edi, con.tx_int_key
  315.         mov     esi, con.temp_ctx
  316.         mov     ecx, SHA256_HASH_SIZE/4
  317.         rep movsd
  318.  
  319.         DEBUGF  1, "Remote Integrity key: "
  320.         stdcall dump_hex, con.tx_int_key, 8
  321.  
  322. ;------------------------------------------------------------------
  323. ; Integrity key server to client: HASH(K || H || "F" || session_id)
  324.  
  325.         mov     esi, con.k_h_ctx
  326.         mov     edi, con.temp_ctx
  327.         mov     ecx, sizeof.ctx_sha224256/4
  328.         rep     movsd
  329.         inc     [con.session_id_prefix]
  330.         invoke  sha256_update, con.temp_ctx, con.session_id_prefix, 32+1
  331.         invoke  sha256_final, con.temp_ctx
  332.         mov     edi, con.rx_int_key
  333.         mov     esi, con.temp_ctx
  334.         mov     ecx, SHA256_HASH_SIZE/4
  335.         rep movsd
  336.  
  337.         DEBUGF  1, "Local Integrity key: "
  338.         stdcall dump_hex, con.rx_int_key, 8
  339.  
  340. ;-------------------------------------
  341. ; << Parse Diffie-Hellman New Keys MSG
  342.  
  343.         stdcall ssh_recv_packet, con, 0
  344.         cmp     eax, -1
  345.         je      .socket_err
  346.  
  347.         cmp     [con.rx_buffer.message_code], SSH_MSG_NEWKEYS
  348.         jne     .proto_err
  349.  
  350.         DEBUGF  2, "Received New Keys\n"
  351.  
  352. ;-------------------------------
  353. ; >> Reply with New Keys message
  354.  
  355.         stdcall ssh_send_packet, con, ssh_new_keys, ssh_new_keys.length, 0
  356.  
  357.         xor     eax, eax
  358.         ret
  359.  
  360.   .socket_err:
  361.         DEBUGF  3, "Socket error during key exchange!\n"
  362.         mov     eax, 1
  363.         ret
  364.  
  365.   .proto_err:
  366.         DEBUGF  3, "Protocol error during key exchange!\n"
  367.         mov     eax, 2
  368.         ret
  369.  
  370. endp
  371.