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

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 matty 28 extern BOOL use_encryption;
32     extern BOOL licence_issued;
33 matty 10
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 matty 25 void
51     sec_hash_48(uint8 *out, uint8 *in, uint8 *salt1, uint8 *salt2, uint8 salt)
52 matty 10 {
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 matty 24 memset(pad, salt + i, i + 1);
62 matty 10
63     SHA1_Init(&sha);
64 matty 24 SHA1_Update(&sha, pad, i + 1);
65 matty 10 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 matty 24 MD5_Final(&out[i * 16], &md5);
74 matty 10 }
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 matty 25 void
82     sec_hash_16(uint8 *out, uint8 *in, uint8 *salt1, uint8 *salt2)
83 matty 10 {
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 matty 25 static void
95     sec_make_40bit(uint8 *key)
96 matty 10 {
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 matty 25 static void
104     sec_generate_keys(uint8 *client_key, uint8 *server_key, int rc4_key_size)
105 matty 10 {
106     uint8 session_key[48];
107     uint8 temp_hash[48];
108     uint8 input[48];
109    
110     /* Construct input data to hash */
111 matty 24 memcpy(input, client_key, 24);
112     memcpy(input + 24, server_key, 24);
113 matty 10
114     /* Generate session key - two rounds of sec_hash_48 */
115 matty 24 sec_hash_48(temp_hash, input, client_key, server_key, 65);
116 matty 10 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 matty 24 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 matty 10
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 matty 24 static uint8 pad_54[40] = {
151     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 24 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
154 matty 25 54, 54, 54
155 matty 10 };
156    
157 matty 24 static uint8 pad_92[48] = {
158     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 24 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
161 matty 25 92, 92, 92, 92, 92, 92, 92
162 matty 10 };
163    
164     /* Output a uint32 into a buffer (little-endian) */
165 matty 25 void
166     buf_out_uint32(uint8 *buffer, uint32 value)
167 matty 10 {
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 matty 25 void
176     sec_sign(uint8 *signature, uint8 *session_key, int length,
177     uint8 *data, int datalen)
178 matty 10 {
179     uint8 shasig[20];
180     uint8 md5sig[16];
181     uint8 lenhdr[4];
182     SHA_CTX sha;
183     MD5_CTX md5;
184    
185 matty 24 buf_out_uint32(lenhdr, datalen);
186 matty 10
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 matty 25 static void
205     sec_update(uint8 *key, uint8 *update_key)
206 matty 10 {
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 matty 25 static void
233     sec_encrypt(uint8 *data, int length)
234 matty 10 {
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 matty 25 static void
250     sec_decrypt(uint8 *data, int length)
251 matty 10 {
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 matty 25 static void
267     sec_read_number(NUMBER * num, uint8 *buffer, int len)
268 matty 10 {
269     INT *data = num->n_part;
270     int i, j;
271    
272     for (i = 0, j = 0; j < len; i++, j += 2)
273 matty 24 data[i] = buffer[j] | (buffer[j + 1] << 8);
274 matty 10
275 matty 24 num->n_len = i;
276     }
277 matty 10
278     /* Write a NUMBER to a buffer */
279 matty 25 static void
280     sec_write_number(NUMBER * num, uint8 *buffer, int len)
281 matty 10 {
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 matty 24 buffer[j + 1] = data[i] >> 8;
289 matty 10 }
290     }
291    
292     /* Perform an RSA public key encryption operation */
293 matty 25 static void
294     sec_rsa_encrypt(uint8 *out, uint8 *in, int len,
295     uint8 *modulus, uint8 *exponent)
296 matty 10 {
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 matty 25 STREAM
312     sec_init(uint32 flags, int maxlen)
313 matty 10 {
314     int hdrlen;
315     STREAM s;
316    
317 matty 28 if (!licence_issued)
318     hdrlen = (flags & SEC_ENCRYPT) ? 12 : 4;
319     else
320     hdrlen = (flags & SEC_ENCRYPT) ? 12 : 0;
321 matty 24 s = mcs_init(maxlen + hdrlen);
322 matty 10 s_push_layer(s, sec_hdr, hdrlen);
323    
324     return s;
325     }
326    
327     /* Transmit secure transport packet */
328 matty 25 void
329     sec_send(STREAM s, uint32 flags)
330 matty 10 {
331     int datalen;
332    
333     s_pop_layer(s, sec_hdr);
334 matty 28 if (!licence_issued || (flags & SEC_ENCRYPT))
335     out_uint32_le(s, flags);
336 matty 10
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 matty 24 hexdump(s->p + 8, datalen);
345 matty 10 #endif
346    
347 matty 24 sec_sign(s->p, sec_sign_key, 8, s->p + 8, datalen);
348     sec_encrypt(s->p + 8, datalen);
349 matty 10 }
350    
351     mcs_send(s);
352     }
353    
354     /* Transfer the client random to the server */
355 matty 25 static void
356     sec_establish_key()
357 matty 10 {
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 matty 25 static void
374     sec_out_mcs_data(STREAM s)
375 matty 10 {
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 matty 24 out_uint16_be(s, (158 | 0x8000)); /* remaining length */
384 matty 10
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 matty 24 out_uint32_le(s, 0x61637544); /* "Duca" ?! */
392     out_uint16_be(s, (144 | 0x8000)); /* remaining length */
393 matty 10
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 matty 24 out_uint32_le(s, 419); /* client build? we are 419 compatible :-) */
405 matty 10
406     /* Unicode name of client, padded to 32 bytes */
407     rdp_out_unistr(s, hostname, hostlen);
408 matty 24 out_uint8s(s, 30 - hostlen);
409 matty 10
410     out_uint32_le(s, 4);
411     out_uint32(s, 0);
412     out_uint32_le(s, 12);
413 matty 24 out_uint8s(s, 64); /* reserved? 4 + 12 doublewords */
414 matty 10
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 matty 28 out_uint32_le(s, use_encryption ? 1 : 0); /* encryption enabled */
422 matty 10 s_mark_end(s);
423     }
424    
425     /* Parse a public key structure */
426 matty 25 static BOOL
427     sec_parse_public_key(STREAM s, uint8 **modulus, uint8 **exponent)
428 matty 10 {
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 matty 24 in_uint8s(s, 8); /* modulus_bits, unknown */
446 matty 10 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 matty 25 static BOOL
455     sec_parse_crypt_info(STREAM s, uint32 *rc4_key_size,
456     uint8 **server_random, uint8 **modulus, uint8 **exponent)
457 matty 10 {
458     uint32 crypt_level, random_len, rsa_info_len;
459     uint16 tag, length;
460     uint8 *next_tag, *end;
461    
462 matty 24 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 matty 10 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 matty 24 in_uint8s(s, 12); /* unknown */
481 matty 10
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 matty 24 if (!sec_parse_public_key
493     (s, modulus, exponent))
494 matty 10 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 matty 25 static void
515     sec_process_crypt_info(STREAM s)
516 matty 10 {
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 matty 24 &modulus, &exponent))
523 matty 10 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 matty 24 SEC_RANDOM_SIZE, modulus, exponent);
529 matty 10 sec_generate_keys(client_random, server_random, rc4_key_size);
530     }
531    
532     /* Process connect response data blob */
533 matty 25 static void
534     sec_process_mcs_data(STREAM s)
535 matty 10 {
536     uint16 tag, length;
537     uint8 *next_tag;
538    
539 matty 24 in_uint8s(s, 23); /* header */
540 matty 10
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 matty 25 STREAM
571     sec_recv()
572 matty 10 {
573     uint32 sec_flags;
574     STREAM s;
575    
576     while ((s = mcs_recv()) != NULL)
577     {
578 matty 28 if (use_encryption || !licence_issued)
579 matty 10 {
580 matty 28 in_uint32_le(s, sec_flags);
581 matty 10
582 matty 28 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 matty 10 }
594    
595     return s;
596     }
597    
598     return NULL;
599     }
600    
601     /* Establish a secure connection */
602 matty 25 BOOL
603     sec_connect(char *server)
604 matty 10 {
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 matty 28 if (use_encryption)
617     sec_establish_key();
618 matty 10 return True;
619     }
620    
621     /* Disconnect a connection */
622 matty 25 void
623     sec_disconnect()
624 matty 10 {
625     mcs_disconnect();
626     }

  ViewVC Help
Powered by ViewVC 1.1.26