/[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 540 - (hide annotations)
Fri Oct 31 20:34:26 2003 UTC (20 years, 6 months ago) by astrand
File MIME type: text/plain
File size: 20460 byte(s)
Replaced C++ comments with C-style

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

  ViewVC Help
Powered by ViewVC 1.1.26