Subversion Repositories Kolibri OS

Rev

Rev 6922 | Blame | Compare with Previous | 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_print, con.dh_x
  86.  
  87. ; Compute e = g^x mod p
  88.         stdcall mpint_modexp, con.dh_e, con.dh_g, con.dh_x, con.dh_p
  89.  
  90.         DEBUGF  1, "DH e: "
  91.         stdcall mpint_print, con.dh_e
  92.  
  93. ; Create group exchange init packet
  94.         mov     edi, con.tx_buffer.message_code
  95.         mov     al, SSH_MSG_KEX_DH_GEX_INIT
  96.         stosb
  97.         mov     esi, con.dh_e
  98.         call    mpint_to_big_endian
  99.  
  100.         DEBUGF  2, "Sending GEX init\n"
  101.         mov     ecx, dword[con.tx_buffer.message_code+1]
  102.         bswap   ecx
  103.         add     ecx, 5
  104.         stdcall ssh_send_packet, con, con.tx_buffer.message_code, ecx, 0
  105.         cmp     eax, -1
  106.         je      .socket_err
  107.  
  108. ;---------------------------------------------
  109. ; << Parse Diffie-Hellman Group Exchange Reply
  110.  
  111.         stdcall ssh_recv_packet, con, 0
  112.         cmp     eax, -1
  113.         je      .socket_err
  114.  
  115.         cmp     [con.rx_buffer.message_code], SSH_MSG_KEX_DH_GEX_REPLY
  116.         jne     .proto_err
  117.  
  118.         DEBUGF  2, "Received GEX Reply\n"
  119.  
  120. ;--------------------------------
  121. ; HASH: string K_S, the host key
  122.         mov     esi, con.rx_buffer+sizeof.ssh_packet_header
  123.         mov     edx, [esi]
  124.         bswap   edx
  125.         add     edx, 4
  126.         lea     ebx, [esi+edx]
  127.         push    ebx
  128.         invoke  sha256_update, con.temp_ctx, esi, edx
  129.  
  130. ;--------------------------------------------------------------------------
  131. ; HASH: uint32 min, minimal size in bits of an acceptable group
  132. ;       uint32 n, preferred size in bits of the group the server will send
  133. ;       uint32 max, maximal size in bits of an acceptable group
  134.         invoke  sha256_update, con.temp_ctx, ssh_gex_req+sizeof.ssh_packet_header-ssh_packet_header.message_code, 12
  135.  
  136. ;----------------------------
  137. ; HASH: mpint p, safe prime
  138.         mov     esi, con.dh_p
  139.         mov     edi, con.mpint_tmp
  140.         call    mpint_to_big_endian
  141.         lea     edx, [eax+4]
  142.         invoke  sha256_update, con.temp_ctx, con.mpint_tmp, edx
  143.  
  144. ;----------------------------------------
  145. ; HASH: mpint g, generator for subgroup
  146.         mov     esi, con.dh_g
  147.         mov     edi, con.mpint_tmp
  148.         call    mpint_to_big_endian
  149.         lea     edx, [eax+4]
  150.         invoke  sha256_update, con.temp_ctx, con.mpint_tmp, edx
  151.  
  152. ;---------------------------------------------------
  153. ; HASH: mpint e, exchange value sent by the client
  154.         mov     esi, con.tx_buffer+sizeof.ssh_packet_header
  155.         mov     edx, [esi]
  156.         bswap   edx
  157.         add     edx, 4
  158.         invoke  sha256_update, con.temp_ctx, esi, edx
  159.  
  160. ;---------------------------------------------------
  161. ; HASH: mpint f, exchange value sent by the server
  162.         mov     esi, [esp]
  163.         mov     edx, [esi]
  164.         bswap   edx
  165.         add     edx, 4
  166.         invoke  sha256_update, con.temp_ctx, esi, edx
  167.         pop     esi
  168.  
  169.         mov     edi, con.dh_f
  170.         call    mpint_to_little_endian
  171.  
  172.         DEBUGF  1, "DH f: "
  173.         stdcall mpint_print, con.dh_f
  174.  
  175.         mov     edi, con.dh_signature
  176.         call    mpint_to_little_endian
  177.  
  178.         DEBUGF  1, "DH signature: "
  179.         stdcall mpint_print, con.dh_signature
  180.  
  181. ;--------------------------------------
  182. ; Calculate shared secret K = f^x mod p
  183.         stdcall mpint_modexp, con.rx_buffer, con.dh_f, con.dh_x, con.dh_p
  184.  
  185.         DEBUGF  1, "DH K: "
  186.         stdcall mpint_print, con.rx_buffer
  187.  
  188. ; We always need it in big endian order, so store it as such.
  189.         mov     edi, con.dh_K
  190.         mov     esi, con.rx_buffer
  191.         call    mpint_to_big_endian
  192.         mov     [con.dh_K_length], eax
  193.  
  194. ;-----------------------------------
  195. ; HASH: mpint K, the shared secret
  196.         mov     edx, [con.dh_K_length]
  197.         add     edx, 4
  198.         invoke  sha256_update, con.temp_ctx, con.dh_K, edx
  199.  
  200. ;-------------------------------
  201. ; Finalize the exchange hash (H)
  202.         invoke  sha256_final, con.temp_ctx
  203.         mov     esi, con.temp_ctx.hash
  204.         mov     edi, con.dh_H
  205.         mov     ecx, SHA256_HASH_SIZE/4
  206.         rep movsd
  207.  
  208.         DEBUGF  1, "Exchange hash H: "
  209.         stdcall dump_hex, con.dh_H, 8
  210.  
  211. ; TODO: skip this block when re-keying
  212.         mov     esi, con.dh_H
  213.         mov     edi, con.session_id
  214.         mov     ecx, SHA256_HASH_SIZE/4
  215.         rep movsd
  216.  
  217. ;---------------
  218. ; Calculate keys
  219.  
  220. ; First, calculate partial hash of K and H so we can re-use it for every key.
  221.  
  222.         invoke  sha256_init, con.k_h_ctx
  223.  
  224.         mov     edx, [con.dh_K_length]
  225.         add     edx, 4
  226.         invoke  sha256_update, con.k_h_ctx, con.dh_K, edx
  227.         invoke  sha256_update, con.k_h_ctx, con.dh_H, 32
  228.  
  229. ;---------------------------------------------------------------
  230. ; Initial IV client to server: HASH(K || H || "A" || session_id)
  231.  
  232.         mov     esi, con.k_h_ctx
  233.         mov     edi, con.temp_ctx
  234.         mov     ecx, sizeof.crash_ctx
  235.         rep movsd
  236.         mov     [con.session_id_prefix], 'A'
  237.         invoke  sha256_update, con.temp_ctx, con.session_id_prefix, 32+1
  238.         invoke  sha256_final, con.temp_ctx.hash
  239.         mov     edi, con.tx_iv
  240.         mov     esi, con.temp_ctx
  241.         mov     ecx, SHA256_HASH_SIZE/4
  242.         rep movsd
  243.  
  244.         DEBUGF  1, "Remote IV: "
  245.         stdcall dump_hex, con.tx_iv, 8
  246.  
  247. ;---------------------------------------------------------------
  248. ; Initial IV server to client: HASH(K || H || "B" || session_id)
  249.  
  250.         mov     esi, con.k_h_ctx
  251.         mov     edi, con.temp_ctx
  252.         mov     ecx, sizeof.crash_ctx/4
  253.         rep     movsd
  254.         inc     [con.session_id_prefix]
  255.         invoke  sha256_update, con.temp_ctx, con.session_id_prefix, 32+1
  256.         invoke  sha256_final, con.temp_ctx
  257.         mov     edi, con.rx_iv
  258.         mov     esi, con.temp_ctx
  259.         mov     ecx, SHA256_HASH_SIZE/4
  260.         rep movsd
  261.  
  262.         DEBUGF  1, "Local IV: "
  263.         stdcall dump_hex, con.rx_iv, 8
  264.  
  265. ;-------------------------------------------------------------------
  266. ; Encryption key client to server: HASH(K || H || "C" || session_id)
  267.  
  268.         mov     esi, con.k_h_ctx
  269.         mov     edi, con.temp_ctx
  270.         mov     ecx, sizeof.crash_ctx
  271.         rep     movsd
  272.         inc     [con.session_id_prefix]
  273.         invoke  sha256_update, con.temp_ctx, con.session_id_prefix, 32+1
  274.         invoke  sha256_final, con.temp_ctx
  275.         mov     edi, con.tx_enc_key
  276.         mov     esi, con.temp_ctx
  277.         mov     ecx, SHA256_HASH_SIZE/4
  278.         rep movsd
  279.  
  280.         DEBUGF  1, "Remote key: "
  281.         stdcall dump_hex, con.tx_enc_key, 8
  282.  
  283. ;-------------------------------------------------------------------
  284. ; Encryption key server to client: HASH(K || H || "D" || session_id)
  285.  
  286.         mov     esi, con.k_h_ctx
  287.         mov     edi, con.temp_ctx
  288.         mov     ecx, sizeof.crash_ctx/4
  289.         rep     movsd
  290.         inc     [con.session_id_prefix]
  291.         invoke  sha256_update, con.temp_ctx, con.session_id_prefix, 32+1
  292.         invoke  sha256_final, con.temp_ctx
  293.         mov     edi, con.rx_enc_key
  294.         mov     esi, con.temp_ctx
  295.         mov     ecx, SHA256_HASH_SIZE/4
  296.         rep movsd
  297.  
  298.         DEBUGF  1, "Local key: "
  299.         stdcall dump_hex, con.rx_enc_key, 8
  300.  
  301. ;------------------------------------------------------------------
  302. ; Integrity key client to server: HASH(K || H || "E" || session_id)
  303.  
  304.         mov     esi, con.k_h_ctx
  305.         mov     edi, con.temp_ctx
  306.         mov     ecx, sizeof.crash_ctx/4
  307.         rep     movsd
  308.         inc     [con.session_id_prefix]
  309.         invoke  sha256_update, con.temp_ctx, con.session_id_prefix, 32+1
  310.         invoke  sha256_final, con.temp_ctx
  311.         mov     edi, con.tx_int_key
  312.         mov     esi, con.temp_ctx
  313.         mov     ecx, SHA256_HASH_SIZE/4
  314.         rep movsd
  315.  
  316.         DEBUGF  1, "Remote Integrity key: "
  317.         stdcall dump_hex, con.tx_int_key, 8
  318.  
  319. ;------------------------------------------------------------------
  320. ; Integrity key server to client: HASH(K || H || "F" || session_id)
  321.  
  322.         mov     esi, con.k_h_ctx
  323.         mov     edi, con.temp_ctx
  324.         mov     ecx, sizeof.crash_ctx/4
  325.         rep     movsd
  326.         inc     [con.session_id_prefix]
  327.         invoke  sha256_update, con.temp_ctx, con.session_id_prefix, 32+1
  328.         invoke  sha256_final, con.temp_ctx
  329.         mov     edi, con.rx_int_key
  330.         mov     esi, con.temp_ctx
  331.         mov     ecx, SHA256_HASH_SIZE/4
  332.         rep movsd
  333.  
  334.         DEBUGF  1, "Local Integrity key: "
  335.         stdcall dump_hex, con.rx_int_key, 8
  336.  
  337. ;-------------------------------------
  338. ; << Parse Diffie-Hellman New Keys MSG
  339.  
  340.         stdcall ssh_recv_packet, con, 0
  341.         cmp     eax, -1
  342.         je      .socket_err
  343.  
  344.         cmp     [con.rx_buffer.message_code], SSH_MSG_NEWKEYS
  345.         jne     .proto_err
  346.  
  347.         DEBUGF  2, "Received New Keys\n"
  348.  
  349. ;-------------------------------
  350. ; >> Reply with New Keys message
  351.  
  352.         stdcall ssh_send_packet, con, ssh_new_keys, ssh_new_keys.length, 0
  353.  
  354.         xor     eax, eax
  355.         ret
  356.  
  357.   .socket_err:
  358.         DEBUGF  3, "Socket error during key exchange!\n"
  359.         mov     eax, 1
  360.         ret
  361.  
  362.   .proto_err:
  363.         DEBUGF  3, "Protocol error during key exchange!\n"
  364.         mov     eax, 2
  365.         ret
  366.  
  367. endp
  368.