Subversion Repositories Kolibri OS

Rev

Rev 6922 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
6419 hidnplayr 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 .
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
 
6469 hidnplayr 28
        DEBUGF  2, "Sending GEX\n"
29
        stdcall ssh_send_packet, con, ssh_gex_req, ssh_gex_req.length, 0
6419 hidnplayr 30
        cmp     eax, -1
31
        je      .socket_err
32
 
33
;---------------------------------------------
34
; << Parse Diffie-Hellman Group Exchange Group
35
 
6469 hidnplayr 36
        stdcall ssh_recv_packet, con, 0
6419 hidnplayr 37
        cmp     eax, -1
38
        je      .socket_err
39
 
6469 hidnplayr 40
        cmp     [con.rx_buffer.message_code], SSH_MSG_KEX_DH_GEX_GROUP
6419 hidnplayr 41
        jne     proto_err
6469 hidnplayr 42
        DEBUGF  2, "Received GEX group\n"
6419 hidnplayr 43
 
6469 hidnplayr 44
        mov     esi, con.rx_buffer+sizeof.ssh_packet_header
45
        mov     edi, con.dh_p
6419 hidnplayr 46
        DEBUGF  1, "DH modulus (p): "
47
        call    mpint_to_little_endian
6469 hidnplayr 48
        stdcall mpint_print, con.dh_p
6419 hidnplayr 49
 
50
        DEBUGF  1, "DH base (g): "
6469 hidnplayr 51
        mov     edi, con.dh_g
6419 hidnplayr 52
        call    mpint_to_little_endian
6469 hidnplayr 53
        stdcall mpint_print, con.dh_g
6419 hidnplayr 54
 
55
;-------------------------------------------
56
; >> Send Diffie-Hellman Group Exchange Init
57
 
58
; generate a random number x, where 1 < x < (p-1)/2
6469 hidnplayr 59
        mov     edi, con.dh_x+4
60
        mov     [con.dh_x], DH_PRIVATE_KEY_SIZE/8
6419 hidnplayr 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
6469 hidnplayr 74
        inc     dword[con.dh_x]
6419 hidnplayr 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
6469 hidnplayr 81
        rep stosd
6419 hidnplayr 82
end if
83
 
84
        DEBUGF  1, "DH x: "
6469 hidnplayr 85
        stdcall mpint_print, con.dh_x
6419 hidnplayr 86
 
87
; Compute e = g^x mod p
6469 hidnplayr 88
        stdcall mpint_modexp, con.dh_e, con.dh_g, con.dh_x, con.dh_p
6419 hidnplayr 89
 
90
        DEBUGF  1, "DH e: "
6469 hidnplayr 91
        stdcall mpint_print, con.dh_e
6419 hidnplayr 92
 
93
; Create group exchange init packet
6469 hidnplayr 94
        mov     edi, con.tx_buffer.message_code
6419 hidnplayr 95
        mov     al, SSH_MSG_KEX_DH_GEX_INIT
96
        stosb
6469 hidnplayr 97
        mov     esi, con.dh_e
6419 hidnplayr 98
        call    mpint_to_big_endian
99
 
6469 hidnplayr 100
        DEBUGF  2, "Sending GEX init\n"
101
        mov     ecx, dword[con.tx_buffer.message_code+1]
6419 hidnplayr 102
        bswap   ecx
103
        add     ecx, 5
6469 hidnplayr 104
        stdcall ssh_send_packet, con, con.tx_buffer.message_code, ecx, 0
6419 hidnplayr 105
        cmp     eax, -1
106
        je      .socket_err
107
 
108
;---------------------------------------------
109
; << Parse Diffie-Hellman Group Exchange Reply
110
 
6469 hidnplayr 111
        stdcall ssh_recv_packet, con, 0
6419 hidnplayr 112
        cmp     eax, -1
113
        je      .socket_err
114
 
6469 hidnplayr 115
        cmp     [con.rx_buffer.message_code], SSH_MSG_KEX_DH_GEX_REPLY
6419 hidnplayr 116
        jne     .proto_err
117
 
6469 hidnplayr 118
        DEBUGF  2, "Received GEX Reply\n"
6419 hidnplayr 119
 
120
;--------------------------------
6469 hidnplayr 121
; HASH: string K_S, the host key
122
        mov     esi, con.rx_buffer+sizeof.ssh_packet_header
6419 hidnplayr 123
        mov     edx, [esi]
124
        bswap   edx
125
        add     edx, 4
126
        lea     ebx, [esi+edx]
127
        push    ebx
