/[rdesktop]/jpeg/rdesktop/trunk/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

Diff of /jpeg/rdesktop/trunk/secure.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 438 by jsorg71, Fri Aug 1 17:01:58 2003 UTC revision 1374 by jsorg71, Tue Jan 9 07:24:44 2007 UTC
# Line 1  Line 1 
1  /* -*- c-basic-offset: 8 -*-  /* -*- c-basic-offset: 8 -*-
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     Protocol services - RDP encryption and licensing     Protocol services - RDP encryption and licensing
4     Copyright (C) Matthew Chapman 1999-2002     Copyright (C) Matthew Chapman 1999-2007
5    
6     This program is free software; you can redistribute it and/or modify     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     it under the terms of the GNU General Public License as published by
# Line 19  Line 19 
19  */  */
20    
21  #include "rdesktop.h"  #include "rdesktop.h"
22    #include "ssl.h"
23    
24  #ifdef WITH_OPENSSL  extern char g_hostname[16];
25  #include <openssl/rc4.h>  extern int g_width;
26  #include <openssl/md5.h>  extern int g_height;
27  #include <openssl/sha.h>  extern unsigned int g_keylayout;
28  #include <openssl/bn.h>  extern int g_keyboard_type;
29  #include <openssl/x509v3.h>  extern int g_keyboard_subtype;
30  #else  extern int g_keyboard_functionkeys;
31  #include "crypto/rc4.h"  extern RD_BOOL g_encryption;
32  #include "crypto/md5.h"  extern RD_BOOL g_licence_issued;
33  #include "crypto/sha.h"  extern RD_BOOL g_use_rdp5;
34  #include "crypto/bn.h"  extern RD_BOOL g_console_session;
35  #endif  extern int g_server_depth;
   
 extern char hostname[16];  
 extern int width;  
 extern int height;  
 extern int keylayout;  
 extern BOOL g_encryption;  
 extern BOOL g_licence_issued;  
 extern BOOL g_use_rdp5;  
 extern int g_server_bpp;  
