/[rdesktop]/sourceforge.net/trunk/rdesktop/secure.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /sourceforge.net/trunk/rdesktop/secure.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1237 - (hide annotations)
Wed Jun 14 08:26:00 2006 UTC (17 years, 11 months ago) by matthewc
File MIME type: text/plain
File size: 24533 byte(s)
Allow server public key to be anywhere from 512 bits to 2048 bits.
(Vista Beta 2 uses a 2048 bit key)

1 forsberg 352 /* -*- c-basic-offset: 8 -*-
2 matty 10 rdesktop: A Remote Desktop Protocol client.
3     Protocol services - RDP encryption and licensing
4 stargo 828 Copyright (C) Matthew Chapman 1999-2005
5 matty 10
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10    
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     GNU General Public License for more details.
15    
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19     */
20    
21     #include "rdesktop.h"
22 matty 32
23     #include <openssl/rc4.h>
24     #include <openssl/md5.h>
25     #include <openssl/sha.h>
26     #include <openssl/bn.h>
27 forsberg 352 #include <openssl/x509v3.h>
28 matty 10
29 jsorg71 710 extern char g_hostname[16];
30 jsorg71 447 extern int g_width;
31     extern int g_height;
32 astrand 1035 extern unsigned int g_keylayout;
33 astrand 964 extern int g_keyboard_type;
34     extern int g_keyboard_subtype;
35     extern int g_keyboard_functionkeys;
36 jsorg71 437 extern BOOL g_encryption;
37 jsorg71 380 extern BOOL g_licence_issued;
38 jsorg71 438 extern BOOL g_use_rdp5;
39 matthewc 482 extern BOOL g_console_session;
40 astrand 1042 extern int g_server_depth;
41 forsberg 412 extern uint16 mcs_userid;
42 matthewc 432 extern VCHANNEL g_channels[];
43     extern unsigned int g_num_channels;
44 matty 10
45     static int rc4_key_len;
46     static RC4_KEY rc4_decrypt_key;
47     static RC4_KEY rc4_encrypt_key;
48 forsberg 352 static RSA *server_public_key;
49 matthewc 1237 static uint32 server_public_key_len;
50 matty 10
51 matthewc 57 static uint8 sec_sign_key[16];
52 matty 10 static uint8 sec_decrypt_key[16];
53     static uint8 sec_encrypt_key[16];
54 matthewc 57 static uint8 sec_decrypt_update_key[16];
55     static uint8 sec_encrypt_update_key[16];
56 matthewc 1237 static uint8 sec_crypted_random[SEC_MAX_MODULUS_SIZE];
57 matty 10
58 jsorg71 438 uint16 g_server_rdp_version = 0;
59 forsberg 352
60 astrand 977 /* These values must be available to reset state - Session Directory */
61     static int sec_encrypt_use_count = 0;
62     static int sec_decrypt_use_count = 0;
63    
64 matty 10 /*
65 matthewc 699 * I believe this is based on SSLv3 with the following differences:
66     * MAC algorithm (5.2.3.1) uses only 32-bit length in place of seq_num/type/length fields
67     * MAC algorithm uses SHA1 and MD5 for the two hash functions instead of one or other
68     * key_block algorithm (6.2.2) uses 'X', 'YY', 'ZZZ' instead of 'A', 'BB', 'CCC'
69     * key_block partitioning is different (16 bytes each: MAC secret, decrypt key, encrypt key)
70     * encryption/decryption keys updated every 4096 packets
71     * See http://wp.netscape.com/eng/ssl3/draft302.txt
72     */
73    
74     /*
75     * 48-byte transformation used to generate master secret (6.1) and key material (6.2.2).
76 matty 10 * Both SHA1 and MD5 algorithms are used.
77     */
78 matty 25 void
79 astrand 64 sec_hash_48(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2, uint8 salt)
80 matty 10 {
81     uint8 shasig[20];
82     uint8 pad[4];
83     SHA_CTX sha;
84     MD5_CTX md5;
85     int i;
86    
87     for (i = 0; i < 3; i++)
88     {
89 matty 24 memset(pad, salt + i, i + 1);
90 matty 10
91     SHA1_Init(&sha);
92 matty 24 SHA1_Update(&sha, pad, i + 1);
93 matty 10 SHA1_Update(&sha, in, 48);
94     SHA1_Update(&sha, salt1, 32);
95     SHA1_Update(&sha, salt2, 32);
96     SHA1_Final(shasig, &sha);
97    
98     MD5_Init(&md5);
99     MD5_Update(&md5, in, 48);
100     MD5_Update(&md5, shasig, 20);
101 matty 24 MD5_Final(&out[i * 16], &md5);
102 matty 10 }
103     }
104    
105     /*
106 matthewc 699 * 16-byte transformation used to generate export keys (6.2.2).
107 matty 10 */
108 matty 25 void
109 astrand 64 sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2)
110 matty 10 {
111     MD5_CTX md5;
112    
113     MD5_Init(&md5);
114     MD5_Update(&md5, in, 16);
115     MD5_Update(&md5, salt1, 32);
116     MD5_Update(&md5, salt2, 32);
117     MD5_Final(out, &md5);
118     }
119    
120     /* Reduce key entropy from 64 to 40 bits */
121 matty 25 static void
122 astrand 64 sec_make_40bit(uint8 * key)
123 matty 10 {
124     key[0] = 0xd1;
125     key[1] = 0x26;
126     key[2] = 0x9e;
127     }
128    
129 matthewc 699 /* Generate encryption keys given client and server randoms */
130 matty 25 static void
131 matthewc 699 sec_generate_keys(uint8 * client_random, uint8 * server_random, int rc4_key_size)
132 matty 10 {
133 matthewc 699 uint8 pre_master_secret[48];
134     uint8 master_secret[48];
135     uint8 key_block[48];
136 matty 10
137 matthewc 699 /* Construct pre-master secret */
138 astrand 706 memcpy(pre_master_secret, client_random, 24);
139 matthewc 699 memcpy(pre_master_secret + 24, server_random, 24);
140 matty 10
141 matthewc 699 /* Generate master secret and then key material */
142     sec_hash_48(master_secret, pre_master_secret, client_random, server_random, 'A');
143 astrand 706 sec_hash_48(key_block, master_secret, client_random, server_random, 'X');
144 matty 10
145 matthewc 699 /* First 16 bytes of key material is MAC secret */
146     memcpy(sec_sign_key, key_block, 16);
147 matty 10
148 matthewc 699 /* Generate export keys from next two blocks of 16 bytes */
149     sec_hash_16(sec_decrypt_key, &key_block[16], client_random, server_random);
150     sec_hash_16(sec_encrypt_key, &key_block[32], client_random, server_random);
151 matty 10
152     if (rc4_key_size == 1)
153     {
154 matty 30 DEBUG(("40-bit encryption enabled\n"));
155 matty 10 sec_make_40bit(sec_sign_key);
156     sec_make_40bit(sec_decrypt_key);
157     sec_make_40bit(sec_encrypt_key);
158     rc4_key_len = 8;
159     }
160     else
161     {
162 forsberg 352 DEBUG(("rc_4_key_size == %d, 128-bit encryption enabled\n", rc4_key_size));
163 matty 10 rc4_key_len = 16;
164     }
165    
166 matthewc 57 /* Save initial RC4 keys as update keys */
167     memcpy(sec_decrypt_update_key, sec_decrypt_key, 16);
168     memcpy(sec_encrypt_update_key, sec_encrypt_key, 16);
169 matty 10
170     /* Initialise RC4 state arrays */
171     RC4_set_key(&rc4_decrypt_key, rc4_key_len, sec_decrypt_key);
172     RC4_set_key(&rc4_encrypt_key, rc4_key_len, sec_encrypt_key);
173     }
174    
175 matty 24 static uint8 pad_54[40] = {
176     54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
177 matty 25 54, 54, 54,
178 matty 24 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
179 matty 25 54, 54, 54
180 matty 10 };
181    
182 matty 24 static uint8 pad_92[48] = {
183     92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
184 matty 25 92, 92, 92, 92, 92, 92, 92,
185 matty 24 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
186 matty 25 92, 92, 92, 92, 92, 92, 92
187 matty 10 };
188    
189     /* Output a uint32 into a buffer (little-endian) */
190 matty 25 void
191 astrand 64 buf_out_uint32(uint8 * buffer, uint32 value)
192 matty 10 {
193     buffer[0] = (value) & 0xff;
194     buffer[1] = (value >> 8) & 0xff;
195     buffer[2] = (value >> 16) & 0xff;
196     buffer[3] = (value >> 24) & 0xff;
197     }
198    
199 matthewc 699 /* Generate a MAC hash (5.2.3.1), using a combination of SHA1 and MD5 */
200 matty 25 void
201 astrand 82 sec_sign(uint8 * signature, int siglen, uint8 * session_key, int keylen, uint8 * data, int datalen)
202 matty 10 {
203     uint8 shasig[20];
204     uint8 md5sig[16];
205     uint8 lenhdr[4];
206     SHA_CTX sha;
207     MD5_CTX md5;
208    
209 matty 24 buf_out_uint32(lenhdr, datalen);
210 matty 10
211     SHA1_Init(&sha);
212 matthewc 61 SHA1_Update(&sha, session_key, keylen);
213 matty 10 SHA1_Update(&sha, pad_54, 40);
214     SHA1_Update(&sha, lenhdr, 4);
215     SHA1_Update(&sha, data, datalen);
216     SHA1_Final(shasig, &sha);
217    
218     MD5_Init(&md5);
219 matthewc 61 MD5_Update(&md5, session_key, keylen);
220 matty 10 MD5_Update(&md5, pad_92, 48);
221     MD5_Update(&md5, shasig, 20);
222     MD5_Final(md5sig, &md5);
223    
224 matthewc 61 memcpy(signature, md5sig, siglen);
225 matty 10 }
226    
227 matthewc 699 /* Update an encryption key */
228 matty 25 static void
229 astrand 64 sec_update(uint8 * key, uint8 * update_key)
230 matty 10 {
231     uint8 shasig[20];
232     SHA_CTX sha;
233     MD5_CTX md5;
234     RC4_KEY update;
235    
236     SHA1_Init(&sha);
237 matthewc 57 SHA1_Update(&sha, update_key, rc4_key_len);
238 matty 10 SHA1_Update(&sha, pad_54, 40);
239 matthewc 57 SHA1_Update(&sha, key, rc4_key_len);
240 matty 10 SHA1_Final(shasig, &sha);
241    
242     MD5_Init(&md5);
243 matthewc 57 MD5_Update(&md5, update_key, rc4_key_len);
244 matty 10 MD5_Update(&md5, pad_92, 48);
245     MD5_Update(&md5, shasig, 20);
246     MD5_Final(key, &md5);
247    
248     RC4_set_key(&update, rc4_key_len, key);
249     RC4(&update, rc4_key_len, key, key);
250    
251     if (rc4_key_len == 8)
252     sec_make_40bit(key);
253     }
254    
255     /* Encrypt data using RC4 */
256 matty 25 static void
257 astrand 64 sec_encrypt(uint8 * data, int length)
258 matty 10 {
259 astrand 977 if (sec_encrypt_use_count == 4096)
260 matty 10 {
261     sec_update(sec_encrypt_key, sec_encrypt_update_key);
262     RC4_set_key(&rc4_encrypt_key, rc4_key_len, sec_encrypt_key);
263 astrand 977 sec_encrypt_use_count = 0;
264 matty 10 }
265    
266     RC4(&rc4_encrypt_key, length, data, data);
267 astrand 977 sec_encrypt_use_count++;
268 matty 10 }
269    
270     /* Decrypt data using RC4 */
271 forsberg 352 void
272 astrand 64 sec_decrypt(uint8 * data, int length)
273 matty 10 {
274 astrand 977 if (sec_decrypt_use_count == 4096)
275 matty 10 {
276     sec_update(sec_decrypt_key, sec_decrypt_update_key);
277     RC4_set_key(&rc4_decrypt_key, rc4_key_len, sec_decrypt_key);
278 astrand 977 sec_decrypt_use_count = 0;
279 matty 10 }
280    
281     RC4(&rc4_decrypt_key, length, data, data);
282 astrand 977 sec_decrypt_use_count++;
283 matty 10 }
284    
285 matty 25 static void
286 astrand 64 reverse(uint8 * p, int len)
287 matty 10 {
288     int i, j;
289 matty 32 uint8 temp;
290 matty 10
291 astrand 64 for (i = 0, j = len - 1; i < j; i++, j--)
292 matty 10 {
293 matty 32 temp = p[i];
294     p[i] = p[j];
295     p[j] = temp;
296 matty 10 }
297     }
298    
299     /* Perform an RSA public key encryption operation */
300 matty 25 static void
301 matthewc 1237 sec_rsa_encrypt(uint8 * out, uint8 * in, int len, uint32 modulus_size, uint8 * modulus, uint8 * exponent)
302 matty 10 {
303 matthewc 295 BN_CTX *ctx;
304 matty 32 BIGNUM mod, exp, x, y;
305 matthewc 1237 uint8 inr[SEC_MAX_MODULUS_SIZE];
306 matty 32 int outlen;
307 matty 10
308 matthewc 1237 reverse(modulus, modulus_size);
309 matty 32 reverse(exponent, SEC_EXPONENT_SIZE);
310     memcpy(inr, in, len);
311     reverse(inr, len);
312 matty 10
313 matthewc 295 ctx = BN_CTX_new();
314 matty 32 BN_init(&mod);
315     BN_init(&exp);
316     BN_init(&x);
317     BN_init(&y);
318    
319 matthewc 1237 BN_bin2bn(modulus, modulus_size, &mod);
320 matty 32 BN_bin2bn(exponent, SEC_EXPONENT_SIZE, &exp);
321     BN_bin2bn(inr, len, &x);
322 matthewc 295 BN_mod_exp(&y, &x, &exp, &mod, ctx);
323 matty 32 outlen = BN_bn2bin(&y, out);
324     reverse(out, outlen);
325 matthewc 1237 if (outlen < modulus_size)
326     memset(out + outlen, 0, modulus_size - outlen);
327 matty 32
328     BN_free(&y);
329     BN_clear_free(&x);
330     BN_free(&exp);
331     BN_free(&mod);
332 matthewc 295 BN_CTX_free(ctx);
333 matty 10 }
334    
335     /* Initialise secure transport packet */
336 matty 25 STREAM
337     sec_init(uint32 flags, int maxlen)
338 matty 10 {
339     int hdrlen;
340     STREAM s;
341    
342 jsorg71 380 if (!g_licence_issued)
343 matty 28 hdrlen = (flags & SEC_ENCRYPT) ? 12 : 4;
344     else
345     hdrlen = (flags & SEC_ENCRYPT) ? 12 : 0;
346 matty 24 s = mcs_init(maxlen + hdrlen);
347 matty 10 s_push_layer(s, sec_hdr, hdrlen);
348    
349     return s;
350     }
351    
352 forsberg 412 /* Transmit secure transport packet over specified channel */
353 matty 25 void
354 forsberg 412 sec_send_to_channel(STREAM s, uint32 flags, uint16 channel)
355 matty 10 {
356     int datalen;
357    
358     s_pop_layer(s, sec_hdr);
359 jsorg71 380 if (!g_licence_issued || (flags & SEC_ENCRYPT))
360 matty 28 out_uint32_le(s, flags);
361 matty 10
362     if (flags & SEC_ENCRYPT)
363     {
364     flags &= ~SEC_ENCRYPT;
365     datalen = s->end - s->p - 8;
366    
367 matty 30 #if WITH_DEBUG
368     DEBUG(("Sending encrypted packet:\n"));
369 matty 24 hexdump(s->p + 8, datalen);
370 matty 10 #endif
371    
372 astrand 82 sec_sign(s->p, 8, sec_sign_key, rc4_key_len, s->p + 8, datalen);
373 matty 24 sec_encrypt(s->p + 8, datalen);
374 matty 10 }
375    
376 forsberg 412 mcs_send_to_channel(s, channel);
377 matty 10 }
378    
379 forsberg 412 /* Transmit secure transport packet */
380    
381     void
382     sec_send(STREAM s, uint32 flags)
383     {
384     sec_send_to_channel(s, flags, MCS_GLOBAL_CHANNEL);
385     }
386    
387    
388 matty 10 /* Transfer the client random to the server */
389 matty 25 static void
390 matthewc 192 sec_establish_key(void)
391 matty 10 {
392 matthewc 1237 uint32 length = server_public_key_len + SEC_PADDING_SIZE;
393 matty 10 uint32 flags = SEC_CLIENT_RANDOM;
394     STREAM s;
395    
396 matthewc 1237 s = sec_init(flags, length+4);
397 matty 10
398     out_uint32_le(s, length);
399 matthewc 1237 out_uint8p(s, sec_crypted_random, server_public_key_len);
400 matty 10 out_uint8s(s, SEC_PADDING_SIZE);
401    
402     s_mark_end(s);
403     sec_send(s, flags);
404     }
405    
406     /* Output connect initial data blob */
407 matty 25 static void
408     sec_out_mcs_data(STREAM s)
409 matty 10 {
410 jsorg71 710 int hostlen = 2 * strlen(g_hostname);
411 matthewc 432 int length = 158 + 76 + 12 + 4;
412     unsigned int i;
413 astrand 101
414 matthewc 432 if (g_num_channels > 0)
415 astrand 435 length += g_num_channels * 12 + 8;
416 forsberg 412
417 jsorg71 88 if (hostlen > 30)
418     hostlen = 30;
419 matty 10
420 matthewc 642 /* Generic Conference Control (T.124) ConferenceCreateRequest */
421     out_uint16_be(s, 5);
422 matty 10 out_uint16_be(s, 0x14);
423     out_uint8(s, 0x7c);
424     out_uint16_be(s, 1);
425    
426 forsberg 352 out_uint16_be(s, (length | 0x8000)); /* remaining length */
427 matty 10
428     out_uint16_be(s, 8); /* length? */
429     out_uint16_be(s, 16);
430     out_uint8(s, 0);
431     out_uint16_le(s, 0xc001);
432     out_uint8(s, 0);
433    
434 matthewc 642 out_uint32_le(s, 0x61637544); /* OEM ID: "Duca", as in Ducati. */
435 forsberg 352 out_uint16_be(s, ((length - 14) | 0x8000)); /* remaining length */
436 matty 10
437     /* Client information */
438     out_uint16_le(s, SEC_TAG_CLI_INFO);
439 forsberg 352 out_uint16_le(s, 212); /* length */
440 jsorg71 438 out_uint16_le(s, g_use_rdp5 ? 4 : 1); /* RDP version. 1 == RDP4, 4 == RDP5. */
441 matty 10 out_uint16_le(s, 8);
442 jsorg71 447 out_uint16_le(s, g_width);
443     out_uint16_le(s, g_height);
444 matty 10 out_uint16_le(s, 0xca01);
445     out_uint16_le(s, 0xaa03);
446 jsorg71 710 out_uint32_le(s, g_keylayout);
447 forsberg 352 out_uint32_le(s, 2600); /* Client build. We are now 2600 compatible :-) */
448 matty 10
449     /* Unicode name of client, padded to 32 bytes */
450 jsorg71 710 rdp_out_unistr(s, g_hostname, hostlen);
451 matty 24 out_uint8s(s, 30 - hostlen);
452 matty 10
453 astrand 966 /* See
454     http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wceddk40/html/cxtsksupportingremotedesktopprotocol.asp */
455 astrand 964 out_uint32_le(s, g_keyboard_type);
456     out_uint32_le(s, g_keyboard_subtype);
457     out_uint32_le(s, g_keyboard_functionkeys);
458 matty 24 out_uint8s(s, 64); /* reserved? 4 + 12 doublewords */
459 n-ki 677 out_uint16_le(s, 0xca01); /* colour depth? */
460 matthewc 365 out_uint16_le(s, 1);
461 matty 10
462 forsberg 352 out_uint32(s, 0);
463 astrand 1042 out_uint8(s, g_server_depth);
464 forsberg 357 out_uint16_le(s, 0x0700);
465     out_uint8(s, 0);
466 forsberg 352 out_uint32_le(s, 1);
467     out_uint8s(s, 64); /* End of client info */
468    
469     out_uint16_le(s, SEC_TAG_CLI_4);
470     out_uint16_le(s, 12);
471 matthewc 482 out_uint32_le(s, g_console_session ? 0xb : 9);
472 matthewc 365 out_uint32(s, 0);
473 forsberg 352
474 matty 10 /* Client encryption settings */
475     out_uint16_le(s, SEC_TAG_CLI_CRYPT);
476 forsberg 352 out_uint16_le(s, 12); /* length */
477 jsorg71 437 out_uint32_le(s, g_encryption ? 0x3 : 0); /* encryption supported, 128-bit supported */
478 matthewc 365 out_uint32(s, 0); /* Unknown */
479 forsberg 352
480 matthewc 432 DEBUG_RDP5(("g_num_channels is %d\n", g_num_channels));
481     if (g_num_channels > 0)
482 forsberg 412 {
483     out_uint16_le(s, SEC_TAG_CLI_CHANNELS);
484 matthewc 432 out_uint16_le(s, g_num_channels * 12 + 8); /* length */
485     out_uint32_le(s, g_num_channels); /* number of virtual channels */
486     for (i = 0; i < g_num_channels; i++)
487 forsberg 412 {
488 matthewc 432 DEBUG_RDP5(("Requesting channel %s\n", g_channels[i].name));
489     out_uint8a(s, g_channels[i].name, 8);
490     out_uint32_be(s, g_channels[i].flags);
491 forsberg 412 }
492     }
493 forsberg 352
494 matty 10 s_mark_end(s);
495     }
496    
497     /* Parse a public key structure */
498 matty 25 static BOOL
499 astrand 64 sec_parse_public_key(STREAM s, uint8 ** modulus, uint8 ** exponent)
500 matty 10 {
501     uint32 magic, modulus_len;
502    
503     in_uint32_le(s, magic);
504     if (magic != SEC_RSA_MAGIC)
505     {
506 matty 30 error("RSA magic 0x%x\n", magic);
507 matty 10 return False;
508     }
509    
510     in_uint32_le(s, modulus_len);
511 matthewc 1237 modulus_len -= SEC_PADDING_SIZE;
512     if ((modulus_len < 64) || (modulus_len > SEC_MAX_MODULUS_SIZE))
513 matty 10 {
514 matthewc 1237 error("Bad server public key size (%u bits)\n", modulus_len*8);
515 matty 10 return False;
516     }
517    
518 matty 24 in_uint8s(s, 8); /* modulus_bits, unknown */
519 matty 10 in_uint8p(s, *exponent, SEC_EXPONENT_SIZE);
520 matthewc 1237 in_uint8p(s, *modulus, modulus_len);
521 matty 10 in_uint8s(s, SEC_PADDING_SIZE);
522 matthewc 1237 server_public_key_len = modulus_len;
523 matty 10
524     return s_check(s);
525     }
526    
527 forsberg 352 static BOOL
528     sec_parse_x509_key(X509 * cert)
529     {
530     EVP_PKEY *epk = NULL;
531     /* By some reason, Microsoft sets the OID of the Public RSA key to
532     the oid for "MD5 with RSA Encryption" instead of "RSA Encryption"
533    
534     Kudos to Richard Levitte for the following (. intiutive .)
535     lines of code that resets the OID and let's us extract the key. */
536     if (OBJ_obj2nid(cert->cert_info->key->algor->algorithm) == NID_md5WithRSAEncryption)
537     {
538     DEBUG_RDP5(("Re-setting algorithm type to RSA in server certificate\n"));
539 astrand 1199 ASN1_OBJECT_free(cert->cert_info->key->algor->algorithm);
540 forsberg 352 cert->cert_info->key->algor->algorithm = OBJ_nid2obj(NID_rsaEncryption);
541     }
542     epk = X509_get_pubkey(cert);
543     if (NULL == epk)
544     {
545     error("Failed to extract public key from certificate\n");
546     return False;
547     }
548    
549 astrand 1199 server_public_key = RSAPublicKey_dup((RSA *) epk->pkey.ptr);
550     EVP_PKEY_free(epk);
551    
552 matthewc 1237 server_public_key_len = RSA_size(server_public_key);
553     if ((server_public_key_len < 64) || (server_public_key_len > SEC_MAX_MODULUS_SIZE))
554     {
555     error("Bad server public key size (%u bits)\n", server_public_key_len*8);
556     return False;
557     }
558    
559 forsberg 352 return True;
560     }
561    
562    
563 matty 10 /* Parse a crypto information structure */
564 matty 25 static BOOL
565 astrand 64 sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
566 astrand 82 uint8 ** server_random, uint8 ** modulus, uint8 ** exponent)
567 matty 10 {
568     uint32 crypt_level, random_len, rsa_info_len;
569 matthewc 363 uint32 cacert_len, cert_len, flags;
570 forsberg 352 X509 *cacert, *server_cert;
571 matty 10 uint16 tag, length;
572     uint8 *next_tag, *end;
573    
574 matty 24 in_uint32_le(s, *rc4_key_size); /* 1 = 40-bit, 2 = 128-bit */
575     in_uint32_le(s, crypt_level); /* 1 = low, 2 = medium, 3 = high */
576 forsberg 352 if (crypt_level == 0) /* no encryption */
577 jsorg71 89 return False;
578 matty 10 in_uint32_le(s, random_len);
579     in_uint32_le(s, rsa_info_len);
580    
581     if (random_len != SEC_RANDOM_SIZE)
582     {
583 forsberg 352 error("random len %d, expected %d\n", random_len, SEC_RANDOM_SIZE);
584 matty 10 return False;
585     }
586    
587     in_uint8p(s, *server_random, random_len);
588    
589     /* RSA info */
590     end = s->p + rsa_info_len;
591     if (end > s->end)
592     return False;
593    
594 forsberg 412 in_uint32_le(s, flags); /* 1 = RDP4-style, 0x80000002 = X.509 */
595 matthewc 363 if (flags & 1)
596 forsberg 352 {
597     DEBUG_RDP5(("We're going for the RDP4-style encryption\n"));
598 matthewc 363 in_uint8s(s, 8); /* unknown */
599 matty 10
600 forsberg 352 while (s->p < end)
601     {
602     in_uint16_le(s, tag);
603     in_uint16_le(s, length);
604    
605     next_tag = s->p + length;
606    
607     switch (tag)
608     {
609     case SEC_TAG_PUBKEY:
610     if (!sec_parse_public_key(s, modulus, exponent))
611     return False;
612     DEBUG_RDP5(("Got Public key, RDP4-style\n"));
613    
614     break;
615    
616     case SEC_TAG_KEYSIG:
617     /* Is this a Microsoft key that we just got? */
618     /* Care factor: zero! */
619     /* Actually, it would probably be a good idea to check if the public key is signed with this key, and then store this
620     key as a known key of the hostname. This would prevent some MITM-attacks. */
621     break;
622    
623     default:
624     unimpl("crypt tag 0x%x\n", tag);
625     }
626    
627     s->p = next_tag;
628     }
629     }
630 matthewc 363 else
631 matty 10 {
632 stargo 557 uint32 certcount;
633    
634 forsberg 352 DEBUG_RDP5(("We're going for the RDP5-style encryption\n"));
635 astrand 580 in_uint32_le(s, certcount); /* Number of certificates */
636 matty 10
637 astrand 580 if (certcount < 2)
638 stargo 557 {
639     error("Server didn't send enough X509 certificates\n");
640     return False;
641     }
642    
643 astrand 580 for (; certcount > 2; certcount--)
644     { /* ignore all the certificates between the root and the signing CA */
645 stargo 557 uint32 ignorelen;
646     X509 *ignorecert;
647    
648     DEBUG_RDP5(("Ignored certs left: %d\n", certcount));
649    
650     in_uint32_le(s, ignorelen);
651     DEBUG_RDP5(("Ignored Certificate length is %d\n", ignorelen));
652     ignorecert = d2i_X509(NULL, &(s->p), ignorelen);
653    
654 astrand 580 if (ignorecert == NULL)
655     { /* XXX: error out? */
656 stargo 557 DEBUG_RDP5(("got a bad cert: this will probably screw up the rest of the communication\n"));
657     }
658    
659     #ifdef WITH_DEBUG_RDP5
660 astrand 580 DEBUG_RDP5(("cert #%d (ignored):\n", certcount));
661 stargo 557 X509_print_fp(stdout, ignorecert);
662     #endif
663     }
664    
665 forsberg 352 /* Do da funky X.509 stuffy
666 matty 10
667 forsberg 352 "How did I find out about this? I looked up and saw a
668     bright light and when I came to I had a scar on my forehead
669     and knew about X.500"
670     - Peter Gutman in a early version of
671     http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
672     */
673    
674     in_uint32_le(s, cacert_len);
675 forsberg 419 DEBUG_RDP5(("CA Certificate length is %d\n", cacert_len));
676 forsberg 352 cacert = d2i_X509(NULL, &(s->p), cacert_len);
677     /* Note: We don't need to move s->p here - d2i_X509 is
678     "kind" enough to do it for us */
679     if (NULL == cacert)
680 matty 10 {
681 forsberg 352 error("Couldn't load CA Certificate from server\n");
682     return False;
683     }
684 matty 10
685 forsberg 352 /* Currently, we don't use the CA Certificate.
686     FIXME:
687     *) Verify the server certificate (server_cert) with the
688     CA certificate.
689     *) Store the CA Certificate with the hostname of the
690     server we are connecting to as key, and compare it
691     when we connect the next time, in order to prevent
692     MITM-attacks.
693     */
694 matty 10
695 astrand 1199 X509_free(cacert);
696    
697 forsberg 352 in_uint32_le(s, cert_len);
698 forsberg 419 DEBUG_RDP5(("Certificate length is %d\n", cert_len));
699 forsberg 352 server_cert = d2i_X509(NULL, &(s->p), cert_len);
700     if (NULL == server_cert)
701     {
702     error("Couldn't load Certificate from server\n");
703     return False;
704     }
705 matty 10
706 forsberg 352 in_uint8s(s, 16); /* Padding */
707    
708     /* Note: Verifying the server certificate must be done here,
709     before sec_parse_public_key since we'll have to apply
710     serious violence to the key after this */
711    
712     if (!sec_parse_x509_key(server_cert))
713     {
714     DEBUG_RDP5(("Didn't parse X509 correctly\n"));
715 astrand 1199 X509_free(server_cert);
716 forsberg 352 return False;
717 matty 10 }
718 astrand 1199 X509_free(server_cert);
719 forsberg 352 return True; /* There's some garbage here we don't care about */
720 matty 10 }
721     return s_check_end(s);
722     }
723    
724     /* Process crypto information blob */
725 matty 25 static void
726     sec_process_crypt_info(STREAM s)
727 matty 10 {
728     uint8 *server_random, *modulus, *exponent;
729     uint8 client_random[SEC_RANDOM_SIZE];
730     uint32 rc4_key_size;
731    
732 astrand 82 if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random, &modulus, &exponent))
733 forsberg 352 {
734     DEBUG(("Failed to parse crypt info\n"));
735 matty 10 return;
736 forsberg 352 }
737 matty 10
738 forsberg 352 DEBUG(("Generating client random\n"));
739 matthewc 1237 generate_random(client_random);
740 forsberg 377
741 forsberg 352 if (NULL != server_public_key)
742     { /* Which means we should use
743     RDP5-style encryption */
744 matthewc 1237 uint8 inr[SEC_MAX_MODULUS_SIZE];
745     uint32 padding_len = server_public_key_len - SEC_RANDOM_SIZE;
746 forsberg 352
747 matthewc 1237 /* This is what the MS client do: */
748     memset(inr, 0, padding_len);
749     /* *ARIGL!* Plaintext attack, anyone?
750     I tried doing:
751     generate_random(inr);
752     ..but that generates connection errors now and then (yes,
753     "now and then". Something like 0 to 3 attempts needed before a
754     successful connection. Nice. Not!
755     */
756     memcpy(inr + padding_len, client_random, SEC_RANDOM_SIZE);
757     reverse(inr + padding_len, SEC_RANDOM_SIZE);
758 forsberg 352
759 matthewc 1237 RSA_public_encrypt(server_public_key_len,
760 forsberg 352 inr, sec_crypted_random, server_public_key, RSA_NO_PADDING);
761    
762 matthewc 1237 reverse(sec_crypted_random, server_public_key_len);
763 forsberg 352
764 astrand 1199 RSA_free(server_public_key);
765     server_public_key = NULL;
766 forsberg 352 }
767     else
768     { /* RDP4-style encryption */
769     sec_rsa_encrypt(sec_crypted_random,
770 matthewc 1237 client_random, SEC_RANDOM_SIZE, server_public_key_len, modulus, exponent);
771 forsberg 352 }
772 matty 10 sec_generate_keys(client_random, server_random, rc4_key_size);
773     }
774    
775 forsberg 352
776     /* Process SRV_INFO, find RDP version supported by server */
777     static void
778     sec_process_srv_info(STREAM s)
779     {
780 jsorg71 438 in_uint16_le(s, g_server_rdp_version);
781     DEBUG_RDP5(("Server RDP version is %d\n", g_server_rdp_version));
782     if (1 == g_server_rdp_version)
783 n-ki 677 {
784 jsorg71 438 g_use_rdp5 = 0;
785 astrand 1042 g_server_depth = 8;
786 n-ki 677 }
787 forsberg 352 }
788    
789    
790 matty 10 /* Process connect response data blob */
791 forsberg 352 void
792 matty 25 sec_process_mcs_data(STREAM s)
793 matty 10 {
794     uint16 tag, length;
795     uint8 *next_tag;
796 jsorg71 90 uint8 len;
797 matty 10
798 matthewc 642 in_uint8s(s, 21); /* header (T.124 ConferenceCreateResponse) */
799 jsorg71 90 in_uint8(s, len);
800     if (len & 0x80)
801     in_uint8(s, len);
802 matty 10
803     while (s->p < s->end)
804     {
805     in_uint16_le(s, tag);
806     in_uint16_le(s, length);
807    
808     if (length <= 4)
809     return;
810    
811     next_tag = s->p + length - 4;
812    
813     switch (tag)
814     {
815     case SEC_TAG_SRV_INFO:
816 forsberg 352 sec_process_srv_info(s);
817     break;
818    
819 matthewc 432 case SEC_TAG_SRV_CRYPT:
820     sec_process_crypt_info(s);
821     break;
822    
823     case SEC_TAG_SRV_CHANNELS:
824 forsberg 419 /* FIXME: We should parse this information and
825     use it to map RDP5 channels to MCS
826 astrand 435 channels */
827 matty 10 break;
828    
829     default:
830 matty 30 unimpl("response tag 0x%x\n", tag);
831 matty 10 }
832    
833     s->p = next_tag;
834     }
835     }
836    
837     /* Receive secure transport packet */
838 matty 25 STREAM
839 jsorg71 733 sec_recv(uint8 * rdpver)
840 matty 10 {
841     uint32 sec_flags;
842 forsberg 352 uint16 channel;
843 matty 10 STREAM s;
844    
845 jsorg71 733 while ((s = mcs_recv(&channel, rdpver)) != NULL)
846 matty 10 {
847 jsorg71 733 if (rdpver != NULL)
848     {
849     if (*rdpver != 3)
850     {
851     if (*rdpver & 0x80)
852     {
853     in_uint8s(s, 8); /* signature */
854     sec_decrypt(s->p, s->end - s->p);
855     }
856     return s;
857     }
858     }
859 jsorg71 437 if (g_encryption || !g_licence_issued)
860 matty 10 {
861 matty 28 in_uint32_le(s, sec_flags);
862 matty 10
863 matthewc 432 if (sec_flags & SEC_ENCRYPT)
864     {
865     in_uint8s(s, 8); /* signature */
866     sec_decrypt(s->p, s->end - s->p);
867     }
868    
869 matty 28 if (sec_flags & SEC_LICENCE_NEG)
870     {
871     licence_process(s);
872     continue;
873     }
874 astrand 977
875     if (sec_flags & 0x0400) /* SEC_REDIRECT_ENCRYPT */
876     {
877     uint8 swapbyte;
878    
879     in_uint8s(s, 8); /* signature */
880     sec_decrypt(s->p, s->end - s->p);
881    
882     /* Check for a redirect packet, starts with 00 04 */
883     if (s->p[0] == 0 && s->p[1] == 4)
884     {
885     /* for some reason the PDU and the length seem to be swapped.
886     This isn't good, but we're going to do a byte for byte
887     swap. So the first foure value appear as: 00 04 XX YY,
888     where XX YY is the little endian length. We're going to
889     use 04 00 as the PDU type, so after our swap this will look
890     like: XX YY 04 00 */
891     swapbyte = s->p[0];
892     s->p[0] = s->p[2];
893     s->p[2] = swapbyte;
894    
895     swapbyte = s->p[1];
896     s->p[1] = s->p[3];
897     s->p[3] = swapbyte;
898    
899     swapbyte = s->p[2];
900     s->p[2] = s->p[3];
901     s->p[3] = swapbyte;
902     }
903     #ifdef WITH_DEBUG
904     /* warning! this debug statement will show passwords in the clear! */
905     hexdump(s->p, s->end - s->p);
906     #endif
907     }
908    
909 matty 10 }
910    
911 matthewc 432 if (channel != MCS_GLOBAL_CHANNEL)
912 forsberg 352 {
913 matthewc 432 channel_process(s, channel);
914 jsorg71 779 *rdpver = 0xff;
915     return s;
916 forsberg 352 }
917    
918 matthewc 432 return s;
919 matty 10 }
920    
921     return NULL;
922     }
923    
924     /* Establish a secure connection */
925 matty 25 BOOL
926 forsberg 352 sec_connect(char *server, char *username)
927 matty 10 {
928     struct stream mcs_data;
929    
930     /* We exchange some RDP data during the MCS-Connect */
931     mcs_data.size = 512;
932 forsberg 412 mcs_data.p = mcs_data.data = (uint8 *) xmalloc(mcs_data.size);
933 matty 10 sec_out_mcs_data(&mcs_data);
934    
935 forsberg 352 if (!mcs_connect(server, &mcs_data, username))
936 matty 10 return False;
937    
938 astrand 540 /* sec_process_mcs_data(&mcs_data); */
939 jsorg71 437 if (g_encryption)
940 matty 28 sec_establish_key();
941 matthewc 218 xfree(mcs_data.data);
942 matty 10 return True;
943     }
944    
945 astrand 977 /* Establish a secure connection */
946     BOOL
947     sec_reconnect(char *server)
948     {
949     struct stream mcs_data;
950    
951     /* We exchange some RDP data during the MCS-Connect */
952     mcs_data.size = 512;
953     mcs_data.p = mcs_data.data = (uint8 *) xmalloc(mcs_data.size);
954     sec_out_mcs_data(&mcs_data);
955    
956     if (!mcs_reconnect(server, &mcs_data))
957     return False;
958    
959     /* sec_process_mcs_data(&mcs_data); */
960     if (g_encryption)
961     sec_establish_key();
962     xfree(mcs_data.data);
963     return True;
964     }
965    
966 matty 10 /* Disconnect a connection */
967 matty 25 void
968 matthewc 192 sec_disconnect(void)
969 matty 10 {
970     mcs_disconnect();
971     }
972 astrand 977
973     /* reset the state of the sec layer */
974     void
975     sec_reset_state(void)
976     {
977     g_server_rdp_version = 0;
978     sec_encrypt_use_count = 0;
979     sec_decrypt_use_count = 0;
980     mcs_reset_state();
981     }

  ViewVC Help
Powered by ViewVC 1.1.26