6469 hidnplayr 128
        invoke  sha256_update, con.temp_ctx, esi, edx
6419 hidnplayr 129
 
130
;--------------------------------------------------------------------------
6469 hidnplayr 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
6419 hidnplayr 135
 
136
;----------------------------
6469 hidnplayr 137
; HASH: mpint p, safe prime
138
        mov     esi, con.dh_p
6922 hidnplayr 139
        mov     edi, con.mpint_tmp
6419 hidnplayr 140
        call    mpint_to_big_endian
141
        lea     edx, [eax+4]
6922 hidnplayr 142
        invoke  sha256_update, con.temp_ctx, con.mpint_tmp, edx
6419 hidnplayr 143
 
144
;----------------------------------------
6469 hidnplayr 145
; HASH: mpint g, generator for subgroup
146
        mov     esi, con.dh_g
6922 hidnplayr 147
        mov     edi, con.mpint_tmp
6419 hidnplayr 148
        call    mpint_to_big_endian
149
        lea     edx, [eax+4]
6922 hidnplayr 150
        invoke  sha256_update, con.temp_ctx, con.mpint_tmp, edx
6419 hidnplayr 151
 
152
;---------------------------------------------------
6469 hidnplayr 153
; HASH: mpint e, exchange value sent by the client
154
        mov     esi, con.tx_buffer+sizeof.ssh_packet_header
6419 hidnplayr 155
        mov     edx, [esi]
156
        bswap   edx
157
        add     edx, 4
6469 hidnplayr 158
        invoke  sha256_update, con.temp_ctx, esi, edx
6419 hidnplayr 159
 
160
;---------------------------------------------------
6469 hidnplayr 161
; HASH: mpint f, exchange value sent by the server
6419 hidnplayr 162
        mov     esi, [esp]
163
        mov     edx, [esi]
164
        bswap   edx
165
        add     edx, 4
6469 hidnplayr 166
        invoke  sha256_update, con.temp_ctx, esi, edx
6419 hidnplayr 167
        pop     esi
168
 
6469 hidnplayr 169
        mov     edi, con.dh_f
6419 hidnplayr 170
        call    mpint_to_little_endian
171
 
172
        DEBUGF  1, "DH f: "
6469 hidnplayr 173
        stdcall mpint_print, con.dh_f
6419 hidnplayr 174
 
6469 hidnplayr 175
        mov     edi, con.dh_signature
6419 hidnplayr 176
        call    mpint_to_little_endian
177
 
178
        DEBUGF  1, "DH signature: "
6469 hidnplayr 179
        stdcall mpint_print, con.dh_signature
6419 hidnplayr 180
 
181
;--------------------------------------
182
; Calculate shared secret K = f^x mod p
6469 hidnplayr 183
        stdcall mpint_modexp, con.rx_buffer, con.dh_f, con.dh_x, con.dh_p
6419 hidnplayr 184
 
185
        DEBUGF  1, "DH K: "
6469 hidnplayr 186
        stdcall mpint_print, con.rx_buffer
6419 hidnplayr 187
 
188
; We always need it in big endian order, so store it as such.
6469 hidnplayr 189
        mov     edi, con.dh_K
190
        mov     esi, con.rx_buffer
6419 hidnplayr 191
        call    mpint_to_big_endian
6469 hidnplayr 192
        mov     [con.dh_K_length], eax
6419 hidnplayr 193
 
194
;-----------------------------------
6469 hidnplayr 195
; HASH: mpint K, the shared secret
196
        mov     edx, [con.dh_K_length]
6419 hidnplayr 197
        add     edx, 4
6469 hidnplayr 198
        invoke  sha256_update, con.temp_ctx, con.dh_K, edx
6419 hidnplayr 199
 
200
;-------------------------------
201
; Finalize the exchange hash (H)
6469 hidnplayr 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
6419 hidnplayr 207
 
208
        DEBUGF  1, "Exchange hash H: "
6469 hidnplayr 209
        stdcall dump_hex, con.dh_H, 8
6419 hidnplayr 210
 
211
; TODO: skip this block when re-keying
6469 hidnplayr 212
        mov     esi, con.dh_H
213
        mov     edi, con.session_id
214
        mov     ecx, SHA256_HASH_SIZE/4
6419 hidnplayr 215
        rep movsd
216
 
217
;---------------
218
; Calculate keys
219
 
6469 hidnplayr 220
; First, calculate partial hash of K and H so we can re-use it for every key.
6419 hidnplayr 221
 
6469 hidnplayr 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
 
6419 hidnplayr 229
;---------------------------------------------------------------
230
; Initial IV client to server: HASH(K || H || "A" || session_id)
231
 
