/[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 10 - (hide annotations)
Tue Aug 15 10:23:24 2000 UTC (23 years, 9 months ago) by matty
File MIME type: text/plain
File size: 13417 byte(s)
Major commit of work from laptop - done in various free moments.
Implemented encryption layer and some basic licensing negotiation.
Reorganised code somewhat. While this is not quite as clean, it is
a lot faster - our parser speed was becoming a bottle-neck.

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

  ViewVC Help
Powered by ViewVC 1.1.26