/[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 25 - (show annotations)
Sat Jan 6 03:47:04 2001 UTC (23 years, 5 months ago) by matty
File MIME type: text/plain
File size: 13519 byte(s)
Changed indentation style (-psl).

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

  ViewVC Help
Powered by ViewVC 1.1.26