6469 hidnplayr 232
        mov     esi, con.k_h_ctx
233
        mov     edi, con.temp_ctx
7698 dunkaist 234
        mov     ecx, sizeof.crash_ctx
6469 hidnplayr 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
6419 hidnplayr 243
 
244
        DEBUGF  1, "Remote IV: "
6469 hidnplayr 245
        stdcall dump_hex, con.tx_iv, 8
6419 hidnplayr 246
 
247
;---------------------------------------------------------------
248
; Initial IV server to client: HASH(K || H || "B" || session_id)
249
 
6469 hidnplayr 250
        mov     esi, con.k_h_ctx
251
        mov     edi, con.temp_ctx
7698 dunkaist 252
        mov     ecx, sizeof.crash_ctx/4
6469 hidnplayr 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
6419 hidnplayr 261
 
262
        DEBUGF  1, "Local IV: "
6469 hidnplayr 263
        stdcall dump_hex, con.rx_iv, 8
6419 hidnplayr 264
 
265
;-------------------------------------------------------------------
266
; Encryption key client to server: HASH(K || H || "C" || session_id)
267
 
6469 hidnplayr 268
        mov     esi, con.k_h_ctx
269
        mov     edi, con.temp_ctx
7698 dunkaist 270
        mov     ecx, sizeof.crash_ctx
6469 hidnplayr 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
6419 hidnplayr 279
 
280
        DEBUGF  1, "Remote key: "
6469 hidnplayr 281
        stdcall dump_hex, con.tx_enc_key, 8
6419 hidnplayr 282
 
283
;-------------------------------------------------------------------
284
; Encryption key server to client: HASH(K || H || "D" || session_id)
285
 
6469 hidnplayr 286
        mov     esi, con.k_h_ctx
287
        mov     edi, con.temp_ctx
7698 dunkaist 288
        mov     ecx, sizeof.crash_ctx/4
6469 hidnplayr 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
6419 hidnplayr 297
 
298
        DEBUGF  1, "Local key: "
6469 hidnplayr 299
        stdcall dump_hex, con.rx_enc_key, 8
6419 hidnplayr 300
 
301
;------------------------------------------------------------------
302
; Integrity key client to server: HASH(K || H || "E" || session_id)
303
 
6469 hidnplayr 304
        mov     esi, con.k_h_ctx
305
        mov     edi, con.temp_ctx
7698 dunkaist 306
        mov     ecx, sizeof.crash_ctx/4
6469 hidnplayr 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
6419 hidnplayr 315
 
316
        DEBUGF  1, "Remote Integrity key: "
6469 hidnplayr 317
        stdcall dump_hex, con.tx_int_key, 8
6419 hidnplayr 318
 
319
;------------------------------------------------------------------
320
; Integrity key server to client: HASH(K || H || "F" || session_id)
321
 
6469 hidnplayr 322
        mov     esi, con.k_h_ctx
323
        mov     edi, con.temp_ctx
7698 dunkaist 324
        mov     ecx, sizeof.crash_ctx/4
6469 hidnplayr 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
6419 hidnplayr 333
 
334
        DEBUGF  1, "Local Integrity key: "
6469 hidnplayr 335
        stdcall dump_hex, con.rx_int_key, 8
6419 hidnplayr 336
 
337
;-------------------------------------
338
; << Parse Diffie-Hellman New Keys MSG
339
 
6469 hidnplayr 340
        stdcall ssh_recv_packet, con, 0
6419 hidnplayr 341
        cmp     eax, -1
342
        je      .socket_err
343
 
6469 hidnplayr 344
        cmp     [con.rx_buffer.message_code], SSH_MSG_NEWKEYS
6419 hidnplayr 345
        jne     .proto_err
346
 
6469 hidnplayr 347
        DEBUGF  2, "Received New Keys\n"
6419 hidnplayr 348
 
349
;-------------------------------
350
; >> Reply with New Keys message
351
 
6469 hidnplayr 352
        stdcall ssh_send_packet, con, ssh_new_keys, ssh_new_keys.length, 0
6419 hidnplayr 353
 
354
        xor     eax, eax
355
        ret
356
 
357
  .socket_err:
6469 hidnplayr 358
        DEBUGF  3, "Socket error during key exchange!\n"
6419 hidnplayr 359
        mov     eax, 1
360
        ret
361
 
362
  .proto_err:
6469 hidnplayr 363
        DEBUGF  3, "Protocol error during key exchange!\n"
6419 hidnplayr 364
        mov     eax, 2
365
        ret
366
 
367
endp