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

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 24 void sec_hash_48(uint8 *out, uint8 *in, uint8 *salt1, uint8 *salt2,
49     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     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 matty 24 memcpy(input, client_key, 24);
108     memcpy(input + 24, server_key, 24);
109 matty 10
110     /* Generate session key - two rounds of sec_hash_48 */
111 matty 24 sec_hash_48(temp_hash, input, client_key, server_key, 65);
112 matty 10 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 matty 24 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 matty 10
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 matty 24 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 matty 10 };
152    
153 matty 24 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 matty 10 };
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 matty 24 uint8 *data, int datalen)
172 matty 10 {
173     uint8 shasig[20];
174     uint8 md5sig[16];
175     uint8 lenhdr[4];
176     SHA_CTX sha;
177     MD5_CTX md5;
178    
179 matty 24 buf_out_uint32(lenhdr, datalen);
180 matty 10
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 matty 24 static void sec_read_number(NUMBER * num, uint8 *buffer, int len)
258 matty 10 {
259     INT *data = num->n_part;
260     int i, j;
261    
262     for (i = 0, j = 0; j < len; i++, j += 2)
263 matty 24 data[i] = buffer[j] | (buffer[j + 1] << 8);
264 matty 10
265 matty 24 num->n_len = i;
266     }
267 matty 10
268     /* Write a NUMBER to a buffer */
269 matty 24 static void sec_write_number(NUMBER * num, uint8 *buffer, int len)
270 matty 10 {
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 matty 24 buffer[j + 1] = data[i] >> 8;
278 matty 10 }
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 matty 24 s = mcs_init(maxlen + hdrlen);
306 matty 10 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 matty 24 hexdump(s->p + 8, datalen);
327 matty 10 #endif
328    
329 matty 24 sec_sign(s->p, sec_sign_key, 8, s->p + 8, datalen);
330     sec_encrypt(s->p + 8, datalen);
331 matty 10 }
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 matty 24 out_uint16_be(s, (158 | 0x8000)); /* remaining length */
364 matty 10
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 matty 24 out_uint32_le(s, 0x61637544); /* "Duca" ?! */
372     out_uint16_be(s, (144 | 0x8000)); /* remaining length */
373 matty 10
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 matty 24 out_uint32_le(s, 419); /* client build? we are 419 compatible :-) */
385 matty 10
386     /* Unicode name of client, padded to 32 bytes */
387     rdp_out_unistr(s, hostname, hostlen);
388 matty 24 out_uint8s(s, 30 - hostlen);
389 matty 10
390     out_uint32_le(s, 4);
391     out_uint32(s, 0);
392     out_uint32_le(s, 12);
393 matty 24 out_uint8s(s, 64); /* reserved? 4 + 12 doublewords */
394 matty 10
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 matty 24 in_uint8s(s, 8); /* modulus_bits, unknown */
425 matty 10 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 matty 24 uint8 **server_random, uint8 **modulus,
435     uint8 **exponent)
436 matty 10 {
437     uint32 crypt_level, random_len, rsa_info_len;
438     uint16 tag, length;
439     uint8 *next_tag, *end;
440    
441 matty 24 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 matty 10 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 matty 24 in_uint8s(s, 12); /* unknown */
460 matty 10
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 matty 24 if (!sec_parse_public_key
472     (s, modulus, exponent))
473 matty 10 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 matty 24 &modulus, &exponent))
501 matty 10 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 matty 24 SEC_RANDOM_SIZE, modulus, exponent);
507 matty 10 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 matty 24 in_uint8s(s, 23); /* header */
517 matty 10
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 matty 24 in_uint8s(s, 8); /* signature */
565 matty 10 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