36  extern uint16 mcs_userid;  extern uint16 mcs_userid;
37  extern VCHANNEL g_channels[];  extern VCHANNEL g_channels[];
38  extern unsigned int g_num_channels;  extern unsigned int g_num_channels;
39    
40  static int rc4_key_len;  static int rc4_key_len;
41  static RC4_KEY rc4_decrypt_key;  static SSL_RC4 rc4_decrypt_key;
42  static RC4_KEY rc4_encrypt_key;  static SSL_RC4 rc4_encrypt_key;
43  static RSA *server_public_key;  static uint32 server_public_key_len;
44    
45  static uint8 sec_sign_key[16];  static uint8 sec_sign_key[16];
46  static uint8 sec_decrypt_key[16];  static uint8 sec_decrypt_key[16];
47  static uint8 sec_encrypt_key[16];  static uint8 sec_encrypt_key[16];
48  static uint8 sec_decrypt_update_key[16];  static uint8 sec_decrypt_update_key[16];
49  static uint8 sec_encrypt_update_key[16];  static uint8 sec_encrypt_update_key[16];
50  static uint8 sec_crypted_random[SEC_MODULUS_SIZE];  static uint8 sec_crypted_random[SEC_MAX_MODULUS_SIZE];
51    
52  uint16 g_server_rdp_version = 0;  uint16 g_server_rdp_version = 0;
53    
54    /* These values must be available to reset state - Session Directory */
55    static int sec_encrypt_use_count = 0;
56    static int sec_decrypt_use_count = 0;
57    
58  /*  /*
59   * General purpose 48-byte transformation, using two 32-byte salts (generally,   * I believe this is based on SSLv3 with the following differences:
60   * a client and server salt) and a global salt value used for padding.   *  MAC algorithm (5.2.3.1) uses only 32-bit length in place of seq_num/type/length fields
61     *  MAC algorithm uses SHA1 and MD5 for the two hash functions instead of one or other
62     *  key_block algorithm (6.2.2) uses 'X', 'YY', 'ZZZ' instead of 'A', 'BB', 'CCC'
63     *  key_block partitioning is different (16 bytes each: MAC secret, decrypt key, encrypt key)
64     *  encryption/decryption keys updated every 4096 packets
65     * See http://wp.netscape.com/eng/ssl3/draft302.txt
66     */
67    
68    /*
69     * 48-byte transformation used to generate master secret (6.1) and key material (6.2.2).
70   * Both SHA1 and MD5 algorithms are used.   * Both SHA1 and MD5 algorithms are used.
71   */   */
72  void  void
# Line 69  sec_hash_48(uint8 * out, uint8 * in, uin Line 74  sec_hash_48(uint8 * out, uint8 * in, uin
74  {  {
75          uint8 shasig[20];          uint8 shasig[20];
76          uint8 pad[4];          uint8 pad[4];
77          SHA_CTX sha;          SSL_SHA1 sha1;
78          MD5_CTX md5;          SSL_MD5 md5;
79          int i;          int i;
80    
81          for (i = 0; i < 3; i++)          for (i = 0; i < 3; i++)
82          {          {
83                  memset(pad, salt + i, i + 1);                  memset(pad, salt + i, i + 1);
84    
85                  SHA1_Init(&sha);                  ssl_sha1_init(&sha1);
86                  SHA1_Update(&sha, pad, i + 1);                  ssl_sha1_update(&sha1, pad, i + 1);
87                  SHA1_Update(&sha, in, 48);                  ssl_sha1_update(&sha1, in, 48);
88                  SHA1_Update(&sha, salt1, 32);                  ssl_sha1_update(&sha1, salt1, 32);
89                  SHA1_Update(&sha, salt2, 32);                  ssl_sha1_update(&sha1, salt2, 32);
90                  SHA1_Final(shasig, &sha);                  ssl_sha1_final(&sha1, shasig);
91    
92                  MD5_Init(&md5);                  ssl_md5_init(&md5);
93                  MD5_Update(&md5, in, 48);                  ssl_md5_update(&md5, in, 48);
94                  MD5_Update(&md5, shasig, 20);                  ssl_md5_update(&md5, shasig, 20);
95                  MD5_Final(&out[i * 16], &md5);                  ssl_md5_final(&md5, &out[i * 16]);
96          }          }
97  }  }
98    
99  /*  /*
100   * Weaker 16-byte transformation, also using two 32-byte salts, but   * 16-byte transformation used to generate export keys (6.2.2).
  * only using a single round of MD5.  
101   */   */
102  void  void
103  sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2)  sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2)
104  {  {
105          MD5_CTX md5;          SSL_MD5 md5;
106    
107          MD5_Init(&md5);          ssl_md5_init(&md5);
108          MD5_Update(&md5, in, 16);          ssl_md5_update(&md5, in, 16);
109          MD5_Update(&md5, salt1, 32);          ssl_md5_update(&md5, salt1, 32);
110          MD5_Update(&md5, salt2, 32);          ssl_md5_update(&md5, salt2, 32);
111          MD5_Final(out, &md5);          ssl_md5_final(&md5, out);
112  }  }
113    
114  /* Reduce key entropy from 64 to 40 bits */  /* Reduce key entropy from 64 to 40 bits */
# Line 116  sec_make_40bit(uint8 * key) Line 120  sec_make_40bit(uint8 * key)
120          key[2] = 0x9e;          key[2] = 0x9e;
121  }  }
122    
123  /* Generate a session key and RC4 keys, given client and server randoms */  /* Generate encryption keys given client and server randoms */
124  static void  static void
125  sec_generate_keys(uint8 * client_key, uint8 * server_key, int rc4_key_size)  sec_generate_keys(uint8 * client_random, uint8 * server_random, int rc4_key_size)
126  {  {
127          uint8 session_key[48];          uint8 pre_master_secret[48];
128          uint8 temp_hash[48];          uint8 master_secret[48];
129          uint8 input[48];          uint8 key_block[48];
130    
131          /* Construct input data to hash */          /* Construct pre-master secret */
132          memcpy(input, client_key, 24);          memcpy(pre_master_secret, client_random, 24);
133          memcpy(input + 24, server_key, 24);          memcpy(pre_master_secret + 24, server_random, 24);
134    
135          /* Generate session key - two rounds of sec_hash_48 */          /* Generate master secret and then key material */
136          sec_hash_48(temp_hash, input, client_key, server_key, 65);          sec_hash_48(master_secret, pre_master_secret, client_random, server_random, 'A');
137          sec_hash_48(session_key, temp_hash, client_key, server_key, 88);          sec_hash_48(key_block, master_secret, client_random, server_random, 'X');
138    
139          /* Store first 16 bytes of session key, for generating signatures */          /* First 16 bytes of key material is MAC secret */
140          memcpy(sec_sign_key, session_key, 16);          memcpy(sec_sign_key, key_block, 16);
141    
142          /* Generate RC4 keys */          /* Generate export keys from next two blocks of 16 bytes */
143          sec_hash_16(sec_decrypt_key, &session_key[16], client_key, server_key);          sec_hash_16(sec_decrypt_key, &key_block[16], client_random, server_random);
144          sec_hash_16(sec_encrypt_key, &session_key[32], client_key, server_key);          sec_hash_16(sec_encrypt_key, &key_block[32], client_random, server_random);
145    
146          if (rc4_key_size == 1)          if (rc4_key_size == 1)
147          {          {
# Line 186  buf_out_uint32(uint8 * buffer, uint32 va Line 190  buf_out_uint32(uint8 * buffer, uint32 va
190          buffer[3] = (value >> 24) & 0xff;          buffer[3] = (value >> 24) & 0xff;
191  }  }
192    
193  /* Generate a signature hash, using a combination of SHA1 and MD5 */  /* Generate a MAC hash (5.2.3.1), using a combination of SHA1 and MD5 */
194  void  void
195  sec_sign(uint8 * signature, int siglen, uint8 * session_key, int keylen, uint8 * data, int datalen)  sec_sign(uint8 * signature, int siglen, uint8 * session_key, int keylen, uint8 * data, int datalen)
196  {  {
197          uint8 shasig[20];          uint8 shasig[20];
198          uint8 md5sig[16];          uint8 md5sig[16];
199          uint8 lenhdr[4];          uint8 lenhdr[4];
200          SHA_CTX sha;          SSL_SHA1 sha1;
201          MD5_CTX md5;          SSL_MD5 md5;
202    
203          buf_out_uint32(lenhdr, datalen);          buf_out_uint32(lenhdr, datalen);
204    
205          SHA1_Init(&sha);          ssl_sha1_init(&sha1);
206          SHA1_Update(&sha, session_key, keylen);          ssl_sha1_update(&sha1, session_key, keylen);
207          SHA1_Update(&sha, pad_54, 40);          ssl_sha1_update(&sha1, pad_54, 40);
208          SHA1_Update(&sha, lenhdr, 4);          ssl_sha1_update(&sha1, lenhdr, 4);
209          SHA1_Update(&sha, data, datalen);          ssl_sha1_update(&sha1, data, datalen);
210          SHA1_Final(shasig, &sha);          ssl_sha1_final(&sha1, shasig);
211    
212          MD5_Init(&md5);          ssl_md5_init(&md5);
213          MD5_Update(&md5, session_key, keylen);          ssl_md5_update(&md5, session_key, keylen);
214          MD5_Update(&md5, pad_92, 48);          ssl_md5_update(&md5, pad_92, 48);
215          MD5_Update(&md5, shasig, 20);          ssl_md5_update(&md5, shasig, 20);
216          MD5_Final(md5sig, &md5);          ssl_md5_final(&md5, md5sig);
217    
218          memcpy(signature, md5sig, siglen);          memcpy(signature, md5sig, siglen);
219  }  }
220    
221  /* Update an encryption key - similar to the signing process */  /* Update an encryption key */
222  static void  static void
223  sec_update(uint8 * key, uint8 * update_key)  sec_update(uint8 * key, uint8 * update_key)
224  {  {
225          uint8 shasig[20];          uint8 shasig[20];
226          SHA_CTX sha;          SSL_SHA1 sha1;
227          MD5_CTX md5;          SSL_MD5 md5;
228          RC4_KEY update;          SSL_RC4 update;
229    
230          SHA1_Init(&sha);          ssl_sha1_init(&sha1);
231          SHA1_Update(&sha, update_key, rc4_key_len);          ssl_sha1_update(&sha1, update_key, rc4_key_len);
232          SHA1_Update(&sha, pad_54, 40);          ssl_sha1_update(&sha1, pad_54, 40);
233          SHA1_Update(&sha, key, rc4_key_len);          ssl_sha1_update(&sha1, key, rc4_key_len);
234          SHA1_Final(shasig, &sha);          ssl_sha1_final(&sha1, shasig);
235    
236          MD5_Init(&md5);          ssl_md5_init(&md5);
237          MD5_Update(&md5, update_key, rc4_key_len);          ssl_md5_update(&md5, update_key, rc4_key_len);
238          MD5_Update(&md5, pad_92, 48);          ssl_md5_update(&md5, pad_92, 48);
239          MD5_Update(&md5, shasig, 20);          ssl_md5_update(&md5, shasig, 20);
240          MD5_Final(key, &md5);          ssl_md5_final(&md5, key);
241    
242          RC4_set_key(&update, rc4_key_len, key);          ssl_rc4_set_key(&update, key, rc4_key_len);
243          RC4(&update, rc4_key_len, key, key);          ssl_rc4_crypt(&update, key, key, rc4_key_len);
244    
245          if (rc4_key_len == 8)          if (rc4_key_len == 8)
246                  sec_make_40bit(key);                  sec_make_40bit(key);
# Line 246  sec_update(uint8 * key, uint8 * update_k Line 250  sec_update(uint8 * key, uint8 * update_k
250  static void  static void
251  sec_encrypt(uint8 * data, int length)  sec_encrypt(uint8 * data, int length)
252  {  {
253          static int use_count;          if (sec_encrypt_use_count == 4096)
   
         if (use_count == 4096)  
254          {          {
255                  sec_update(sec_encrypt_key, sec_encrypt_update_key);                  sec_update(sec_encrypt_key, sec_encrypt_update_key);
256                  RC4_set_key(&rc4_encrypt_key, rc4_key_len, sec_encrypt_key);                  ssl_rc4_set_key(&rc4_encrypt_key, sec_encrypt_key, rc4_key_len);
257                  use_count = 0;                  sec_encrypt_use_count = 0;
258          }          }
259    
260          RC4(&rc4_encrypt_key, length, data, data);          ssl_rc4_crypt(&rc4_encrypt_key, data, data, length);
261          use_count++;          sec_encrypt_use_count++;
262  }  }
263    
264  /* Decrypt data using RC4 */  /* Decrypt data using RC4 */
265  void  void
266  sec_decrypt(uint8 * data, int length)  sec_decrypt(uint8 * data, int length)
267  {  {
268          static int use_count;          if (sec_decrypt_use_count == 4096)
   
         if (use_count == 4096)  
269          {          {
270                  sec_update(sec_decrypt_key, sec_decrypt_update_key);                  sec_update(sec_decrypt_key, sec_decrypt_update_key);
271                  RC4_set_key(&rc4_decrypt_key, rc4_key_len, sec_decrypt_key);                  ssl_rc4_set_key(&rc4_decrypt_key, sec_decrypt_key, rc4_key_len);
272                  use_count = 0;                  sec_decrypt_use_count = 0;
273          }          }
274    
275          RC4(&rc4_decrypt_key, length, data, data);          ssl_rc4_crypt(&rc4_decrypt_key, data, data, length);
276          use_count++;          sec_decrypt_use_count++;
 }  
   
 static void  
 reverse(uint8 * p, int len)  
 {  
         int i, j;  
         uint8 temp;  
   
         for (i = 0, j = len - 1; i < j; i++, j--)  
         {  
                 temp = p[i];  
                 p[i] = p[j];  
                 p[j] = temp;  
         }  
277  }  }
278    
279  /* Perform an RSA public key encryption operation */  /* Perform an RSA public key encryption operation */
280  static void  static void
281  sec_rsa_encrypt(uint8 * out, uint8 * in, int len, uint8 * modulus, uint8 * exponent)  sec_rsa_encrypt(uint8 * out, uint8 * in, int len, uint32 modulus_size, uint8 * modulus,
282                    uint8 * exponent)
283  {  {
284          BN_CTX *ctx;          ssl_rsa_encrypt(out, in, len, modulus_size, modulus, exponent);
         BIGNUM mod, exp, x, y;  
         uint8 inr[SEC_MODULUS_SIZE];  
         int outlen;  
   
         reverse(modulus, SEC_MODULUS_SIZE);  
         reverse(exponent, SEC_EXPONENT_SIZE);  
         memcpy(inr, in, len);  
         reverse(inr, len);  
   
         ctx = BN_CTX_new();  
         BN_init(&mod);  
         BN_init(&exp);  
         BN_init(&x);  
         BN_init(&y);  
   
         BN_bin2bn(modulus, SEC_MODULUS_SIZE, &mod);  
         BN_bin2bn(exponent, SEC_EXPONENT_SIZE, &exp);  
         BN_bin2bn(inr, len, &x);  
         BN_mod_exp(&y, &x, &exp, &mod, ctx);  
         outlen = BN_bn2bin(&y, out);  
         reverse(out, outlen);  
         if (outlen < SEC_MODULUS_SIZE)  
                 memset(out + outlen, 0, SEC_MODULUS_SIZE - outlen);  
   
         BN_free(&y);  
         BN_clear_free(&x);  
         BN_free(&exp);  
         BN_free(&mod);  
         BN_CTX_free(ctx);  
285  }  }
286    
287  /* Initialise secure transport packet */  /* Initialise secure transport packet */
# Line 349  sec_send_to_channel(STREAM s, uint32 fla Line 307  sec_send_to_channel(STREAM s, uint32 fla
307  {  {
308          int datalen;          int datalen;
309    
310    #ifdef WITH_SCARD
311            scard_lock(SCARD_LOCK_SEC);
312    #endif
313    
314          s_pop_layer(s, sec_hdr);          s_pop_layer(s, sec_hdr);
315          if (!g_licence_issued || (flags & SEC_ENCRYPT))          if (!g_licence_issued || (flags & SEC_ENCRYPT))
316                  out_uint32_le(s, flags);                  out_uint32_le(s, flags);
# Line 368  sec_send_to_channel(STREAM s, uint32 fla Line 330  sec_send_to_channel(STREAM s, uint32 fla
330          }          }
331    
332          mcs_send_to_channel(s, channel);          mcs_send_to_channel(s, channel);
333    
334    #ifdef WITH_SCARD
335            scard_unlock(SCARD_LOCK_SEC);
336    #endif
337  }  }
338    
339  /* Transmit secure transport packet */  /* Transmit secure transport packet */
# Line 383  sec_send(STREAM s, uint32 flags) Line 349  sec_send(STREAM s, uint32 flags)
349  static void  static void
350  sec_establish_key(void)  sec_establish_key(void)
351  {  {
352          uint32 length = SEC_MODULUS_SIZE + SEC_PADDING_SIZE;          uint32 length = server_public_key_len + SEC_PADDING_SIZE;
353          uint32 flags = SEC_CLIENT_RANDOM;          uint32 flags = SEC_CLIENT_RANDOM;
354          STREAM s;          STREAM s;
355    
356          s = sec_init(flags, 76);          s = sec_init(flags, length + 4);
357    
358          out_uint32_le(s, length);          out_uint32_le(s, length);
359          out_uint8p(s, sec_crypted_random, SEC_MODULUS_SIZE);          out_uint8p(s, sec_crypted_random, server_public_key_len);
360          out_uint8s(s, SEC_PADDING_SIZE);          out_uint8s(s, SEC_PADDING_SIZE);
361    
362          s_mark_end(s);          s_mark_end(s);
# Line 401  sec_establish_key(void) Line 367  sec_establish_key(void)
367  static void  static void
368  sec_out_mcs_data(STREAM s)  sec_out_mcs_data(STREAM s)
369  {  {
370          int hostlen = 2 * strlen(hostname);          int hostlen = 2 * strlen(g_hostname);
371          int length = 158 + 76 + 12 + 4;          int length = 158 + 76 + 12 + 4;
372          unsigned int i;          unsigned int i;
373    
# Line 411  sec_out_mcs_data(STREAM s) Line 377  sec_out_mcs_data(STREAM s)
377          if (hostlen > 30)          if (hostlen > 30)
378                  hostlen = 30;                  hostlen = 30;
379    
380          out_uint16_be(s, 5);    /* unknown */          /* Generic Conference Control (T.124) ConferenceCreateRequest */
381            out_uint16_be(s, 5);
382          out_uint16_be(s, 0x14);          out_uint16_be(s, 0x14);
383          out_uint8(s, 0x7c);          out_uint8(s, 0x7c);
384          out_uint16_be(s, 1);          out_uint16_be(s, 1);
# Line 424  sec_out_mcs_data(STREAM s) Line 391  sec_out_mcs_data(STREAM s)
391          out_uint16_le(s, 0xc001);          out_uint16_le(s, 0xc001);
392          out_uint8(s, 0);          out_uint8(s, 0);
393    
394          out_uint32_le(s, 0x61637544);   /* "Duca" ?! */          out_uint32_le(s, 0x61637544);   /* OEM ID: "Duca", as in Ducati. */
395          out_uint16_be(s, ((length - 14) | 0x8000));     /* remaining length */          out_uint16_be(s, ((length - 14) | 0x8000));     /* remaining length */
396    
397          /* Client information */          /* Client information */
# Line 432  sec_out_mcs_data(STREAM s) Line 399  sec_out_mcs_data(STREAM s)
399          out_uint16_le(s, 212);  /* length */          out_uint16_le(s, 212);  /* length */
400          out_uint16_le(s, g_use_rdp5 ? 4 : 1);   /* RDP version. 1 == RDP4, 4 == RDP5. */          out_uint16_le(s, g_use_rdp5 ? 4 : 1);   /* RDP version. 1 == RDP4, 4 == RDP5. */
401          out_uint16_le(s, 8);          out_uint16_le(s, 8);
402          out_uint16_le(s, width);          out_uint16_le(s, g_width);
403          out_uint16_le(s, height);          out_uint16_le(s, g_height);
404          out_uint16_le(s, 0xca01);          out_uint16_le(s, 0xca01);
405          out_uint16_le(s, 0xaa03);          out_uint16_le(s, 0xaa03);
406          out_uint32_le(s, keylayout);          out_uint32_le(s, g_keylayout);
407          out_uint32_le(s, 2600); /* Client build. We are now 2600 compatible :-) */          out_uint32_le(s, 2600); /* Client build. We are now 2600 compatible :-) */
408    
409          /* Unicode name of client, padded to 32 bytes */          /* Unicode name of client, padded to 32 bytes */
410          rdp_out_unistr(s, hostname, hostlen);          rdp_out_unistr(s, g_hostname, hostlen);
411          out_uint8s(s, 30 - hostlen);          out_uint8s(s, 30 - hostlen);
412    
413          out_uint32_le(s, 4);          /* See
414          out_uint32(s, 0);             http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wceddk40/html/cxtsksupportingremotedesktopprotocol.asp */
415          out_uint32_le(s, 12);          out_uint32_le(s, g_keyboard_type);
416            out_uint32_le(s, g_keyboard_subtype);
417            out_uint32_le(s, g_keyboard_functionkeys);
418          out_uint8s(s, 64);      /* reserved? 4 + 12 doublewords */          out_uint8s(s, 64);      /* reserved? 4 + 12 doublewords */
419            out_uint16_le(s, 0xca01);       /* colour depth? */
         switch (g_server_bpp)  
         {  
                 case 8:  
                         out_uint16_le(s, 0xca01);  
                         break;  
                 case 15:  
                         out_uint16_le(s, 0xca02);  
                         break;  
                 case 16:  
                         out_uint16_le(s, 0xca03);  
                         break;  
                 case 24:  
                         out_uint16_le(s, 0xca04);  
                         break;  
         }  
420          out_uint16_le(s, 1);          out_uint16_le(s, 1);
421    
422          out_uint32(s, 0);          out_uint32(s, 0);
423          out_uint8(s, g_server_bpp);          out_uint8(s, g_server_depth);
424          out_uint16_le(s, 0x0700);          out_uint16_le(s, 0x0700);
425          out_uint8(s, 0);          out_uint8(s, 0);
426          out_uint32_le(s, 1);          out_uint32_le(s, 1);
# Line 474  sec_out_mcs_data(STREAM s) Line 428  sec_out_mcs_data(STREAM s)
428    
429          out_uint16_le(s, SEC_TAG_CLI_4);          out_uint16_le(s, SEC_TAG_CLI_4);
430          out_uint16_le(s, 12);          out_uint16_le(s, 12);
431          out_uint32_le(s, 9);          out_uint32_le(s, g_console_session ? 0xb : 9);
432          out_uint32(s, 0);          out_uint32(s, 0);
433    
434          /* Client encryption settings */          /* Client encryption settings */
# Line 501  sec_out_mcs_data(STREAM s) Line 455  sec_out_mcs_data(STREAM s)
455  }  }
456    
457  /* Parse a public key structure */  /* Parse a public key structure */
458  static BOOL  static RD_BOOL
459  sec_parse_public_key(STREAM s, uint8 ** modulus, uint8 ** exponent)  sec_parse_public_key(STREAM s, uint8 * modulus, uint8 * exponent)
460  {  {
461          uint32 magic, modulus_len;          uint32 magic, modulus_len;
462    
# Line 514  sec_parse_public_key(STREAM s, uint8 ** Line 468  sec_parse_public_key(STREAM s, uint8 **
468          }          }
469    
470          in_uint32_le(s, modulus_len);          in_uint32_le(s, modulus_len);
471          if (modulus_len != SEC_MODULUS_SIZE + SEC_PADDING_SIZE)          modulus_len -= SEC_PADDING_SIZE;
472            if ((modulus_len < SEC_MODULUS_SIZE) || (modulus_len > SEC_MAX_MODULUS_SIZE))
473          {          {
474                  error("modulus len 0x%x\n", modulus_len);                  error("Bad server public key size (%u bits)\n", modulus_len * 8);
475                  return False;                  return False;
476          }          }
477    
478          in_uint8s(s, 8);        /* modulus_bits, unknown */          in_uint8s(s, 8);        /* modulus_bits, unknown */
479          in_uint8p(s, *exponent, SEC_EXPONENT_SIZE);          in_uint8a(s, exponent, SEC_EXPONENT_SIZE);
480          in_uint8p(s, *modulus, SEC_MODULUS_SIZE);          in_uint8a(s, modulus, modulus_len);
481          in_uint8s(s, SEC_PADDING_SIZE);          in_uint8s(s, SEC_PADDING_SIZE);
482            server_public_key_len = modulus_len;
483    
484          return s_check(s);          return s_check(s);
485  }  }
486    
487  static BOOL  /* Parse a public signature structure */
488  sec_parse_x509_key(X509 * cert)  static RD_BOOL
489  {  sec_parse_public_sig(STREAM s, uint32 len, uint8 * modulus, uint8 * exponent)
490          EVP_PKEY *epk = NULL;  {
491          /* By some reason, Microsoft sets the OID of the Public RSA key to          uint8 signature[SEC_MAX_MODULUS_SIZE];
492             the oid for "MD5 with RSA Encryption" instead of "RSA Encryption"          uint32 sig_len;
493    
494             Kudos to Richard Levitte for the following (. intiutive .)          if (len != 72)
495             lines of code that resets the OID and let's us extract the key. */          {
496          if (OBJ_obj2nid(cert->cert_info->key->algor->algorithm) == NID_md5WithRSAEncryption)                  return True;
497          {          }
498                  DEBUG_RDP5(("Re-setting algorithm type to RSA in server certificate\n"));          memset(signature, 0, sizeof(signature));
499                  cert->cert_info->key->algor->algorithm = OBJ_nid2obj(NID_rsaEncryption);          sig_len = len - 8;
500          }          in_uint8a(s, signature, sig_len);
501          epk = X509_get_pubkey(cert);          return ssl_sig_ok(exponent, SEC_EXPONENT_SIZE, modulus, server_public_key_len,
502          if (NULL == epk)                            signature, sig_len);
         {  
                 error("Failed to extract public key from certificate\n");  
                 return False;  
         }  
   
         server_public_key = (RSA *) epk->pkey.ptr;  
   
         return True;  
503  }  }
504    
   
505  /* Parse a crypto information structure */  /* Parse a crypto information structure */
506  static BOOL  static RD_BOOL
507  sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,  sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
508                       uint8 ** server_random, uint8 ** modulus, uint8 ** exponent)                       uint8 ** server_random, uint8 * modulus, uint8 * exponent)
509  {  {
510          uint32 crypt_level, random_len, rsa_info_len;          uint32 crypt_level, random_len, rsa_info_len;
511          uint32 cacert_len, cert_len, flags;          uint32 cacert_len, cert_len, flags;
512          X509 *cacert, *server_cert;          SSL_CERT *cacert, *server_cert;
513            SSL_RKEY *server_public_key;
514          uint16 tag, length;          uint16 tag, length;
515          uint8 *next_tag, *end;          uint8 *next_tag, *end;
516    
# Line 609  sec_parse_crypt_info(STREAM s, uint32 * Line 557  sec_parse_crypt_info(STREAM s, uint32 *
557                                          break;                                          break;
558    
559                                  case SEC_TAG_KEYSIG:                                  case SEC_TAG_KEYSIG:
560                                          /* Is this a Microsoft key that we just got? */                                          if (!sec_parse_public_sig(s, length, modulus, exponent))
561                                          /* Care factor: zero! */                                                  return False;
                                         /* Actually, it would probably be a good idea to check if the public key is signed with this key, and then store this  
                                            key as a known key of the hostname. This would prevent some MITM-attacks. */  
562                                          break;                                          break;
563    
564                                  default:                                  default:
# Line 624  sec_parse_crypt_info(STREAM s, uint32 * Line 570  sec_parse_crypt_info(STREAM s, uint32 *
570          }          }
571          else          else
572          {          {
573                    uint32 certcount;
574    
575                  DEBUG_RDP5(("We're going for the RDP5-style encryption\n"));                  DEBUG_RDP5(("We're going for the RDP5-style encryption\n"));
576                  in_uint8s(s, 4);        /* Number of certificates */                  in_uint32_le(s, certcount);     /* Number of certificates */
577                    if (certcount < 2)
578                    {
579                            error("Server didn't send enough X509 certificates\n");
580                            return False;
581                    }
582                    for (; certcount > 2; certcount--)
583                    {               /* ignore all the certificates between the root and the signing CA */
584                            uint32 ignorelen;
585                            SSL_CERT *ignorecert;
586    
587                            DEBUG_RDP5(("Ignored certs left: %d\n", certcount));
588                            in_uint32_le(s, ignorelen);
589                            DEBUG_RDP5(("Ignored Certificate length is %d\n", ignorelen));
590                            ignorecert = ssl_cert_read(s->p, ignorelen);
591                            in_uint8s(s, ignorelen);
592                            if (ignorecert == NULL)
593                            {       /* XXX: error out? */
594                                    DEBUG_RDP5(("got a bad cert: this will probably screw up the rest of the communication\n"));
595                            }
596    
597                  /* Do da funky X.509 stuffy  #ifdef WITH_DEBUG_RDP5
598                            DEBUG_RDP5(("cert #%d (ignored):\n", certcount));
599                            ssl_cert_print_fp(stdout, ignorecert);
600    #endif
601                    }
602                    /* Do da funky X.509 stuffy
603    
604                     "How did I find out about this?  I looked up and saw a                     "How did I find out about this?  I looked up and saw a
605                     bright light and when I came to I had a scar on my forehead                     bright light and when I came to I had a scar on my forehead
# Line 635  sec_parse_crypt_info(STREAM s, uint32 * Line 607  sec_parse_crypt_info(STREAM s, uint32 *
607                     - Peter Gutman in a early version of                     - Peter Gutman in a early version of
608                     http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt                     http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
609                   */                   */
   
610                  in_uint32_le(s, cacert_len);                  in_uint32_le(s, cacert_len);
611                  DEBUG_RDP5(("CA Certificate length is %d\n", cacert_len));                  DEBUG_RDP5(("CA Certificate length is %d\n", cacert_len));
612                  cacert = d2i_X509(NULL, &(s->p), cacert_len);                  cacert = ssl_cert_read(s->p, cacert_len);
613                  /* Note: We don't need to move s->p here - d2i_X509 is                  in_uint8s(s, cacert_len);
                    "kind" enough to do it for us */  
614                  if (NULL == cacert)                  if (NULL == cacert)
615                  {                  {
616                          error("Couldn't load CA Certificate from server\n");                          error("Couldn't load CA Certificate from server\n");
617                          return False;                          return False;
618                  }                  }
   
                 /* Currently, we don't use the CA Certificate.  
                    FIXME:  
                    *) Verify the server certificate (server_cert) with the  
                    CA certificate.  
                    *) Store the CA Certificate with the hostname of the  
                    server we are connecting to as key, and compare it  
                    when we connect the next time, in order to prevent  
                    MITM-attacks.  
                  */  
   
619                  in_uint32_le(s, cert_len);                  in_uint32_le(s, cert_len);
620                  DEBUG_RDP5(("Certificate length is %d\n", cert_len));                  DEBUG_RDP5(("Certificate length is %d\n", cert_len));
621                  server_cert = d2i_X509(NULL, &(s->p), cert_len);                  server_cert = ssl_cert_read(s->p, cert_len);
622                    in_uint8s(s, cert_len);
623                  if (NULL == server_cert)                  if (NULL == server_cert)
624                  {                  {
625                            ssl_cert_free(cacert);
626                          error("Couldn't load Certificate from server\n");                          error("Couldn't load Certificate from server\n");
627                          return False;                          return False;
628                  }                  }
629                    if (!ssl_certs_ok(server_cert, cacert))
630                    {
631                            ssl_cert_free(server_cert);
632                            ssl_cert_free(cacert);
633                            error("Security error CA Certificate invalid\n");
634                            return False;
635                    }
636                    ssl_cert_free(cacert);
637                  in_uint8s(s, 16);       /* Padding */                  in_uint8s(s, 16);       /* Padding */
638                    server_public_key = ssl_cert_to_rkey(server_cert, &server_public_key_len);
639                  /* Note: Verifying the server certificate must be done here,                  if (NULL == server_public_key)
                    before sec_parse_public_key since we'll have to apply  
                    serious violence to the key after this */  
   
                 if (!sec_parse_x509_key(server_cert))  
640                  {                  {
641                          DEBUG_RDP5(("Didn't parse X509 correctly\n"));                          DEBUG_RDP5(("Didn't parse X509 correctly\n"));
642                            ssl_cert_free(server_cert);
643                          return False;                          return False;
644                  }                  }
645                    ssl_cert_free(server_cert);
646                    if ((server_public_key_len < SEC_MODULUS_SIZE) ||
647                        (server_public_key_len > SEC_MAX_MODULUS_SIZE))
648                    {
649                            error("Bad server public key size (%u bits)\n", server_public_key_len * 8);
650                            ssl_rkey_free(server_public_key);
651                            return False;
652                    }
653                    if (ssl_rkey_get_exp_mod(server_public_key, exponent, SEC_EXPONENT_SIZE,
654                                             modulus, SEC_MAX_MODULUS_SIZE) != 0)
655                    {
656                            error("Problem extracting RSA exponent, modulus");
657                            ssl_rkey_free(server_public_key);
658                            return False;
659                    }
660                    ssl_rkey_free(server_public_key);
661                  return True;    /* There's some garbage here we don't care about */                  return True;    /* There's some garbage here we don't care about */
662          }          }
663          return s_check_end(s);          return s_check_end(s);
# Line 686  sec_parse_crypt_info(STREAM s, uint32 * Line 667  sec_parse_crypt_info(STREAM s, uint32 *
667  static void  static void
668  sec_process_crypt_info(STREAM s)  sec_process_crypt_info(STREAM s)
669  {  {
670          uint8 *server_random, *modulus, *exponent;          uint8 *server_random = NULL;
671          uint8 client_random[SEC_RANDOM_SIZE];          uint8 client_random[SEC_RANDOM_SIZE];
672            uint8 modulus[SEC_MAX_MODULUS_SIZE];
673            uint8 exponent[SEC_EXPONENT_SIZE];
674          uint32 rc4_key_size;          uint32 rc4_key_size;
         uint8 inr[SEC_MODULUS_SIZE];  
675    
676          if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random, &modulus, &exponent))          memset(modulus, 0, sizeof(modulus));
677            memset(exponent, 0, sizeof(exponent));
678            if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random, modulus, exponent))
679          {          {
680                  DEBUG(("Failed to parse crypt info\n"));                  DEBUG(("Failed to parse crypt info\n"));
681                  return;                  return;
682          }          }
   
