/[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 1475 by jsorg71, Fri Jul 11 03:51:23 2008 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-2008
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;  
 extern uint16 mcs_userid;  
36  extern VCHANNEL g_channels[];  extern VCHANNEL g_channels[];
37  extern unsigned int g_num_channels;  extern unsigned int g_num_channels;
38    
39  static int rc4_key_len;  static int g_rc4_key_len;
40  static RC4_KEY rc4_decrypt_key;  static SSL_RC4 g_rc4_decrypt_key;
41  static RC4_KEY rc4_encrypt_key;  static SSL_RC4 g_rc4_encrypt_key;
42  static RSA *server_public_key;  static uint32 g_server_public_key_len;
43    
44  static uint8 sec_sign_key[16];  static uint8 g_sec_sign_key[16];
45  static uint8 sec_decrypt_key[16];  static uint8 g_sec_decrypt_key[16];
46  static uint8 sec_encrypt_key[16];  static uint8 g_sec_encrypt_key[16];
47  static uint8 sec_decrypt_update_key[16];  static uint8 g_sec_decrypt_update_key[16];
48  static uint8 sec_encrypt_update_key[16];  static uint8 g_sec_encrypt_update_key[16];
49  static uint8 sec_crypted_random[SEC_MODULUS_SIZE];  static uint8 g_sec_crypted_random[SEC_MAX_MODULUS_SIZE];
50    
51  uint16 g_server_rdp_version = 0;  uint16 g_server_rdp_version = 0;
52    
53    /* These values must be available to reset state - Session Directory */
54    static int g_sec_encrypt_use_count = 0;
55    static int g_sec_decrypt_use_count = 0;
56    
57  /*  /*
58   * General purpose 48-byte transformation, using two 32-byte salts (generally,   * I believe this is based on SSLv3 with the following differences:
59   * 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
60     *  MAC algorithm uses SHA1 and MD5 for the two hash functions instead of one or other
61     *  key_block algorithm (6.2.2) uses 'X', 'YY', 'ZZZ' instead of 'A', 'BB', 'CCC'
62     *  key_block partitioning is different (16 bytes each: MAC secret, decrypt key, encrypt key)
63     *  encryption/decryption keys updated every 4096 packets
64     * See http://wp.netscape.com/eng/ssl3/draft302.txt
65     */
66    
67    /*
68     * 48-byte transformation used to generate master secret (6.1) and key material (6.2.2).
69   * Both SHA1 and MD5 algorithms are used.   * Both SHA1 and MD5 algorithms are used.
70   */   */
71  void  void
# Line 69  sec_hash_48(uint8 * out, uint8 * in, uin Line 73  sec_hash_48(uint8 * out, uint8 * in, uin
73  {  {
74          uint8 shasig[20];          uint8 shasig[20];
75          uint8 pad[4];          uint8 pad[4];
76          SHA_CTX sha;          SSL_SHA1 sha1;
77          MD5_CTX md5;          SSL_MD5 md5;
78          int i;          int i;
79    
80          for (i = 0; i < 3; i++)          for (i = 0; i < 3; i++)
81          {          {
82                  memset(pad, salt + i, i + 1);                  memset(pad, salt + i, i + 1);
83    
84                  SHA1_Init(&sha);                  ssl_sha1_init(&sha1);
85                  SHA1_Update(&sha, pad, i + 1);                  ssl_sha1_update(&sha1, pad, i + 1);
86                  SHA1_Update(&sha, in, 48);                  ssl_sha1_update(&sha1, in, 48);
87                  SHA1_Update(&sha, salt1, 32);                  ssl_sha1_update(&sha1, salt1, 32);
88                  SHA1_Update(&sha, salt2, 32);                  ssl_sha1_update(&sha1, salt2, 32);
89                  SHA1_Final(shasig, &sha);                  ssl_sha1_final(&sha1, shasig);
90    
91                  MD5_Init(&md5);                  ssl_md5_init(&md5);
92                  MD5_Update(&md5, in, 48);                  ssl_md5_update(&md5, in, 48);
93                  MD5_Update(&md5, shasig, 20);                  ssl_md5_update(&md5, shasig, 20);
94                  MD5_Final(&out[i * 16], &md5);                  ssl_md5_final(&md5, &out[i * 16]);
95          }          }
96  }  }
97    
98  /*  /*
99   * 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.  
100   */   */
101  void  void
102  sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2)  sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2)
103  {  {
104          MD5_CTX md5;          SSL_MD5 md5;
105    
106          MD5_Init(&md5);          ssl_md5_init(&md5);
107          MD5_Update(&md5, in, 16);          ssl_md5_update(&md5, in, 16);
108          MD5_Update(&md5, salt1, 32);          ssl_md5_update(&md5, salt1, 32);
109          MD5_Update(&md5, salt2, 32);          ssl_md5_update(&md5, salt2, 32);
110          MD5_Final(out, &md5);          ssl_md5_final(&md5, out);
111  }  }
112    
113  /* Reduce key entropy from 64 to 40 bits */  /* Reduce key entropy from 64 to 40 bits */
# Line 116  sec_make_40bit(uint8 * key) Line 119  sec_make_40bit(uint8 * key)
119          key[2] = 0x9e;          key[2] = 0x9e;
120  }  }
121    
122  /* Generate a session key and RC4 keys, given client and server randoms */  /* Generate encryption keys given client and server randoms */
123  static void  static void
124  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)
125  {  {
126          uint8 session_key[48];          uint8 pre_master_secret[48];
127          uint8 temp_hash[48];          uint8 master_secret[48];
128          uint8 input[48];          uint8 key_block[48];
129    
130          /* Construct input data to hash */          /* Construct pre-master secret */
131          memcpy(input, client_key, 24);          memcpy(pre_master_secret, client_random, 24);
132          memcpy(input + 24, server_key, 24);          memcpy(pre_master_secret + 24, server_random, 24);
133    
134          /* Generate session key - two rounds of sec_hash_48 */          /* Generate master secret and then key material */
135          sec_hash_48(temp_hash, input, client_key, server_key, 65);          sec_hash_48(master_secret, pre_master_secret, client_random, server_random, 'A');
136          sec_hash_48(session_key, temp_hash, client_key, server_key, 88);          sec_hash_48(key_block, master_secret, client_random, server_random, 'X');
137    
138          /* Store first 16 bytes of session key, for generating signatures */          /* First 16 bytes of key material is MAC secret */
139          memcpy(sec_sign_key, session_key, 16);          memcpy(g_sec_sign_key, key_block, 16);
140    
141          /* Generate RC4 keys */          /* Generate export keys from next two blocks of 16 bytes */
142          sec_hash_16(sec_decrypt_key, &session_key[16], client_key, server_key);          sec_hash_16(g_sec_decrypt_key, &key_block[16], client_random, server_random);
143          sec_hash_16(sec_encrypt_key, &session_key[32], client_key, server_key);          sec_hash_16(g_sec_encrypt_key, &key_block[32], client_random, server_random);
144    
145          if (rc4_key_size == 1)          if (rc4_key_size == 1)
146          {          {
147                  DEBUG(("40-bit encryption enabled\n"));                  DEBUG(("40-bit encryption enabled\n"));
148                  sec_make_40bit(sec_sign_key);                  sec_make_40bit(g_sec_sign_key);
149                  sec_make_40bit(sec_decrypt_key);                  sec_make_40bit(g_sec_decrypt_key);
150                  sec_make_40bit(sec_encrypt_key);                  sec_make_40bit(g_sec_encrypt_key);
151                  rc4_key_len = 8;                  g_rc4_key_len = 8;
152          }          }
153          else          else
154          {          {
155                  DEBUG(("rc_4_key_size == %d, 128-bit encryption enabled\n", rc4_key_size));                  DEBUG(("rc_4_key_size == %d, 128-bit encryption enabled\n", rc4_key_size));
156                  rc4_key_len = 16;                  g_rc4_key_len = 16;
157          }          }
158    
159          /* Save initial RC4 keys as update keys */          /* Save initial RC4 keys as update keys */
160          memcpy(sec_decrypt_update_key, sec_decrypt_key, 16);          memcpy(g_sec_decrypt_update_key, g_sec_decrypt_key, 16);
161          memcpy(sec_encrypt_update_key, sec_encrypt_key, 16);          memcpy(g_sec_encrypt_update_key, g_sec_encrypt_key, 16);
162    
163          /* Initialise RC4 state arrays */          /* Initialise RC4 state arrays */
164          RC4_set_key(&rc4_decrypt_key, rc4_key_len, sec_decrypt_key);          ssl_rc4_set_key(&g_rc4_decrypt_key, g_sec_decrypt_key, g_rc4_key_len);
165          RC4_set_key(&rc4_encrypt_key, rc4_key_len, sec_encrypt_key);          ssl_rc4_set_key(&g_rc4_encrypt_key, g_sec_encrypt_key, g_rc4_key_len);
166  }  }
167    
168  static uint8 pad_54[40] = {  static uint8 pad_54[40] = {
# Line 186  buf_out_uint32(uint8 * buffer, uint32 va Line 189  buf_out_uint32(uint8 * buffer, uint32 va
189          buffer[3] = (value >> 24) & 0xff;          buffer[3] = (value >> 24) & 0xff;
190  }  }
191    
192  /* 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 */
193  void  void
194  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)
195  {  {
196          uint8 shasig[20];          uint8 shasig[20];
197          uint8 md5sig[16];          uint8 md5sig[16];
198          uint8 lenhdr[4];          uint8 lenhdr[4];
199          SHA_CTX sha;          SSL_SHA1 sha1;
200          MD5_CTX md5;          SSL_MD5 md5;
201    
202          buf_out_uint32(lenhdr, datalen);          buf_out_uint32(lenhdr, datalen);
203    
204          SHA1_Init(&sha);          ssl_sha1_init(&sha1);
205          SHA1_Update(&sha, session_key, keylen);          ssl_sha1_update(&sha1, session_key, keylen);
206          SHA1_Update(&sha, pad_54, 40);          ssl_sha1_update(&sha1, pad_54, 40);
207          SHA1_Update(&sha, lenhdr, 4);          ssl_sha1_update(&sha1, lenhdr, 4);
208          SHA1_Update(&sha, data, datalen);          ssl_sha1_update(&sha1, data, datalen);
209          SHA1_Final(shasig, &sha);          ssl_sha1_final(&sha1, shasig);
210    
211          MD5_Init(&md5);          ssl_md5_init(&md5);
212          MD5_Update(&md5, session_key, keylen);          ssl_md5_update(&md5, session_key, keylen);
213          MD5_Update(&md5, pad_92, 48);          ssl_md5_update(&md5, pad_92, 48);
214          MD5_Update(&md5, shasig, 20);          ssl_md5_update(&md5, shasig, 20);
215          MD5_Final(md5sig, &md5);          ssl_md5_final(&md5, md5sig);
216    
217          memcpy(signature, md5sig, siglen);          memcpy(signature, md5sig, siglen);
218  }  }
219    
220  /* Update an encryption key - similar to the signing process */  /* Update an encryption key */
221  static void  static void
222  sec_update(uint8 * key, uint8 * update_key)  sec_update(uint8 * key, uint8 * update_key)
223  {  {
224          uint8 shasig[20];          uint8 shasig[20];
225          SHA_CTX sha;          SSL_SHA1 sha1;
226          MD5_CTX md5;          SSL_MD5 md5;
227          RC4_KEY update;          SSL_RC4 update;
228    
229          SHA1_Init(&sha);          ssl_sha1_init(&sha1);
230          SHA1_Update(&sha, update_key, rc4_key_len);          ssl_sha1_update(&sha1, update_key, g_rc4_key_len);
231          SHA1_Update(&sha, pad_54, 40);          ssl_sha1_update(&sha1, pad_54, 40);
232          SHA1_Update(&sha, key, rc4_key_len);          ssl_sha1_update(&sha1, key, g_rc4_key_len);
233          SHA1_Final(shasig, &sha);          ssl_sha1_final(&sha1, shasig);
234    
235          MD5_Init(&md5);          ssl_md5_init(&md5);
236          MD5_Update(&md5, update_key, rc4_key_len);          ssl_md5_update(&md5, update_key, g_rc4_key_len);
237          MD5_Update(&md5, pad_92, 48);          ssl_md5_update(&md5, pad_92, 48);
238          MD5_Update(&md5, shasig, 20);          ssl_md5_update(&md5, shasig, 20);
239          MD5_Final(key, &md5);          ssl_md5_final(&md5, key);
240    
241          RC4_set_key(&update, rc4_key_len, key);          ssl_rc4_set_key(&update, key, g_rc4_key_len);
242          RC4(&update, rc4_key_len, key, key);          ssl_rc4_crypt(&update, key, key, g_rc4_key_len);
243    
244          if (rc4_key_len == 8)          if (g_rc4_key_len == 8)
245                  sec_make_40bit(key);                  sec_make_40bit(key);
246  }  }
247    
# Line 246  sec_update(uint8 * key, uint8 * update_k Line 249  sec_update(uint8 * key, uint8 * update_k
249  static void  static void
250  sec_encrypt(uint8 * data, int length)  sec_encrypt(uint8 * data, int length)
251  {  {
252          static int use_count;          if (g_sec_encrypt_use_count == 4096)
   
         if (use_count == 4096)  
253          {          {
254                  sec_update(sec_encrypt_key, sec_encrypt_update_key);                  sec_update(g_sec_encrypt_key, g_sec_encrypt_update_key);
255                  RC4_set_key(&rc4_encrypt_key, rc4_key_len, sec_encrypt_key);                  ssl_rc4_set_key(&g_rc4_encrypt_key, g_sec_encrypt_key, g_rc4_key_len);
256                  use_count = 0;                  g_sec_encrypt_use_count = 0;
257          }          }
258    
259          RC4(&rc4_encrypt_key, length, data, data);          ssl_rc4_crypt(&g_rc4_encrypt_key, data, data, length);
260          use_count++;          g_sec_encrypt_use_count++;
261  }  }
262    
263  /* Decrypt data using RC4 */  /* Decrypt data using RC4 */
264  void  void
265  sec_decrypt(uint8 * data, int length)  sec_decrypt(uint8 * data, int length)
266  {  {
267          static int use_count;          if (g_sec_decrypt_use_count == 4096)
   
         if (use_count == 4096)  
268          {          {
269                  sec_update(sec_decrypt_key, sec_decrypt_update_key);                  sec_update(g_sec_decrypt_key, g_sec_decrypt_update_key);
270                  RC4_set_key(&rc4_decrypt_key, rc4_key_len, sec_decrypt_key);                  ssl_rc4_set_key(&g_rc4_decrypt_key, g_sec_decrypt_key, g_rc4_key_len);
271                  use_count = 0;                  g_sec_decrypt_use_count = 0;
272          }          }
273    
274          RC4(&rc4_decrypt_key, length, data, data);          ssl_rc4_crypt(&g_rc4_decrypt_key, data, data, length);
275          use_count++;          g_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;  
         }  
276  }  }
277    
278  /* Perform an RSA public key encryption operation */  /* Perform an RSA public key encryption operation */
279  static void  static void
280  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,
281                    uint8 * exponent)
282  {  {
283          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);  
284  }  }
285    
286  /* Initialise secure transport packet */  /* Initialise secure transport packet */
# Line 349  sec_send_to_channel(STREAM s, uint32 fla Line 306  sec_send_to_channel(STREAM s, uint32 fla
306  {  {
307          int datalen;          int datalen;
308    
309    #ifdef WITH_SCARD
310            scard_lock(SCARD_LOCK_SEC);
311    #endif
312    
313          s_pop_layer(s, sec_hdr);          s_pop_layer(s, sec_hdr);
314          if (!g_licence_issued || (flags & SEC_ENCRYPT))          if (!g_licence_issued || (flags & SEC_ENCRYPT))
315                  out_uint32_le(s, flags);                  out_uint32_le(s, flags);
# Line 363  sec_send_to_channel(STREAM s, uint32 fla Line 324  sec_send_to_channel(STREAM s, uint32 fla
324                  hexdump(s->p + 8, datalen);                  hexdump(s->p + 8, datalen);
325  #endif  #endif
326    
327                  sec_sign(s->p, 8, sec_sign_key, rc4_key_len, s->p + 8, datalen);                  sec_sign(s->p, 8, g_sec_sign_key, g_rc4_key_len, s->p + 8, datalen);
328                  sec_encrypt(s->p + 8, datalen);                  sec_encrypt(s->p + 8, datalen);
329          }          }
330    
331          mcs_send_to_channel(s, channel);          mcs_send_to_channel(s, channel);
332    
333    #ifdef WITH_SCARD
334            scard_unlock(SCARD_LOCK_SEC);
335    #endif
336  }  }
337    
338  /* Transmit secure transport packet */  /* Transmit secure transport packet */
# Line 383  sec_send(STREAM s, uint32 flags) Line 348  sec_send(STREAM s, uint32 flags)
348  static void  static void
349  sec_establish_key(void)  sec_establish_key(void)
350  {  {
351          uint32 length = SEC_MODULUS_SIZE + SEC_PADDING_SIZE;          uint32 length = g_server_public_key_len + SEC_PADDING_SIZE;
352          uint32 flags = SEC_CLIENT_RANDOM;          uint32 flags = SEC_CLIENT_RANDOM;
353          STREAM s;          STREAM s;
354    
355          s = sec_init(flags, 76);          s = sec_init(flags, length + 4);
356    
357          out_uint32_le(s, length);          out_uint32_le(s, length);
358          out_uint8p(s, sec_crypted_random, SEC_MODULUS_SIZE);          out_uint8p(s, g_sec_crypted_random, g_server_public_key_len);
359          out_uint8s(s, SEC_PADDING_SIZE);          out_uint8s(s, SEC_PADDING_SIZE);
360    
361          s_mark_end(s);          s_mark_end(s);
# Line 401  sec_establish_key(void) Line 366  sec_establish_key(void)
366  static void  static void
367  sec_out_mcs_data(STREAM s)  sec_out_mcs_data(STREAM s)
368  {  {
369          int hostlen = 2 * strlen(hostname);          int hostlen = 2 * strlen(g_hostname);
370          int length = 158 + 76 + 12 + 4;          int length = 158 + 76 + 12 + 4;
371          unsigned int i;          unsigned int i;
372    
# Line 411  sec_out_mcs_data(STREAM s) Line 376  sec_out_mcs_data(STREAM s)
376          if (hostlen > 30)          if (hostlen > 30)
377                  hostlen = 30;                  hostlen = 30;
378    
379          out_uint16_be(s, 5);    /* unknown */          /* Generic Conference Control (T.124) ConferenceCreateRequest */
380            out_uint16_be(s, 5);
381          out_uint16_be(s, 0x14);          out_uint16_be(s, 0x14);
382          out_uint8(s, 0x7c);          out_uint8(s, 0x7c);
383          out_uint16_be(s, 1);          out_uint16_be(s, 1);
# Line 424  sec_out_mcs_data(STREAM s) Line 390  sec_out_mcs_data(STREAM s)
390          out_uint16_le(s, 0xc001);          out_uint16_le(s, 0xc001);
391          out_uint8(s, 0);          out_uint8(s, 0);
392    
393          out_uint32_le(s, 0x61637544);   /* "Duca" ?! */          out_uint32_le(s, 0x61637544);   /* OEM ID: "Duca", as in Ducati. */
394          out_uint16_be(s, ((length - 14) | 0x8000));     /* remaining length */          out_uint16_be(s, ((length - 14) | 0x8000));     /* remaining length */
395    
396          /* Client information */          /* Client information */
# Line 432  sec_out_mcs_data(STREAM s) Line 398  sec_out_mcs_data(STREAM s)
398          out_uint16_le(s, 212);  /* length */          out_uint16_le(s, 212);  /* length */
399          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. */
400          out_uint16_le(s, 8);          out_uint16_le(s, 8);
401          out_uint16_le(s, width);          out_uint16_le(s, g_width);
402          out_uint16_le(s, height);          out_uint16_le(s, g_height);
403          out_uint16_le(s, 0xca01);          out_uint16_le(s, 0xca01);
404          out_uint16_le(s, 0xaa03);          out_uint16_le(s, 0xaa03);
405          out_uint32_le(s, keylayout);          out_uint32_le(s, g_keylayout);
406          out_uint32_le(s, 2600); /* Client build. We are now 2600 compatible :-) */          out_uint32_le(s, 2600); /* Client build. We are now 2600 compatible :-) */
407    
408          /* Unicode name of client, padded to 32 bytes */          /* Unicode name of client, padded to 32 bytes */
409          rdp_out_unistr(s, hostname, hostlen);          rdp_out_unistr(s, g_hostname, hostlen);
410          out_uint8s(s, 30 - hostlen);          out_uint8s(s, 30 - hostlen);
411    
412          out_uint32_le(s, 4);          /* See
413          out_uint32(s, 0);             http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wceddk40/html/cxtsksupportingremotedesktopprotocol.asp */
414          out_uint32_le(s, 12);          out_uint32_le(s, g_keyboard_type);
415            out_uint32_le(s, g_keyboard_subtype);
416            out_uint32_le(s, g_keyboard_functionkeys);
417          out_uint8s(s, 64);      /* reserved? 4 + 12 doublewords */          out_uint8s(s, 64);      /* reserved? 4 + 12 doublewords */
418            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;  
         }  
419          out_uint16_le(s, 1);          out_uint16_le(s, 1);
420    
421          out_uint32(s, 0);          out_uint32(s, 0);
422          out_uint8(s, g_server_bpp);          out_uint8(s, g_server_depth);
423          out_uint16_le(s, 0x0700);          out_uint16_le(s, 0x0700);
424          out_uint8(s, 0);          out_uint8(s, 0);
425          out_uint32_le(s, 1);          out_uint32_le(s, 1);
# Line 474  sec_out_mcs_data(STREAM s) Line 427  sec_out_mcs_data(STREAM s)
427    
428          out_uint16_le(s, SEC_TAG_CLI_4);          out_uint16_le(s, SEC_TAG_CLI_4);
429          out_uint16_le(s, 12);          out_uint16_le(s, 12);
430          out_uint32_le(s, 9);          out_uint32_le(s, g_console_session ? 0xb : 9);
431          out_uint32(s, 0);          out_uint32(s, 0);
432    
433          /* Client encryption settings */          /* Client encryption settings */
# Line 501  sec_out_mcs_data(STREAM s) Line 454  sec_out_mcs_data(STREAM s)
454  }  }
455    
456  /* Parse a public key structure */  /* Parse a public key structure */
457  static BOOL  static RD_BOOL
458  sec_parse_public_key(STREAM s, uint8 ** modulus, uint8 ** exponent)  sec_parse_public_key(STREAM s, uint8 * modulus, uint8 * exponent)
459  {  {
460          uint32 magic, modulus_len;          uint32 magic, modulus_len;
461    
# Line 514  sec_parse_public_key(STREAM s, uint8 ** Line 467  sec_parse_public_key(STREAM s, uint8 **
467          }          }
468    
469          in_uint32_le(s, modulus_len);          in_uint32_le(s, modulus_len);
470          if (modulus_len != SEC_MODULUS_SIZE + SEC_PADDING_SIZE)          modulus_len -= SEC_PADDING_SIZE;
471            if ((modulus_len < SEC_MODULUS_SIZE) || (modulus_len > SEC_MAX_MODULUS_SIZE))
472          {          {
473                  error("modulus len 0x%x\n", modulus_len);                  error("Bad server public key size (%u bits)\n", modulus_len * 8);
474                  return False;                  return False;
475          }          }
476    
477          in_uint8s(s, 8);        /* modulus_bits, unknown */          in_uint8s(s, 8);        /* modulus_bits, unknown */
478          in_uint8p(s, *exponent, SEC_EXPONENT_SIZE);          in_uint8a(s, exponent, SEC_EXPONENT_SIZE);
479          in_uint8p(s, *modulus, SEC_MODULUS_SIZE);          in_uint8a(s, modulus, modulus_len);
480          in_uint8s(s, SEC_PADDING_SIZE);          in_uint8s(s, SEC_PADDING_SIZE);
481            g_server_public_key_len = modulus_len;
482    
483          return s_check(s);          return s_check(s);
484  }  }
485    
486  static BOOL  /* Parse a public signature structure */
487  sec_parse_x509_key(X509 * cert)  static RD_BOOL
488  {  sec_parse_public_sig(STREAM s, uint32 len, uint8 * modulus, uint8 * exponent)
489          EVP_PKEY *epk = NULL;  {
490          /* By some reason, Microsoft sets the OID of the Public RSA key to          uint8 signature[SEC_MAX_MODULUS_SIZE];
491             the oid for "MD5 with RSA Encryption" instead of "RSA Encryption"          uint32 sig_len;
492    
493             Kudos to Richard Levitte for the following (. intiutive .)          if (len != 72)
494             lines of code that resets the OID and let's us extract the key. */          {
495          if (OBJ_obj2nid(cert->cert_info->key->algor->algorithm) == NID_md5WithRSAEncryption)                  return True;
496          {          }
497                  DEBUG_RDP5(("Re-setting algorithm type to RSA in server certificate\n"));          memset(signature, 0, sizeof(signature));
498                  cert->cert_info->key->algor->algorithm = OBJ_nid2obj(NID_rsaEncryption);          sig_len = len - 8;
499          }          in_uint8a(s, signature, sig_len);
500          epk = X509_get_pubkey(cert);          return ssl_sig_ok(exponent, SEC_EXPONENT_SIZE, modulus, g_server_public_key_len,
501          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;  
502  }  }
503    
   
504  /* Parse a crypto information structure */  /* Parse a crypto information structure */
505  static BOOL  static RD_BOOL
506  sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,  sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
507                       uint8 ** server_random, uint8 ** modulus, uint8 ** exponent)                       uint8 ** server_random, uint8 * modulus, uint8 * exponent)
508  {  {
509          uint32 crypt_level, random_len, rsa_info_len;          uint32 crypt_level, random_len, rsa_info_len;
510          uint32 cacert_len, cert_len, flags;          uint32 cacert_len, cert_len, flags;
511          X509 *cacert, *server_cert;          SSL_CERT *cacert, *server_cert;
512            SSL_RKEY *server_public_key;
513          uint16 tag, length;          uint16 tag, length;
514          uint8 *next_tag, *end;          uint8 *next_tag, *end;
515    
# Line 609  sec_parse_crypt_info(STREAM s, uint32 * Line 556  sec_parse_crypt_info(STREAM s, uint32 *
556                                          break;                                          break;
557    
558                                  case SEC_TAG_KEYSIG:                                  case SEC_TAG_KEYSIG:
559                                          /* Is this a Microsoft key that we just got? */                                          if (!sec_parse_public_sig(s, length, modulus, exponent))
560                                          /* 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. */  
561                                          break;                                          break;
562    
563                                  default:                                  default:
# Line 624  sec_parse_crypt_info(STREAM s, uint32 * Line 569  sec_parse_crypt_info(STREAM s, uint32 *
569          }          }
570          else          else
571          {          {
572                    uint32 certcount;
573    
574                  DEBUG_RDP5(("We're going for the RDP5-style encryption\n"));                  DEBUG_RDP5(("We're going for the RDP5-style encryption\n"));
575                  in_uint8s(s, 4);        /* Number of certificates */                  in_uint32_le(s, certcount);     /* Number of certificates */
576                    if (certcount < 2)
577                    {
578                            error("Server didn't send enough X509 certificates\n");
579                            return False;
580                    }
581                    for (; certcount > 2; certcount--)
582                    {               /* ignore all the certificates between the root and the signing CA */
583                            uint32 ignorelen;
584                            SSL_CERT *ignorecert;
585    
586                            DEBUG_RDP5(("Ignored certs left: %d\n", certcount));
587                            in_uint32_le(s, ignorelen);
588                            DEBUG_RDP5(("Ignored Certificate length is %d\n", ignorelen));
589                            ignorecert = ssl_cert_read(s->p, ignorelen);
590                            in_uint8s(s, ignorelen);
591                            if (ignorecert == NULL)
592                            {       /* XXX: error out? */
593                                    DEBUG_RDP5(("got a bad cert: this will probably screw up the rest of the communication\n"));
594                            }
595    
596                  /* Do da funky X.509 stuffy  #ifdef WITH_DEBUG_RDP5
597                            DEBUG_RDP5(("cert #%d (ignored):\n", certcount));
598                            ssl_cert_print_fp(stdout, ignorecert);
599    #endif
600                    }
601                    /* Do da funky X.509 stuffy
602    
603                     "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
604                     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 606  sec_parse_crypt_info(STREAM s, uint32 *
606                     - Peter Gutman in a early version of                     - Peter Gutman in a early version of
607                     http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt                     http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
608                   */                   */
   
609                  in_uint32_le(s, cacert_len);                  in_uint32_le(s, cacert_len);
610                  DEBUG_RDP5(("CA Certificate length is %d\n", cacert_len));                  DEBUG_RDP5(("CA Certificate length is %d\n", cacert_len));
611                  cacert = d2i_X509(NULL, &(s->p), cacert_len);                  cacert = ssl_cert_read(s->p, cacert_len);
612                  /* 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 */  
613                  if (NULL == cacert)                  if (NULL == cacert)
614                  {                  {
615                          error("Couldn't load CA Certificate from server\n");                          error("Couldn't load CA Certificate from server\n");
616                          return False;                          return False;
617                  }                  }
   
                 /* 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.  
                  */  
   
618                  in_uint32_le(s, cert_len);                  in_uint32_le(s, cert_len);
619                  DEBUG_RDP5(("Certificate length is %d\n", cert_len));                  DEBUG_RDP5(("Certificate length is %d\n", cert_len));
620                  server_cert = d2i_X509(NULL, &(s->p), cert_len);                  server_cert = ssl_cert_read(s->p, cert_len);
621                    in_uint8s(s, cert_len);
622                  if (NULL == server_cert)                  if (NULL == server_cert)
623                  {                  {
624                            ssl_cert_free(cacert);
625                          error("Couldn't load Certificate from server\n");                          error("Couldn't load Certificate from server\n");
626                          return False;                          return False;
627                  }                  }
628                    if (!ssl_certs_ok(server_cert, cacert))
629                    {
630                            ssl_cert_free(server_cert);
631                            ssl_cert_free(cacert);
632                            error("Security error CA Certificate invalid\n");
633                            return False;
634                    }
635                    ssl_cert_free(cacert);
636                  in_uint8s(s, 16);       /* Padding */                  in_uint8s(s, 16);       /* Padding */
637                    server_public_key = ssl_cert_to_rkey(server_cert, &g_server_public_key_len);
638                  /* 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))  
639                  {                  {
640                          DEBUG_RDP5(("Didn't parse X509 correctly\n"));                          DEBUG_RDP5(("Didn't parse X509 correctly\n"));
641                            ssl_cert_free(server_cert);
642                          return False;                          return False;
643                  }                  }
644                    ssl_cert_free(server_cert);
645                    if ((g_server_public_key_len < SEC_MODULUS_SIZE) ||
646                        (g_server_public_key_len > SEC_MAX_MODULUS_SIZE))
647                    {
648                            error("Bad server public key size (%u bits)\n",
649                                  g_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(g_sec_crypted_random, client_random, SEC_RANDOM_SIZE,
686          {                       /* Which means we should use                          g_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            g_sec_encrypt_use_count = 0;
894            g_sec_decrypt_use_count = 0;
895            mcs_reset_state();
896    }

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

  ViewVC Help
Powered by ViewVC 1.1.26