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

  ViewVC Help
Powered by ViewVC 1.1.26