/[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 24 - (show annotations)
Sat Jan 6 03:12:10 2001 UTC (23 years, 5 months ago) by matty
File MIME type: text/plain
File size: 13548 byte(s)
ran indent (-bli0 -i8 -cli8 -npcs -npsl)

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

  ViewVC Help
Powered by ViewVC 1.1.26