/[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 25 - (hide 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 matty 10 /*
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 matty 25 void
49     sec_hash_48(uint8 *out, uint8 *in, uint8 *salt1, uint8 *salt2, uint8 salt)
50 matty 10 {
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 matty 24 memset(pad, salt + i, i + 1);
60 matty 10
61     SHA1_Init(&sha);
62 matty 24 SHA1_Update(&sha, pad, i + 1);
63 matty 10 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 matty 24 MD5_Final(&out[i * 16], &md5);
72 matty 10 }
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 matty 25 void
80     sec_hash_16(uint8 *out, uint8 *in, uint8 *salt1, uint8 *salt2)
81 matty 10 {
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 matty 25 static void
93     sec_make_40bit(uint8 *key)
94 matty 10 {
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 matty 25 static void
102     sec_generate_keys(uint8 *client_key, uint8 *server_key, int rc4_key_size)
103 matty 10 {
104     uint8 session_key[48];
105     uint8 temp_hash[48];
106     uint8 input[48];
107    
108     /* Construct input data to hash */
109 matty 24 memcpy(input, client_key, 24);
110     memcpy(input + 24, server_key, 24);
111 matty 10
112     /* Generate session key - two rounds of sec_hash_48 */
113 matty 24 sec_hash_48(temp_hash, input, client_key, server_key, 65);
114 matty 10 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 matty 24 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 matty 10
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 matty 24 static uint8 pad_54[40] = {
149     54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
150 matty 25 54, 54, 54,
151 matty 24 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
152 matty 25 54, 54, 54
153 matty 10 };
154    
155 matty 24 static uint8 pad_92[48] = {
156     92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
157 matty 25 92, 92, 92, 92, 92, 92, 92,
158 matty 24 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
159 matty 25 92, 92, 92, 92, 92, 92, 92
160 matty 10 };
161    
162     /* Output a uint32 into a buffer (little-endian) */
163 matty 25 void
164     buf_out_uint32(uint8 *buffer, uint32 value)
165 matty 10 {
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 matty 25 void
174     sec_sign(uint8 *signature, uint8 *session_key, int length,
175     uint8 *data, int datalen)
176 matty 10 {
177     uint8 shasig[20];
178     uint8 md5sig[16];
179     uint8 lenhdr[4];
180     SHA_CTX sha;
181     MD5_CTX md5;
182    
183 matty 24 buf_out_uint32(lenhdr, datalen);
184 matty 10
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 matty 25 static void
203     sec_update(uint8 *key, uint8 *update_key)
204 matty 10 {
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 matty 25 static void
231     sec_encrypt(uint8 *data, int length)
232 matty 10 {
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 matty 25 static void
248     sec_decrypt(uint8 *data, int length)
249 matty 10 {
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 matty 25 static void
265     sec_read_number(NUMBER * num, uint8 *buffer, int len)
266 matty 10 {
267     INT *data = num->n_part;
268     int i, j;
269    
270     for (i = 0, j = 0; j < len; i++, j += 2)
271 matty 24 data[i] = buffer[j] | (buffer[j + 1] << 8);
272 matty 10
273 matty 24 num->n_len = i;
274     }
275 matty 10
276     /* Write a NUMBER to a buffer */
277 matty 25 static void
278     sec_write_number(NUMBER * num, uint8 *buffer, int len)
279 matty 10 {
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 matty 24 buffer[j + 1] = data[i] >> 8;
287 matty 10 }
288     }
289    
290     /* Perform an RSA public key encryption operation */
291 matty 25 static void
292     sec_rsa_encrypt(uint8 *out, uint8 *in, int len,
293     uint8 *modulus, uint8 *exponent)
294 matty 10 {
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 matty 25 STREAM
310     sec_init(uint32 flags, int maxlen)
311 matty 10 {
312     int hdrlen;
313     STREAM s;
314    
315     hdrlen = (flags & SEC_ENCRYPT) ? 12 : 4;
316 matty 24 s = mcs_init(maxlen + hdrlen);
317 matty 10 s_push_layer(s, sec_hdr, hdrlen);
318    
319     return s;
320     }
321    
322     /* Transmit secure transport packet */
323 matty 25 void
324     sec_send(STREAM s, uint32 flags)
325 matty 10 {
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 matty 24 hexdump(s->p + 8, datalen);
339 matty 10 #endif
340    
341 matty 24 sec_sign(s->p, sec_sign_key, 8, s->p + 8, datalen);
342     sec_encrypt(s->p + 8, datalen);
343 matty 10 }
344    
345     mcs_send(s);
346     }
347    
348     /* Transfer the client random to the server */
349 matty 25 static void
350     sec_establish_key()
351 matty 10 {
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 matty 25 static void
368     sec_out_mcs_data(STREAM s)
369 matty 10 {
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 matty 24 out_uint16_be(s, (158 | 0x8000)); /* remaining length */
378 matty 10
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 matty 24 out_uint32_le(s, 0x61637544); /* "Duca" ?! */
386     out_uint16_be(s, (144 | 0x8000)); /* remaining length */
387 matty 10
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 matty 24 out_uint32_le(s, 419); /* client build? we are 419 compatible :-) */
399 matty 10
400     /* Unicode name of client, padded to 32 bytes */
401     rdp_out_unistr(s, hostname, hostlen);
402 matty 24 out_uint8s(s, 30 - hostlen);
403 matty 10
404     out_uint32_le(s, 4);
405     out_uint32(s, 0);
406     out_uint32_le(s, 12);
407 matty 24 out_uint8s(s, 64); /* reserved? 4 + 12 doublewords */
408 matty 10
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 matty 25 static BOOL
421     sec_parse_public_key(STREAM s, uint8 **modulus, uint8 **exponent)
422 matty 10 {
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 matty 24 in_uint8s(s, 8); /* modulus_bits, unknown */
440 matty 10 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 matty 25 static BOOL
449     sec_parse_crypt_info(STREAM s, uint32 *rc4_key_size,
450     uint8 **server_random, uint8 **modulus, uint8 **exponent)
451 matty 10 {
452     uint32 crypt_level, random_len, rsa_info_len;
453     uint16 tag, length;
454     uint8 *next_tag, *end;
455    
456 matty 24 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 matty 10 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 matty 24 in_uint8s(s, 12); /* unknown */
475 matty 10
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 matty 24 if (!sec_parse_public_key
487     (s, modulus, exponent))
488 matty 10 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 matty 25 static void
509     sec_process_crypt_info(STREAM s)
510 matty 10 {
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 matty 24 &modulus, &exponent))
517 matty 10 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 matty 24 SEC_RANDOM_SIZE, modulus, exponent);
523 matty 10 sec_generate_keys(client_random, server_random, rc4_key_size);
524     }
525    
526     /* Process connect response data blob */
527 matty 25 static void
528     sec_process_mcs_data(STREAM s)
529 matty 10 {
530     uint16 tag, length;
531     uint8 *next_tag;
532    
533 matty 24 in_uint8s(s, 23); /* header */
534 matty 10
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 matty 25 STREAM
565     sec_recv()
566 matty 10 {
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 matty 24 in_uint8s(s, 8); /* signature */
583 matty 10 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 matty 25 BOOL
594     sec_connect(char *server)
595 matty 10 {
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 matty 25 void
613     sec_disconnect()
614 matty 10 {
615     mcs_disconnect();
616     }

  ViewVC Help
Powered by ViewVC 1.1.26