/[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 1239 - (hide annotations)
Wed Jun 21 14:40:02 2006 UTC (17 years, 11 months ago) by astrand
File MIME type: text/plain
File size: 24533 byte(s)
Indent fixes

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 astrand 1239 sec_rsa_encrypt(uint8 * out, uint8 * in, int len, uint32 modulus_size, uint8 * modulus,
302     uint8 * exponent)
303 matty 10 {
304 matthewc 295 BN_CTX *ctx;
305 matty 32 BIGNUM mod, exp, x, y;
306 matthewc 1237 uint8 inr[SEC_MAX_MODULUS_SIZE];
307 matty 32 int outlen;
308 matty 10
309 matthewc 1237 reverse(modulus, modulus_size);
310 matty 32 reverse(exponent, SEC_EXPONENT_SIZE);
311     memcpy(inr, in, len);
312     reverse(inr, len);
313 matty 10
314 matthewc 295 ctx = BN_CTX_new();
315 matty 32 BN_init(&mod);
316     BN_init(&exp);
317     BN_init(&x);
318     BN_init(&y);
319    
320 matthewc 1237 BN_bin2bn(modulus, modulus_size, &mod);
321 matty 32 BN_bin2bn(exponent, SEC_EXPONENT_SIZE, &exp);
322     BN_bin2bn(inr, len, &x);
323 matthewc 295 BN_mod_exp(&y, &x, &exp, &mod, ctx);
324 matty 32 outlen = BN_bn2bin(&y, out);
325     reverse(out, outlen);
326 matthewc 1237 if (outlen < modulus_size)
327     memset(out + outlen, 0, modulus_size - outlen);
328 matty 32
329     BN_free(&y);
330     BN_clear_free(&x);
331     BN_free(&exp);
332     BN_free(&mod);
333 matthewc 295 BN_CTX_free(ctx);
334 matty 10 }
335    
336     /* Initialise secure transport packet */
337 matty 25 STREAM
338     sec_init(uint32 flags, int maxlen)
339 matty 10 {
340     int hdrlen;
341     STREAM s;
342    
343 jsorg71 380 if (!g_licence_issued)
344 matty 28 hdrlen = (flags & SEC_ENCRYPT) ? 12 : 4;
345     else
346     hdrlen = (flags & SEC_ENCRYPT) ? 12 : 0;
347 matty 24 s = mcs_init(maxlen + hdrlen);
348 matty 10 s_push_layer(s, sec_hdr, hdrlen);
349    
350     return s;
351     }
352    
353 forsberg 412 /* Transmit secure transport packet over specified channel */
354 matty 25 void
355 forsberg 412 sec_send_to_channel(STREAM s, uint32 flags, uint16 channel)
356 matty 10 {
357     int datalen;
358    
359     s_pop_layer(s, sec_hdr);
360 jsorg71 380 if (!g_licence_issued || (flags & SEC_ENCRYPT))
361 matty 28 out_uint32_le(s, flags);
362 matty 10
363     if (flags & SEC_ENCRYPT)
364     {
365     flags &= ~SEC_ENCRYPT;
366     datalen = s->end - s->p - 8;
367    
368 matty 30 #if WITH_DEBUG
369     DEBUG(("Sending encrypted packet:\n"));
370 matty 24 hexdump(s->p + 8, datalen);
371 matty 10 #endif
372    
373 astrand 82 sec_sign(s->p, 8, sec_sign_key, rc4_key_len, s->p + 8, datalen);
374 matty 24 sec_encrypt(s->p + 8, datalen);
375 matty 10 }
376    
377 forsberg 412 mcs_send_to_channel(s, channel);
378 matty 10 }
379    
380 forsberg 412 /* Transmit secure transport packet */
381    
382     void
383     sec_send(STREAM s, uint32 flags)
384     {
385     sec_send_to_channel(s, flags, MCS_GLOBAL_CHANNEL);
386     }
387    
388    
389 matty 10 /* Transfer the client random to the server */
390 matty 25 static void
391 matthewc 192 sec_establish_key(void)
392 matty 10 {
393 matthewc 1237 uint32 length = server_public_key_len + SEC_PADDING_SIZE;
394 matty 10 uint32 flags = SEC_CLIENT_RANDOM;
395     STREAM s;
396    
397 astrand 1239 s = sec_init(flags, length + 4);
398 matty 10
399     out_uint32_le(s, length);
400 matthewc 1237 out_uint8p(s, sec_crypted_random, server_public_key_len);
401 matty 10 out_uint8s(s, SEC_PADDING_SIZE);
402    
403     s_mark_end(s);
404     sec_send(s, flags);
405     }
406    
407     /* Output connect initial data blob */
408 matty 25 static void
409     sec_out_mcs_data(STREAM s)
410 matty 10 {
411 jsorg71 710 int hostlen = 2 * strlen(g_hostname);
412 matthewc 432 int length = 158 + 76 + 12 + 4;
413     unsigned int i;
414 astrand 101
415 matthewc 432 if (g_num_channels > 0)
416 astrand 435 length += g_num_channels * 12 + 8;
417 forsberg 412
418 jsorg71 88 if (hostlen > 30)
419     hostlen = 30;
420 matty 10
421 matthewc 642 /* Generic Conference Control (T.124) ConferenceCreateRequest */
422     out_uint16_be(s, 5);
423 matty 10 out_uint16_be(s, 0x14);
424     out_uint8(s, 0x7c);
425     out_uint16_be(s, 1);
426    
427 forsberg 352 out_uint16_be(s, (length | 0x8000)); /* remaining length */
428 matty 10
429     out_uint16_be(s, 8); /* length? */
430     out_uint16_be(s, 16);
431     out_uint8(s, 0);
432     out_uint16_le(s, 0xc001);
433     out_uint8(s, 0);
434    
435 matthewc 642 out_uint32_le(s, 0x61637544); /* OEM ID: "Duca", as in Ducati. */
436 forsberg 352 out_uint16_be(s, ((length - 14) | 0x8000)); /* remaining length */
437 matty 10
438     /* Client information */
439     out_uint16_le(s, SEC_TAG_CLI_INFO);
440 forsberg 352 out_uint16_le(s, 212); /* length */
441 jsorg71 438 out_uint16_le(s, g_use_rdp5 ? 4 : 1); /* RDP version. 1 == RDP4, 4 == RDP5. */
442 matty 10 out_uint16_le(s, 8);
443 jsorg71 447 out_uint16_le(s, g_width);
444     out_uint16_le(s, g_height);
445 matty 10 out_uint16_le(s, 0xca01);
446     out_uint16_le(s, 0xaa03);
447 jsorg71 710 out_uint32_le(s, g_keylayout);
448 forsberg 352 out_uint32_le(s, 2600); /* Client build. We are now 2600 compatible :-) */
449 matty 10
450     /* Unicode name of client, padded to 32 bytes */
451 jsorg71 710 rdp_out_unistr(s, g_hostname, hostlen);
452 matty 24 out_uint8s(s, 30 - hostlen);
453 matty 10
454 astrand 966 /* See
455     http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wceddk40/html/cxtsksupportingremotedesktopprotocol.asp */
456 astrand 964 out_uint32_le(s, g_keyboard_type);
457     out_uint32_le(s, g_keyboard_subtype);
458     out_uint32_le(s, g_keyboard_functionkeys);
459 matty 24 out_uint8s(s, 64); /* reserved? 4 + 12 doublewords */
460 n-ki 677 out_uint16_le(s, 0xca01); /* colour depth? */
461 matthewc 365 out_uint16_le(s, 1);
462 matty 10
463 forsberg 352 out_uint32(s, 0);
464 astrand 1042 out_uint8(s, g_server_depth);
465 forsberg 357 out_uint16_le(s, 0x0700);
466     out_uint8(s, 0);
467 forsberg 352 out_uint32_le(s, 1);
468     out_uint8s(s, 64); /* End of client info */
469    
470     out_uint16_le(s, SEC_TAG_CLI_4);
471     out_uint16_le(s, 12);
472 matthewc 482 out_uint32_le(s, g_console_session ? 0xb : 9);
473 matthewc 365 out_uint32(s, 0);
474 forsberg 352
475 matty 10 /* Client encryption settings */
476     out_uint16_le(s, SEC_TAG_CLI_CRYPT);
477 forsberg 352 out_uint16_le(s, 12); /* length */
478 jsorg71 437 out_uint32_le(s, g_encryption ? 0x3 : 0); /* encryption supported, 128-bit supported */
479 matthewc 365 out_uint32(s, 0); /* Unknown */
480 forsberg 352
481 matthewc 432 DEBUG_RDP5(("g_num_channels is %d\n", g_num_channels));
482     if (g_num_channels > 0)
483 forsberg 412 {
484     out_uint16_le(s, SEC_TAG_CLI_CHANNELS);
485 matthewc 432 out_uint16_le(s, g_num_channels * 12 + 8); /* length */
486     out_uint32_le(s, g_num_channels); /* number of virtual channels */
487     for (i = 0; i < g_num_channels; i++)
488 forsberg 412 {
489 matthewc 432 DEBUG_RDP5(("Requesting channel %s\n", g_channels[i].name));
490     out_uint8a(s, g_channels[i].name, 8);
491     out_uint32_be(s, g_channels[i].flags);
492 forsberg 412 }
493     }
494 forsberg 352
495 matty 10 s_mark_end(s);
496     }
497    
498     /* Parse a public key structure */
499 matty 25 static BOOL
500 astrand 64 sec_parse_public_key(STREAM s, uint8 ** modulus, uint8 ** exponent)
501 matty 10 {
502     uint32 magic, modulus_len;
503    
504     in_uint32_le(s, magic);
505     if (magic != SEC_RSA_MAGIC)
506     {
507 matty 30 error("RSA magic 0x%x\n", magic);
508 matty 10 return False;
509     }
510    
511     in_uint32_le(s, modulus_len);
512 matthewc 1237 modulus_len -= SEC_PADDING_SIZE;
513     if ((modulus_len < 64) || (modulus_len > SEC_MAX_MODULUS_SIZE))
514 matty 10 {
515 astrand 1239 error("Bad server public key size (%u bits)\n", modulus_len * 8);
516 matty 10 return False;
517     }
518    
519 matty 24 in_uint8s(s, 8); /* modulus_bits, unknown */
520 matty 10 in_uint8p(s, *exponent, SEC_EXPONENT_SIZE);
521 matthewc 1237 in_uint8p(s, *modulus, modulus_len);
522 matty 10 in_uint8s(s, SEC_PADDING_SIZE);
523 matthewc 1237 server_public_key_len = modulus_len;
524 matty 10
525     return s_check(s);
526     }
527    
528 forsberg 352 static BOOL
529     sec_parse_x509_key(X509 * cert)
530     {
531     EVP_PKEY *epk = NULL;
532     /* By some reason, Microsoft sets the OID of the Public RSA key to
533     the oid for "MD5 with RSA Encryption" instead of "RSA Encryption"
534    
535     Kudos to Richard Levitte for the following (. intiutive .)
536     lines of code that resets the OID and let's us extract the key. */
537     if (OBJ_obj2nid(cert->cert_info->key->algor->algorithm) == NID_md5WithRSAEncryption)
538     {
539     DEBUG_RDP5(("Re-setting algorithm type to RSA in server certificate\n"));
540 astrand 1199 ASN1_OBJECT_free(cert->cert_info->key->algor->algorithm);
541 forsberg 352 cert->cert_info->key->algor->algorithm = OBJ_nid2obj(NID_rsaEncryption);
542     }
543     epk = X509_get_pubkey(cert);
544     if (NULL == epk)
545     {
546     error("Failed to extract public key from certificate\n");
547     return False;
548     }
549    
550 astrand 1199 server_public_key = RSAPublicKey_dup((RSA *) epk->pkey.ptr);
551     EVP_PKEY_free(epk);
552    
553 matthewc 1237 server_public_key_len = RSA_size(server_public_key);
554     if ((server_public_key_len < 64) || (server_public_key_len > SEC_MAX_MODULUS_SIZE))
555     {
556 astrand 1239 error("Bad server public key size (%u bits)\n", server_public_key_len * 8);
557 matthewc 1237 return False;
558     }
559    
560 forsberg 352 return True;
561     }
562    
563    
564 matty 10 /* Parse a crypto information structure */
565 matty 25 static BOOL
566 astrand 64 sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
567 astrand 82 uint8 ** server_random, uint8 ** modulus, uint8 ** exponent)
568 matty 10 {
569     uint32 crypt_level, random_len, rsa_info_len;
570 matthewc 363 uint32 cacert_len, cert_len, flags;
571 forsberg 352 X509 *cacert, *server_cert;
572 matty 10 uint16 tag, length;
573     uint8 *next_tag, *end;
574    
575 matty 24 in_uint32_le(s, *rc4_key_size); /* 1 = 40-bit, 2 = 128-bit */
576     in_uint32_le(s, crypt_level); /* 1 = low, 2 = medium, 3 = high */
577 forsberg 352 if (crypt_level == 0) /* no encryption */
578 jsorg71 89 return False;
579 matty 10 in_uint32_le(s, random_len);
580     in_uint32_le(s, rsa_info_len);
581    
582     if (random_len != SEC_RANDOM_SIZE)
583     {
584 forsberg 352 error("random len %d, expected %d\n", random_len, SEC_RANDOM_SIZE);
585 matty 10 return False;
586     }
587    
588     in_uint8p(s, *server_random, random_len);
589    
590     /* RSA info */
591     end = s->p + rsa_info_len;
592     if (end > s->end)
593     return False;
594    
595 forsberg 412 in_uint32_le(s, flags); /* 1 = RDP4-style, 0x80000002 = X.509 */
596 matthewc 363 if (flags & 1)
597 forsberg 352 {
598     DEBUG_RDP5(("We're going for the RDP4-style encryption\n"));
599 matthewc 363 in_uint8s(s, 8); /* unknown */
600 matty 10
601 forsberg 352 while (s->p < end)
602     {
603     in_uint16_le(s, tag);
604     in_uint16_le(s, length);
605    
606     next_tag = s->p + length;
607    
608     switch (tag)
609     {
610     case SEC_TAG_PUBKEY:
611     if (!sec_parse_public_key(s, modulus, exponent))
612     return False;
613     DEBUG_RDP5(("Got Public key, RDP4-style\n"));
614    
615     break;
616    
617     case SEC_TAG_KEYSIG:
618     /* Is this a Microsoft key that we just got? */
619     /* Care factor: zero! */
620     /* Actually, it would probably be a good idea to check if the public key is signed with this key, and then store this
621     key as a known key of the hostname. This would prevent some MITM-attacks. */
622     break;
623    
624     default:
625     unimpl("crypt tag 0x%x\n", tag);
626     }
627    
628     s->p = next_tag;
629     }
630     }
631 matthewc 363 else
632 matty 10 {
633 stargo 557 uint32 certcount;
634    
635 forsberg 352 DEBUG_RDP5(("We're going for the RDP5-style encryption\n"));
636 astrand 580 in_uint32_le(s, certcount); /* Number of certificates */
637 matty 10
638 astrand 580 if (certcount < 2)
639 stargo 557 {
640     error("Server didn't send enough X509 certificates\n");
641     return False;
642     }
643    
644 astrand 580 for (; certcount > 2; certcount--)
645     { /* ignore all the certificates between the root and the signing CA */
646 stargo 557 uint32 ignorelen;
647     X509 *ignorecert;
648    
649     DEBUG_RDP5(("Ignored certs left: %d\n", certcount));
650    
651     in_uint32_le(s, ignorelen);
652     DEBUG_RDP5(("Ignored Certificate length is %d\n", ignorelen));
653     ignorecert = d2i_X509(NULL, &(s->p), ignorelen);
654    
655 astrand 580 if (ignorecert == NULL)
656     { /* XXX: error out? */
657 stargo 557 DEBUG_RDP5(("got a bad cert: this will probably screw up the rest of the communication\n"));
658     }
659    
660     #ifdef WITH_DEBUG_RDP5
661 astrand 580 DEBUG_RDP5(("cert #%d (ignored):\n", certcount));
662 stargo 557 X509_print_fp(stdout, ignorecert);
663     #endif
664     }
665    
666 forsberg 352 /* Do da funky X.509 stuffy
667 matty 10
668 forsberg 352 "How did I find out about this? I looked up and saw a
669     bright light and when I came to I had a scar on my forehead
670     and knew about X.500"
671     - Peter Gutman in a early version of
672     http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
673     */
674    
675     in_uint32_le(s, cacert_len);
676 forsberg 419 DEBUG_RDP5(("CA Certificate length is %d\n", cacert_len));
677 forsberg 352 cacert = d2i_X509(NULL, &(s->p), cacert_len);
678     /* Note: We don't need to move s->p here - d2i_X509 is
679     "kind" enough to do it for us */
680     if (NULL == cacert)
681 matty 10 {
682 forsberg 352 error("Couldn't load CA Certificate from server\n");
683     return False;
684     }
685 matty 10
686 forsberg 352 /* Currently, we don't use the CA Certificate.
687     FIXME:
688     *) Verify the server certificate (server_cert) with the
689     CA certificate.
690     *) Store the CA Certificate with the hostname of the
691     server we are connecting to as key, and compare it
692     when we connect the next time, in order to prevent
693     MITM-attacks.
694     */
695 matty 10
696 astrand 1199 X509_free(cacert);
697    
698 forsberg 352 in_uint32_le(s, cert_len);
699 forsberg 419 DEBUG_RDP5(("Certificate length is %d\n", cert_len));
700 forsberg 352 server_cert = d2i_X509(NULL, &(s->p), cert_len);
701     if (NULL == server_cert)
702     {
703     error("Couldn't load Certificate from server\n");
704     return False;
705     }
706 matty 10
707 forsberg 352 in_uint8s(s, 16); /* Padding */
708    
709     /* Note: Verifying the server certificate must be done here,
710     before sec_parse_public_key since we'll have to apply
711     serious violence to the key after this */
712    
713     if (!sec_parse_x509_key(server_cert))
714     {
715     DEBUG_RDP5(("Didn't parse X509 correctly\n"));
716 astrand 1199 X509_free(server_cert);
717 forsberg 352 return False;
718 matty 10 }
719 astrand 1199 X509_free(server_cert);
720 forsberg 352 return True; /* There's some garbage here we don't care about */
721 matty 10 }
722     return s_check_end(s);
723     }
724    
725     /* Process crypto information blob */
726 matty 25 static void
727     sec_process_crypt_info(STREAM s)
728 matty 10 {
729     uint8 *server_random, *modulus, *exponent;
730     uint8 client_random[SEC_RANDOM_SIZE];
731     uint32 rc4_key_size;
732    
733 astrand 82 if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random, &modulus, &exponent))
734 forsberg 352 {
735     DEBUG(("Failed to parse crypt info\n"));
736 matty 10 return;
737 forsberg 352 }
738 matty 10
739 forsberg 352 DEBUG(("Generating client random\n"));
740 matthewc 1237 generate_random(client_random);
741 forsberg 377
742 forsberg 352 if (NULL != server_public_key)
743     { /* Which means we should use
744     RDP5-style encryption */
745 matthewc 1237 uint8 inr[SEC_MAX_MODULUS_SIZE];
746     uint32 padding_len = server_public_key_len - SEC_RANDOM_SIZE;
747 forsberg 352
748 matthewc 1237 /* This is what the MS client do: */
749     memset(inr, 0, padding_len);
750     /* *ARIGL!* Plaintext attack, anyone?
751     I tried doing:
752 astrand 1239 generate_random(inr);
753     ..but that generates connection errors now and then (yes,
754     "now and then". Something like 0 to 3 attempts needed before a
755     successful connection. Nice. Not!
756 matthewc 1237 */
757     memcpy(inr + padding_len, client_random, SEC_RANDOM_SIZE);
758     reverse(inr + padding_len, SEC_RANDOM_SIZE);
759 forsberg 352
760 matthewc 1237 RSA_public_encrypt(server_public_key_len,
761 forsberg 352 inr, sec_crypted_random, server_public_key, RSA_NO_PADDING);
762    
763 matthewc 1237 reverse(sec_crypted_random, server_public_key_len);
764 forsberg 352
765 astrand 1199 RSA_free(server_public_key);
766     server_public_key = NULL;
767 forsberg 352 }
768     else
769     { /* RDP4-style encryption */
770     sec_rsa_encrypt(sec_crypted_random,
771 astrand 1239 client_random, SEC_RANDOM_SIZE, server_public_key_len, modulus,
772     exponent);
773 forsberg 352 }
774 matty 10 sec_generate_keys(client_random, server_random, rc4_key_size);
775     }
776    
777 forsberg 352
778     /* Process SRV_INFO, find RDP version supported by server */
779     static void
780     sec_process_srv_info(STREAM s)
781     {
782 jsorg71 438 in_uint16_le(s, g_server_rdp_version);
783     DEBUG_RDP5(("Server RDP version is %d\n", g_server_rdp_version));
784     if (1 == g_server_rdp_version)
785 n-ki 677 {
786 jsorg71 438 g_use_rdp5 = 0;
787 astrand 1042 g_server_depth = 8;
788 n-ki 677 }
789 forsberg 352 }
790    
791    
792 matty 10 /* Process connect response data blob */
793 forsberg 352 void
794 matty 25 sec_process_mcs_data(STREAM s)
795 matty 10 {
796     uint16 tag, length;
797     uint8 *next_tag;
798 jsorg71 90 uint8 len;
799 matty 10
800 matthewc 642 in_uint8s(s, 21); /* header (T.124 ConferenceCreateResponse) */
801 jsorg71 90 in_uint8(s, len);
802     if (len & 0x80)
803     in_uint8(s, len);
804 matty 10
805     while (s->p < s->end)
806     {
807     in_uint16_le(s, tag);
808     in_uint16_le(s, length);
809    
810     if (length <= 4)
811     return;
812    
813     next_tag = s->p + length - 4;
814    
815     switch (tag)
816     {
817     case SEC_TAG_SRV_INFO:
818 forsberg 352 sec_process_srv_info(s);
819     break;
820    
821 matthewc 432 case SEC_TAG_SRV_CRYPT:
822     sec_process_crypt_info(s);
823     break;
824    
825     case SEC_TAG_SRV_CHANNELS:
826 forsberg 419 /* FIXME: We should parse this information and
827     use it to map RDP5 channels to MCS
828 astrand 435 channels */
829 matty 10 break;
830    
831     default:
832 matty 30 unimpl("response tag 0x%x\n", tag);
833 matty 10 }
834    
835     s->p = next_tag;
836     }
837     }
838    
839     /* Receive secure transport packet */
840 matty 25 STREAM
841 jsorg71 733 sec_recv(uint8 * rdpver)
842 matty 10 {
843     uint32 sec_flags;
844 forsberg 352 uint16 channel;
845 matty 10 STREAM s;
846    
847 jsorg71 733 while ((s = mcs_recv(&channel, rdpver)) != NULL)
848 matty 10 {
849 jsorg71 733 if (rdpver != NULL)
850     {
851     if (*rdpver != 3)
852     {
853     if (*rdpver & 0x80)
854     {
855     in_uint8s(s, 8); /* signature */
856     sec_decrypt(s->p, s->end - s->p);
857     }
858     return s;
859     }
860     }
861 jsorg71 437 if (g_encryption || !g_licence_issued)
862 matty 10 {
863 matty 28 in_uint32_le(s, sec_flags);
864 matty 10
865 matthewc 432 if (sec_flags & SEC_ENCRYPT)
866     {
867     in_uint8s(s, 8); /* signature */
868     sec_decrypt(s->p, s->end - s->p);
869     }
870    
871 matty 28 if (sec_flags & SEC_LICENCE_NEG)
872     {
873     licence_process(s);
874     continue;
875     }
876 astrand 977
877     if (sec_flags & 0x0400) /* SEC_REDIRECT_ENCRYPT */
878     {
879     uint8 swapbyte;
880    
881     in_uint8s(s, 8); /* signature */
882     sec_decrypt(s->p, s->end - s->p);
883    
884     /* Check for a redirect packet, starts with 00 04 */
885     if (s->p[0] == 0 && s->p[1] == 4)
886     {
887     /* for some reason the PDU and the length seem to be swapped.
888     This isn't good, but we're going to do a byte for byte
889     swap. So the first foure value appear as: 00 04 XX YY,
890     where XX YY is the little endian length. We're going to
891     use 04 00 as the PDU type, so after our swap this will look
892     like: XX YY 04 00 */
893     swapbyte = s->p[0];
894     s->p[0] = s->p[2];
895     s->p[2] = swapbyte;
896    
897     swapbyte = s->p[1];
898     s->p[1] = s->p[3];
899     s->p[3] = swapbyte;
900    
901     swapbyte = s->p[2];
902     s->p[2] = s->p[3];
903     s->p[3] = swapbyte;
904     }
905     #ifdef WITH_DEBUG
906     /* warning! this debug statement will show passwords in the clear! */
907     hexdump(s->p, s->end - s->p);
908     #endif
909     }
910    
911 matty 10 }
912    
913 matthewc 432 if (channel != MCS_GLOBAL_CHANNEL)
914 forsberg 352 {
915 matthewc 432 channel_process(s, channel);
916 jsorg71 779 *rdpver = 0xff;
917     return s;
918 forsberg 352 }
919    
920 matthewc 432 return s;
921 matty 10 }
922    
923     return NULL;
924     }
925    
926     /* Establish a secure connection */
927 matty 25 BOOL
928 forsberg 352 sec_connect(char *server, char *username)
929 matty 10 {
930     struct stream mcs_data;
931    
932     /* We exchange some RDP data during the MCS-Connect */
933     mcs_data.size = 512;
934 forsberg 412 mcs_data.p = mcs_data.data = (uint8 *) xmalloc(mcs_data.size);
935 matty 10 sec_out_mcs_data(&mcs_data);
936    
937 forsberg 352 if (!mcs_connect(server, &mcs_data, username))
938 matty 10 return False;
939    
940 astrand 540 /* sec_process_mcs_data(&mcs_data); */
941 jsorg71 437 if (g_encryption)
942 matty 28 sec_establish_key();
943 matthewc 218 xfree(mcs_data.data);
944 matty 10 return True;
945     }
946    
947 astrand 977 /* Establish a secure connection */
948     BOOL
949     sec_reconnect(char *server)
950     {
951     struct stream mcs_data;
952    
953     /* We exchange some RDP data during the MCS-Connect */
954     mcs_data.size = 512;
955     mcs_data.p = mcs_data.data = (uint8 *) xmalloc(mcs_data.size);
956     sec_out_mcs_data(&mcs_data);
957    
958     if (!mcs_reconnect(server, &mcs_data))
959     return False;
960    
961     /* sec_process_mcs_data(&mcs_data); */
962     if (g_encryption)
963     sec_establish_key();
964     xfree(mcs_data.data);
965     return True;
966     }
967    
968 matty 10 /* Disconnect a connection */
969 matty 25 void
970 matthewc 192 sec_disconnect(void)
971 matty 10 {
972     mcs_disconnect();
973     }
974 astrand 977
975     /* reset the state of the sec layer */
976     void
977     sec_reset_state(void)
978     {
979     g_server_rdp_version = 0;
980     sec_encrypt_use_count = 0;
981     sec_decrypt_use_count = 0;
982     mcs_reset_state();
983     }

  ViewVC Help
Powered by ViewVC 1.1.26