/[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 740 - (hide annotations)
Sat Jul 31 13:07:41 2004 UTC (19 years, 9 months ago) by astrand
File MIME type: text/plain
File size: 21754 byte(s)
Now using Autoconf. Old OpenSSL files removed.

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

  ViewVC Help
Powered by ViewVC 1.1.26