/[rdesktop]/sourceforge.net/trunk/rdpproxy/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/rdpproxy/secure.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 430 - (hide annotations)
Mon Jun 30 08:59:07 2003 UTC (20 years, 11 months ago) by forsberg
File MIME type: text/plain
File size: 15299 byte(s)
This commit was generated by cvs2svn to compensate for changes in r428,
which included commits to RCS files with non-trunk default branches.

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

  ViewVC Help
Powered by ViewVC 1.1.26