/[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 28 - (show annotations)
Wed Jun 20 13:54:48 2001 UTC (22 years, 10 months ago) by matty
File MIME type: text/plain
File size: 13798 byte(s)
Merges from pl19-6-5.

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

  ViewVC Help
Powered by ViewVC 1.1.26