/[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 377 - (hide annotations)
Thu May 22 08:37:57 2003 UTC (21 years ago) by forsberg
File MIME type: text/plain
File size: 19560 byte(s)
Set the first half of the client random to zeros instead of randomness.

Setting it to randomness seems to create random(!) connection errors. Bah!

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

  ViewVC Help
Powered by ViewVC 1.1.26