683          DEBUG(("Generating client random\n"));          DEBUG(("Generating client random\n"));
         /* Generate a client random, and hence determine encryption keys */  
         // This is what the MS client do:  
         memset(inr, 0, SEC_RANDOM_SIZE);  
         /*  *ARIGL!* Plaintext attack, anyone?  
            I tried doing:  
            generate_random(inr);  
            ..but that generates connection errors now and then (yes,  
            "now and then". Something like 0 to 3 attempts needed before a  
            successful connection. Nice. Not!  
          */  
   
684          generate_random(client_random);          generate_random(client_random);
685          if (NULL != server_public_key)          sec_rsa_encrypt(sec_crypted_random, client_random, SEC_RANDOM_SIZE,
686          {                       /* Which means we should use                          server_public_key_len, modulus, exponent);
                                    RDP5-style encryption */  
   
                 memcpy(inr + SEC_RANDOM_SIZE, client_random, SEC_RANDOM_SIZE);  
                 reverse(inr + SEC_RANDOM_SIZE, SEC_RANDOM_SIZE);  
   
                 RSA_public_encrypt(SEC_MODULUS_SIZE,  
                                    inr, sec_crypted_random, server_public_key, RSA_NO_PADDING);  
   
                 reverse(sec_crypted_random, SEC_MODULUS_SIZE);  
   
         }  
         else  
         {                       /* RDP4-style encryption */  
                 sec_rsa_encrypt(sec_crypted_random,  
                                 client_random, SEC_RANDOM_SIZE, modulus, exponent);  
         }  
687          sec_generate_keys(client_random, server_random, rc4_key_size);          sec_generate_keys(client_random, server_random, rc4_key_size);
688  }  }
689    
# Line 739  sec_process_srv_info(STREAM s) Line 695  sec_process_srv_info(STREAM s)
695          in_uint16_le(s, g_server_rdp_version);          in_uint16_le(s, g_server_rdp_version);
696          DEBUG_RDP5(("Server RDP version is %d\n", g_server_rdp_version));          DEBUG_RDP5(("Server RDP version is %d\n", g_server_rdp_version));
697          if (1 == g_server_rdp_version)          if (1 == g_server_rdp_version)
698            {
699                  g_use_rdp5 = 0;                  g_use_rdp5 = 0;
700                    g_server_depth = 8;
701            }
702  }  }
703    
704    
# Line 751  sec_process_mcs_data(STREAM s) Line 710  sec_process_mcs_data(STREAM s)
710          uint8 *next_tag;          uint8 *next_tag;
711          uint8 len;          uint8 len;
712    
713          in_uint8s(s, 21);       /* header (T.124 stuff, probably) */          in_uint8s(s, 21);       /* header (T.124 ConferenceCreateResponse) */
714          in_uint8(s, len);          in_uint8(s, len);
715          if (len & 0x80)          if (len & 0x80)
716                  in_uint8(s, len);                  in_uint8(s, len);
# Line 792  sec_process_mcs_data(STREAM s) Line 751  sec_process_mcs_data(STREAM s)
751    
752  /* Receive secure transport packet */  /* Receive secure transport packet */
753  STREAM  STREAM
754  sec_recv(void)  sec_recv(uint8 * rdpver)
755  {  {
756          uint32 sec_flags;          uint32 sec_flags;
757          uint16 channel;          uint16 channel;
758          STREAM s;          STREAM s;
759    
760          while ((s = mcs_recv(&channel)) != NULL)          while ((s = mcs_recv(&channel, rdpver)) != NULL)
761          {          {
762                    if (rdpver != NULL)
763                    {
764                            if (*rdpver != 3)
765                            {
766                                    if (*rdpver & 0x80)
767                                    {
768                                            in_uint8s(s, 8);        /* signature */
769                                            sec_decrypt(s->p, s->end - s->p);
770                                    }
771                                    return s;
772                            }
773                    }
774                  if (g_encryption || !g_licence_issued)                  if (g_encryption || !g_licence_issued)
775                  {                  {
776                          in_uint32_le(s, sec_flags);                          in_uint32_le(s, sec_flags);
# Line 815  sec_recv(void) Line 786  sec_recv(void)
786                                  licence_process(s);                                  licence_process(s);
787                                  continue;                                  continue;
788                          }                          }
789    
790                            if (sec_flags & 0x0400) /* SEC_REDIRECT_ENCRYPT */
791                            {
792                                    uint8 swapbyte;
793    
794                                    in_uint8s(s, 8);        /* signature */
795                                    sec_decrypt(s->p, s->end - s->p);
796    
797                                    /* Check for a redirect packet, starts with 00 04 */
798                                    if (s->p[0] == 0 && s->p[1] == 4)
799                                    {
800                                            /* for some reason the PDU and the length seem to be swapped.
801                                               This isn't good, but we're going to do a byte for byte
802                                               swap.  So the first foure value appear as: 00 04 XX YY,
803                                               where XX YY is the little endian length. We're going to
804                                               use 04 00 as the PDU type, so after our swap this will look
805                                               like: XX YY 04 00 */
806                                            swapbyte = s->p[0];
807                                            s->p[0] = s->p[2];
808                                            s->p[2] = swapbyte;
809    
810                                            swapbyte = s->p[1];
811                                            s->p[1] = s->p[3];
812                                            s->p[3] = swapbyte;
813    
814                                            swapbyte = s->p[2];
815                                            s->p[2] = s->p[3];
816                                            s->p[3] = swapbyte;
817                                    }
818    #ifdef WITH_DEBUG
819                                    /* warning!  this debug statement will show passwords in the clear! */
820                                    hexdump(s->p, s->end - s->p);
821    #endif
822                            }
823    
824                  }                  }
825    
826                  if (channel != MCS_GLOBAL_CHANNEL)                  if (channel != MCS_GLOBAL_CHANNEL)
827                  {                  {
828                          channel_process(s, channel);                          channel_process(s, channel);
829                          continue;                          *rdpver = 0xff;
830                            return s;
831                  }                  }
832    
833                  return s;                  return s;
# Line 830  sec_recv(void) Line 837  sec_recv(void)
837  }  }
838    
839  /* Establish a secure connection */  /* Establish a secure connection */
840  BOOL  RD_BOOL
841  sec_connect(char *server, char *username)  sec_connect(char *server, char *username)
842  {  {
843          struct stream mcs_data;          struct stream mcs_data;
# Line 843  sec_connect(char *server, char *username Line 850  sec_connect(char *server, char *username
850          if (!mcs_connect(server, &mcs_data, username))          if (!mcs_connect(server, &mcs_data, username))
851                  return False;                  return False;
852    
853          //      sec_process_mcs_data(&mcs_data);          /*      sec_process_mcs_data(&mcs_data); */
854            if (g_encryption)
855                    sec_establish_key();
856            xfree(mcs_data.data);
857            return True;
858    }
859    
860    /* Establish a secure connection */
861    RD_BOOL
862    sec_reconnect(char *server)
863    {
864            struct stream mcs_data;
865    
866            /* We exchange some RDP data during the MCS-Connect */
867            mcs_data.size = 512;
868            mcs_data.p = mcs_data.data = (uint8 *) xmalloc(mcs_data.size);
869            sec_out_mcs_data(&mcs_data);
870    
871            if (!mcs_reconnect(server, &mcs_data))
872                    return False;
873    
874            /*      sec_process_mcs_data(&mcs_data); */
875          if (g_encryption)          if (g_encryption)
876                  sec_establish_key();                  sec_establish_key();
877          xfree(mcs_data.data);          xfree(mcs_data.data);
# Line 856  sec_disconnect(void) Line 884  sec_disconnect(void)
884  {  {
885          mcs_disconnect();          mcs_disconnect();
886  }  }
887    
888    /* reset the state of the sec layer */
889    void
890    sec_reset_state(void)
891    {
892            g_server_rdp_version = 0;
893            sec_encrypt_use_count = 0;
894            sec_decrypt_use_count = 0;
895            mcs_reset_state();
896    }

Legend:
Removed from v.438  
changed lines
  Added in v.1374

  ViewVC Help
Powered by ViewVC 1.1.26