/[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

Contents of /sourceforge.net/trunk/rdesktop/secure.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 89 - (show annotations)
Sun Aug 4 03:05:19 2002 UTC (21 years, 9 months ago) by jsorg71
File MIME type: text/plain
File size: 14114 byte(s)
exit sec_parse_crypt_info if crypt_level is 0 from up19-7-3

1 /*
2 rdesktop: A Remote Desktop Protocol client.
3 Protocol services - RDP encryption and licensing
4 Copyright (C) Matthew Chapman 1999-2001
5
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
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 #else
29 #include "crypto/rc4.h"
30 #include "crypto/md5.h"
31 #include "crypto/sha.h"
32 #include "crypto/bn.h"
33 #endif
34
35 extern char hostname[16];
36 extern int width;
37 extern int height;
38 extern int keylayout;
39 extern BOOL encryption;
40 extern BOOL licence_issued;
41
42 static int rc4_key_len;
43 static RC4_KEY rc4_decrypt_key;
44 static RC4_KEY rc4_encrypt_key;
45
46 static uint8 sec_sign_key[16];
47 static uint8 sec_decrypt_key[16];
48 static uint8 sec_encrypt_key[16];
49 static uint8 sec_decrypt_update_key[16];
50 static uint8 sec_encrypt_update_key[16];
51 static uint8 sec_crypted_random[SEC_MODULUS_SIZE];
52
53 /*
54 * General purpose 48-byte transformation, using two 32-byte salts (generally,
55 * a client and server salt) and a global salt value used for padding.
56 * Both SHA1 and MD5 algorithms are used.
57 */
58 void
59 sec_hash_48(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2, uint8 salt)
60 {
61 uint8 shasig[20];
62 uint8 pad[4];
63 SHA_CTX sha;
64 MD5_CTX md5;
65 int i;
66
67 for (i = 0; i < 3; i++)
68 {
69 memset(pad, salt + i, i + 1);
70
71 SHA1_Init(&sha);
72 SHA1_Update(&sha, pad, i + 1);
73 SHA1_Update(&sha, in, 48);
74 SHA1_Update(&sha, salt1, 32);
75 SHA1_Update(&sha, salt2, 32);
76 SHA1_Final(shasig, &sha);
77
78 MD5_Init(&md5);
79 MD5_Update(&md5, in, 48);
80 MD5_Update(&md5, shasig, 20);
81 MD5_Final(&out[i * 16], &md5);
82 }
83 }
84
85 /*
86 * Weaker 16-byte transformation, also using two 32-byte salts, but
87 * only using a single round of MD5.
88 */
89 void
90 sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2)
91 {
92 MD5_CTX md5;
93
94 MD5_Init(&md5);
95 MD5_Update(&md5, in, 16);
96 MD5_Update(&md5, salt1, 32);
97 MD5_Update(&md5, salt2, 32);
98 MD5_Final(out, &md5);
99 }
100
101 /* Reduce key entropy from 64 to 40 bits */
102 static void
103 sec_make_40bit(uint8 * key)
104 {
105 key[0] = 0xd1;
106 key[1] = 0x26;
107 key[2] = 0x9e;
108 }
109
110 /* Generate a session key and RC4 keys, given client and server randoms */
111 static void
112 sec_generate_keys(uint8 * client_key, uint8 * server_key, int rc4_key_size)
113 {
114 uint8 session_key[48];
115 uint8 temp_hash[48];
116 uint8 input[48];
117
118 /* Construct input data to hash */
119 memcpy(input, client_key, 24);
120 memcpy(input + 24, server_key, 24);
121
122 /* Generate session key - two rounds of sec_hash_48 */
123 sec_hash_48(temp_hash, input, client_key, server_key, 65);
124 sec_hash_48(session_key, temp_hash, client_key, server_key, 88);
125
126 /* Store first 16 bytes of session key, for generating signatures */
127 memcpy(sec_sign_key, session_key, 16);
128
129 /* Generate RC4 keys */
130 sec_hash_16(sec_decrypt_key, &session_key[16], client_key, server_key);
131 sec_hash_16(sec_encrypt_key, &session_key[32], client_key, server_key);
132
133 if (rc4_key_size == 1)
134 {
135 DEBUG(("40-bit encryption enabled\n"));
136 sec_make_40bit(sec_sign_key);
137 sec_make_40bit(sec_decrypt_key);
138 sec_make_40bit(sec_encrypt_key);
139 rc4_key_len = 8;
140 }
141 else
142 {
143 DEBUG(("128-bit encryption enabled\n"));
144 rc4_key_len = 16;
145 }
146
147 /* Save initial RC4 keys as update keys */
148 memcpy(sec_decrypt_update_key, sec_decrypt_key, 16);
149 memcpy(sec_encrypt_update_key, sec_encrypt_key, 16);
150
151 /* Initialise RC4 state arrays */
152 RC4_set_key(&rc4_decrypt_key, rc4_key_len, sec_decrypt_key);
153 RC4_set_key(&rc4_encrypt_key, rc4_key_len, sec_encrypt_key);
154 }
155
156 static uint8 pad_54[40] = {
157 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
158 54, 54, 54,
159 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
160 54, 54, 54
161 };
162
163 static uint8 pad_92[48] = {
164 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
165 92, 92, 92, 92, 92, 92, 92,
166 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
167 92, 92, 92, 92, 92, 92, 92
168 };
169
170 /* Output a uint32 into a buffer (little-endian) */
171 void
172 buf_out_uint32(uint8 * buffer, uint32 value)
173 {
174 buffer[0] = (value) & 0xff;
175 buffer[1] = (value >> 8) & 0xff;
176 buffer[2] = (value >> 16) & 0xff;
177 buffer[3] = (value >> 24) & 0xff;
178 }
179
180 /* Generate a signature hash, using a combination of SHA1 and MD5 */
181 void
182 sec_sign(uint8 * signature, int siglen, uint8 * session_key, int keylen, uint8 * data, int datalen)
183 {
184 uint8 shasig[20];
185 uint8 md5sig[16];
186 uint8 lenhdr[4];
187 SHA_CTX sha;
188 MD5_CTX md5;
189
190 buf_out_uint32(lenhdr, datalen);
191
192 SHA1_Init(&sha);
193 SHA1_Update(&sha, session_key, keylen);
194 SHA1_Update(&sha, pad_54, 40);
195 SHA1_Update(&sha, lenhdr, 4);
196 SHA1_Update(&sha, data, datalen);
197 SHA1_Final(shasig, &sha);
198
199 MD5_Init(&md5);
200 MD5_Update(&md5, session_key, keylen);
201 MD5_Update(&md5, pad_92, 48);
202 MD5_Update(&md5, shasig, 20);
203 MD5_Final(md5sig, &md5);
204
205 memcpy(signature, md5sig, siglen);
206 }
207
208 /* Update an encryption key - similar to the signing process */
209 static void
210 sec_update(uint8 * key, uint8 * update_key)
211 {
212 uint8 shasig[20];
213 SHA_CTX sha;
214 MD5_CTX md5;
215 RC4_KEY update;
216
217 SHA1_Init(&sha);
218 SHA1_Update(&sha, update_key, rc4_key_len);
219 SHA1_Update(&sha, pad_54, 40);
220 SHA1_Update(&sha, key, rc4_key_len);
221 SHA1_Final(shasig, &sha);
222
223 MD5_Init(&md5);
224 MD5_Update(&md5, update_key, rc4_key_len);
225 MD5_Update(&md5, pad_92, 48);
226 MD5_Update(&md5, shasig, 20);
227 MD5_Final(key, &md5);
228
229 RC4_set_key(&update, rc4_key_len, key);
230 RC4(&update, rc4_key_len, key, key);
231
232 if (rc4_key_len == 8)
233 sec_make_40bit(key);
234 }
235
236 /* Encrypt data using RC4 */
237 static void
238 sec_encrypt(uint8 * data, int length)
239 {
240 static int use_count;
241
242 if (use_count == 4096)
243 {
244 sec_update(sec_encrypt_key, sec_encrypt_update_key);
245 RC4_set_key(&rc4_encrypt_key, rc4_key_len, sec_encrypt_key);
246 use_count = 0;
247 }
248
249 RC4(&rc4_encrypt_key, length, data, data);
250 use_count++;
251 }
252
253 /* Decrypt data using RC4 */
254 static void
255 sec_decrypt(uint8 * data, int length)
256 {
257 static int use_count;
258
259 if (use_count == 4096)
260 {
261 sec_update(sec_decrypt_key, sec_decrypt_update_key);
262 RC4_set_key(&rc4_decrypt_key, rc4_key_len, sec_decrypt_key);
263 use_count = 0;
264 }
265
266 RC4(&rc4_decrypt_key, length, data, data);
267 use_count++;
268 }
269
270 static void
271 reverse(uint8 * p, int len)
272 {
273 int i, j;
274 uint8 temp;
275
276 for (i = 0, j = len - 1; i < j; i++, j--)
277 {
278 temp = p[i];
279 p[i] = p[j];
280 p[j] = temp;
281 }
282 }
283
284 /* Perform an RSA public key encryption operation */
285 static void
286 sec_rsa_encrypt(uint8 * out, uint8 * in, int len, uint8 * modulus, uint8 * exponent)
287 {
288 BN_CTX ctx;
289 BIGNUM mod, exp, x, y;
290 uint8 inr[SEC_MODULUS_SIZE];
291 int outlen;
292
293 reverse(modulus, SEC_MODULUS_SIZE);
294 reverse(exponent, SEC_EXPONENT_SIZE);
295 memcpy(inr, in, len);
296 reverse(inr, len);
297
298 BN_CTX_init(&ctx);
299 BN_init(&mod);
300 BN_init(&exp);
301 BN_init(&x);
302 BN_init(&y);
303
304 BN_bin2bn(modulus, SEC_MODULUS_SIZE, &mod);
305 BN_bin2bn(exponent, SEC_EXPONENT_SIZE, &exp);
306 BN_bin2bn(inr, len, &x);
307 BN_mod_exp(&y, &x, &exp, &mod, &ctx);
308 outlen = BN_bn2bin(&y, out);
309 reverse(out, outlen);
310 if (outlen < SEC_MODULUS_SIZE)
311 memset(out + outlen, 0, SEC_MODULUS_SIZE - outlen);
312
313 BN_free(&y);
314 BN_clear_free(&x);
315 BN_free(&exp);
316 BN_free(&mod);
317 BN_CTX_free(&ctx);
318 }
319
320 /* Initialise secure transport packet */
321 STREAM
322 sec_init(uint32 flags, int maxlen)
323 {
324 int hdrlen;
325 STREAM s;
326
327 if (!licence_issued)
328 hdrlen = (flags & SEC_ENCRYPT) ? 12 : 4;
329 else
330 hdrlen = (flags & SEC_ENCRYPT) ? 12 : 0;
331 s = mcs_init(maxlen + hdrlen);
332 s_push_layer(s, sec_hdr, hdrlen);
333
334 return s;
335 }
336
337 /* Transmit secure transport packet */
338 void
339 sec_send(STREAM s, uint32 flags)
340 {
341 int datalen;
342
343 s_pop_layer(s, sec_hdr);
344 if (!licence_issued || (flags & SEC_ENCRYPT))
345 out_uint32_le(s, flags);
346
347 if (flags & SEC_ENCRYPT)
348 {
349 flags &= ~SEC_ENCRYPT;
350 datalen = s->end - s->p - 8;
351
352 #if WITH_DEBUG
353 DEBUG(("Sending encrypted packet:\n"));
354 hexdump(s->p + 8, datalen);
355 #endif
356
357 sec_sign(s->p, 8, sec_sign_key, rc4_key_len, s->p + 8, datalen);
358 sec_encrypt(s->p + 8, datalen);
359 }
360
361 mcs_send(s);
362 }
363
364 /* Transfer the client random to the server */
365 static void
366 sec_establish_key()
367 {
368 uint32 length = SEC_MODULUS_SIZE + SEC_PADDING_SIZE;
369 uint32 flags = SEC_CLIENT_RANDOM;
370 STREAM s;
371
372 s = sec_init(flags, 76);
373
374 out_uint32_le(s, length);
375 out_uint8p(s, sec_crypted_random, SEC_MODULUS_SIZE);
376 out_uint8s(s, SEC_PADDING_SIZE);
377
378 s_mark_end(s);
379 sec_send(s, flags);
380 }
381
382 /* Output connect initial data blob */
383 static void
384 sec_out_mcs_data(STREAM s)
385 {
386 int hostlen = 2 * strlen(hostname);
387
388 if (hostlen > 30)
389 hostlen = 30;
390
391 out_uint16_be(s, 5); /* unknown */
392 out_uint16_be(s, 0x14);
393 out_uint8(s, 0x7c);
394 out_uint16_be(s, 1);
395
396 out_uint16_be(s, (158 | 0x8000)); /* remaining length */
397
398 out_uint16_be(s, 8); /* length? */
399 out_uint16_be(s, 16);
400 out_uint8(s, 0);
401 out_uint16_le(s, 0xc001);
402 out_uint8(s, 0);
403
404 out_uint32_le(s, 0x61637544); /* "Duca" ?! */
405 out_uint16_be(s, (144 | 0x8000)); /* remaining length */
406
407 /* Client information */
408 out_uint16_le(s, SEC_TAG_CLI_INFO);
409 out_uint16_le(s, 136); /* length */
410 out_uint16_le(s, 1);
411 out_uint16_le(s, 8);
412 out_uint16_le(s, width);
413 out_uint16_le(s, height);
414 out_uint16_le(s, 0xca01);
415 out_uint16_le(s, 0xaa03);
416 out_uint32_le(s, keylayout);
417 out_uint32_le(s, 419); /* client build? we are 419 compatible :-) */
418
419 /* Unicode name of client, padded to 32 bytes */
420 rdp_out_unistr(s, hostname, hostlen);
421 out_uint8s(s, 30 - hostlen);
422
423 out_uint32_le(s, 4);
424 out_uint32(s, 0);
425 out_uint32_le(s, 12);
426 out_uint8s(s, 64); /* reserved? 4 + 12 doublewords */
427
428 out_uint16(s, 0xca01);
429 out_uint16(s, 0);
430
431 /* Client encryption settings */
432 out_uint16_le(s, SEC_TAG_CLI_CRYPT);
433 out_uint16(s, 8); /* length */
434 out_uint32_le(s, encryption ? 0x3 : 0); /* encryption supported, 128-bit supported */
435 s_mark_end(s);
436 }
437
438 /* Parse a public key structure */
439 static BOOL
440 sec_parse_public_key(STREAM s, uint8 ** modulus, uint8 ** exponent)
441 {
442 uint32 magic, modulus_len;
443
444 in_uint32_le(s, magic);
445 if (magic != SEC_RSA_MAGIC)
446 {
447 error("RSA magic 0x%x\n", magic);
448 return False;
449 }
450
451 in_uint32_le(s, modulus_len);
452 if (modulus_len != SEC_MODULUS_SIZE + SEC_PADDING_SIZE)
453 {
454 error("modulus len 0x%x\n", modulus_len);
455 return False;
456 }
457
458 in_uint8s(s, 8); /* modulus_bits, unknown */
459 in_uint8p(s, *exponent, SEC_EXPONENT_SIZE);
460 in_uint8p(s, *modulus, SEC_MODULUS_SIZE);
461 in_uint8s(s, SEC_PADDING_SIZE);
462
463 return s_check(s);
464 }
465
466 /* Parse a crypto information structure */
467 static BOOL
468 sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
469 uint8 ** server_random, uint8 ** modulus, uint8 ** exponent)
470 {
471 uint32 crypt_level, random_len, rsa_info_len;
472 uint16 tag, length;
473 uint8 *next_tag, *end;
474
475 in_uint32_le(s, *rc4_key_size); /* 1 = 40-bit, 2 = 128-bit */
476 in_uint32_le(s, crypt_level); /* 1 = low, 2 = medium, 3 = high */
477 if (crypt_level == 0) /* no encryptation */
478 return False;
479 in_uint32_le(s, random_len);
480 in_uint32_le(s, rsa_info_len);
481
482 if (random_len != SEC_RANDOM_SIZE)
483 {
484 error("random len %d\n", random_len);
485 return False;
486 }
487
488 in_uint8p(s, *server_random, random_len);
489
490 /* RSA info */
491 end = s->p + rsa_info_len;
492 if (end > s->end)
493 return False;
494
495 in_uint8s(s, 12); /* unknown */
496
497 while (s->p < end)
498 {
499 in_uint16_le(s, tag);
500 in_uint16_le(s, length);
501
502 next_tag = s->p + length;
503
504 switch (tag)
505 {
506 case SEC_TAG_PUBKEY:
507 if (!sec_parse_public_key(s, modulus, exponent))
508 return False;
509
510 break;
511
512 case SEC_TAG_KEYSIG:
513 /* Is this a Microsoft key that we just got? */
514 /* Care factor: zero! */
515 break;
516
517 default:
518 unimpl("crypt tag 0x%x\n", tag);
519 }
520
521 s->p = next_tag;
522 }
523
524 return s_check_end(s);
525 }
526
527 /* Process crypto information blob */
528 static void
529 sec_process_crypt_info(STREAM s)
530 {
531 uint8 *server_random, *modulus, *exponent;
532 uint8 client_random[SEC_RANDOM_SIZE];
533 uint32 rc4_key_size;
534
535 if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random, &modulus, &exponent))
536 return;
537
538 /* Generate a client random, and hence determine encryption keys */
539 generate_random(client_random);
540 sec_rsa_encrypt(sec_crypted_random, client_random, SEC_RANDOM_SIZE, modulus, exponent);
541 sec_generate_keys(client_random, server_random, rc4_key_size);
542 }
543
544 /* Process connect response data blob */
545 static void
546 sec_process_mcs_data(STREAM s)
547 {
548 uint16 tag, length;
549 uint8 *next_tag;
550
551 in_uint8s(s, 23); /* header */
552
553 while (s->p < s->end)
554 {
555 in_uint16_le(s, tag);
556 in_uint16_le(s, length);
557
558 if (length <= 4)
559 return;
560
561 next_tag = s->p + length - 4;
562
563 switch (tag)
564 {
565 case SEC_TAG_SRV_INFO:
566 case SEC_TAG_SRV_3:
567 break;
568
569 case SEC_TAG_SRV_CRYPT:
570 sec_process_crypt_info(s);
571 break;
572
573 default:
574 unimpl("response tag 0x%x\n", tag);
575 }
576
577 s->p = next_tag;
578 }
579 }
580
581 /* Receive secure transport packet */
582 STREAM
583 sec_recv()
584 {
585 uint32 sec_flags;
586 STREAM s;
587
588 while ((s = mcs_recv()) != NULL)
589 {
590 if (encryption || !licence_issued)
591 {
592 in_uint32_le(s, sec_flags);
593
594 if (sec_flags & SEC_LICENCE_NEG)
595 {
596 licence_process(s);
597 continue;
598 }
599
600 if (sec_flags & SEC_ENCRYPT)
601 {
602 in_uint8s(s, 8); /* signature */
603 sec_decrypt(s->p, s->end - s->p);
604 }
605 }
606
607 return s;
608 }
609
610 return NULL;
611 }
612
613 /* Establish a secure connection */
614 BOOL
615 sec_connect(char *server)
616 {
617 struct stream mcs_data;
618
619 /* We exchange some RDP data during the MCS-Connect */
620 mcs_data.size = 512;
621 mcs_data.p = mcs_data.data = xmalloc(mcs_data.size);
622 sec_out_mcs_data(&mcs_data);
623
624 if (!mcs_connect(server, &mcs_data))
625 return False;
626
627 sec_process_mcs_data(&mcs_data);
628 if (encryption)
629 sec_establish_key();
630 return True;
631 }
632
633 /* Disconnect a connection */
634 void
635 sec_disconnect()
636 {
637 mcs_disconnect();
638 }

  ViewVC Help
Powered by ViewVC 1.1.26