/[rdesktop]/sourceforge.net/trunk/rdesktop/secure.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/trunk/rdesktop/secure.c

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

revision 30 by matty, Fri Sep 14 13:51:38 2001 UTC revision 412 by forsberg, Fri Jun 6 11:07:46 2003 UTC
# Line 1  Line 1 
1  /*  /* -*- 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-2001     Copyright (C) Matthew Chapman 1999-2002
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    
23    #ifdef WITH_OPENSSL
24    #include <openssl/rc4.h>
25    #include <openssl/md5.h>
26    #include <openssl/sha.h>
27    #include <openssl/bn.h>
28    #include <openssl/x509v3.h>
29    #else
30  #include "crypto/rc4.h"  #include "crypto/rc4.h"
31  #include "crypto/md5.h"  #include "crypto/md5.h"
32  #include "crypto/sha.h"  #include "crypto/sha.h"
33  #include "crypto/arith.h"  #include "crypto/bn.h"
34    #endif
35    
36  extern char hostname[16];  extern char hostname[16];
37  extern int width;  extern int width;
38  extern int height;  extern int height;
39  extern int keylayout;  extern int keylayout;
40  extern BOOL encryption;  extern BOOL encryption;
41  extern BOOL licence_issued;  extern BOOL g_licence_issued;
42    extern BOOL use_rdp5;
43    extern int server_bpp;
44    extern uint16 mcs_userid;
45    
46  static int rc4_key_len;  static int rc4_key_len;
47  static RC4_KEY rc4_decrypt_key;  static RC4_KEY rc4_decrypt_key;
48  static RC4_KEY rc4_encrypt_key;  static RC4_KEY rc4_encrypt_key;
49    static RSA *server_public_key;
50    
51  static uint8 sec_sign_key[8];  static uint8 sec_sign_key[16];
52  static uint8 sec_decrypt_key[16];  static uint8 sec_decrypt_key[16];
53  static uint8 sec_encrypt_key[16];  static uint8 sec_encrypt_key[16];
54  static uint8 sec_decrypt_update_key[8];  static uint8 sec_decrypt_update_key[16];
55  static uint8 sec_encrypt_update_key[8];  static uint8 sec_encrypt_update_key[16];
56  static uint8 sec_crypted_random[64];  static uint8 sec_crypted_random[SEC_MODULUS_SIZE];
57    
58    uint16 server_rdp_version = 0;
59    
60  /*  /*
61   * General purpose 48-byte transformation, using two 32-byte salts (generally,   * General purpose 48-byte transformation, using two 32-byte salts (generally,
# Line 48  static uint8 sec_crypted_random[64]; Line 63  static uint8 sec_crypted_random[64];
63   * Both SHA1 and MD5 algorithms are used.   * Both SHA1 and MD5 algorithms are used.
64   */   */
65  void  void
66  sec_hash_48(uint8 *out, uint8 *in, uint8 *salt1, uint8 *salt2, uint8 salt)  sec_hash_48(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2, uint8 salt)
67  {  {
68          uint8 shasig[20];          uint8 shasig[20];
69          uint8 pad[4];          uint8 pad[4];
# Line 79  sec_hash_48(uint8 *out, uint8 *in, uint8 Line 94  sec_hash_48(uint8 *out, uint8 *in, uint8
94   * only using a single round of MD5.   * only using a single round of MD5.
95   */   */
96  void  void
97  sec_hash_16(uint8 *out, uint8 *in, uint8 *salt1, uint8 *salt2)  sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2)
98  {  {
99          MD5_CTX md5;          MD5_CTX md5;
100    
# Line 92  sec_hash_16(uint8 *out, uint8 *in, uint8 Line 107  sec_hash_16(uint8 *out, uint8 *in, uint8
107    
108  /* Reduce key entropy from 64 to 40 bits */  /* Reduce key entropy from 64 to 40 bits */
109  static void  static void
110  sec_make_40bit(uint8 *key)  sec_make_40bit(uint8 * key)
111  {  {
112          key[0] = 0xd1;          key[0] = 0xd1;
113          key[1] = 0x26;          key[1] = 0x26;
# Line 101  sec_make_40bit(uint8 *key) Line 116  sec_make_40bit(uint8 *key)
116    
117  /* Generate a session key and RC4 keys, given client and server randoms */  /* Generate a session key and RC4 keys, given client and server randoms */
118  static void  static void
119  sec_generate_keys(uint8 *client_key, uint8 *server_key, int rc4_key_size)  sec_generate_keys(uint8 * client_key, uint8 * server_key, int rc4_key_size)
120  {  {
121          uint8 session_key[48];          uint8 session_key[48];
122          uint8 temp_hash[48];          uint8 temp_hash[48];
# Line 115  sec_generate_keys(uint8 *client_key, uin Line 130  sec_generate_keys(uint8 *client_key, uin
130          sec_hash_48(temp_hash, input, client_key, server_key, 65);          sec_hash_48(temp_hash, input, client_key, server_key, 65);
131          sec_hash_48(session_key, temp_hash, client_key, server_key, 88);          sec_hash_48(session_key, temp_hash, client_key, server_key, 88);
132    
133          /* Store first 8 bytes of session key, for generating signatures */          /* Store first 16 bytes of session key, for generating signatures */
134          memcpy(sec_sign_key, session_key, 8);          memcpy(sec_sign_key, session_key, 16);
135    
136          /* Generate RC4 keys */          /* Generate RC4 keys */
137          sec_hash_16(sec_decrypt_key, &session_key[16], client_key,          sec_hash_16(sec_decrypt_key, &session_key[16], client_key, server_key);
138                      server_key);          sec_hash_16(sec_encrypt_key, &session_key[32], client_key, server_key);
         sec_hash_16(sec_encrypt_key, &session_key[32], client_key,  
                     server_key);  
139    
140          if (rc4_key_size == 1)          if (rc4_key_size == 1)
141          {          {
# Line 134  sec_generate_keys(uint8 *client_key, uin Line 147  sec_generate_keys(uint8 *client_key, uin
147          }          }
148          else          else
149          {          {
150                  DEBUG(("128-bit encryption enabled\n"));                  DEBUG(("rc_4_key_size == %d, 128-bit encryption enabled\n", rc4_key_size));
151                  rc4_key_len = 16;                  rc4_key_len = 16;
152          }          }
153    
154          /* Store first 8 bytes of RC4 keys as update keys */          /* Save initial RC4 keys as update keys */
155          memcpy(sec_decrypt_update_key, sec_decrypt_key, 8);          memcpy(sec_decrypt_update_key, sec_decrypt_key, 16);
156          memcpy(sec_encrypt_update_key, sec_encrypt_key, 8);          memcpy(sec_encrypt_update_key, sec_encrypt_key, 16);
157    
158          /* Initialise RC4 state arrays */          /* Initialise RC4 state arrays */
159          RC4_set_key(&rc4_decrypt_key, rc4_key_len, sec_decrypt_key);          RC4_set_key(&rc4_decrypt_key, rc4_key_len, sec_decrypt_key);
# Line 163  static uint8 pad_92[48] = { Line 176  static uint8 pad_92[48] = {
176    
177  /* Output a uint32 into a buffer (little-endian) */  /* Output a uint32 into a buffer (little-endian) */
178  void  void
179  buf_out_uint32(uint8 *buffer, uint32 value)  buf_out_uint32(uint8 * buffer, uint32 value)
180  {  {
181          buffer[0] = (value) & 0xff;          buffer[0] = (value) & 0xff;
182          buffer[1] = (value >> 8) & 0xff;          buffer[1] = (value >> 8) & 0xff;
# Line 173  buf_out_uint32(uint8 *buffer, uint32 val Line 186  buf_out_uint32(uint8 *buffer, uint32 val
186    
187  /* Generate a signature hash, using a combination of SHA1 and MD5 */  /* Generate a signature hash, using a combination of SHA1 and MD5 */
188  void  void
189  sec_sign(uint8 *signature, uint8 *session_key, int length,  sec_sign(uint8 * signature, int siglen, uint8 * session_key, int keylen, uint8 * data, int datalen)
          uint8 *data, int datalen)  
190  {  {
191          uint8 shasig[20];          uint8 shasig[20];
192          uint8 md5sig[16];          uint8 md5sig[16];
# Line 185  sec_sign(uint8 *signature, uint8 *sessio Line 197  sec_sign(uint8 *signature, uint8 *sessio
197          buf_out_uint32(lenhdr, datalen);          buf_out_uint32(lenhdr, datalen);
198    
199          SHA1_Init(&sha);          SHA1_Init(&sha);
200          SHA1_Update(&sha, session_key, length);          SHA1_Update(&sha, session_key, keylen);
201          SHA1_Update(&sha, pad_54, 40);          SHA1_Update(&sha, pad_54, 40);
202          SHA1_Update(&sha, lenhdr, 4);          SHA1_Update(&sha, lenhdr, 4);
203          SHA1_Update(&sha, data, datalen);          SHA1_Update(&sha, data, datalen);
204          SHA1_Final(shasig, &sha);          SHA1_Final(shasig, &sha);
205    
206          MD5_Init(&md5);          MD5_Init(&md5);
207          MD5_Update(&md5, session_key, length);          MD5_Update(&md5, session_key, keylen);
208          MD5_Update(&md5, pad_92, 48);          MD5_Update(&md5, pad_92, 48);
209          MD5_Update(&md5, shasig, 20);          MD5_Update(&md5, shasig, 20);
210          MD5_Final(md5sig, &md5);          MD5_Final(md5sig, &md5);
211    
212          memcpy(signature, md5sig, length);          memcpy(signature, md5sig, siglen);
213  }  }
214    
215  /* Update an encryption key - similar to the signing process */  /* Update an encryption key - similar to the signing process */
216  static void  static void
217  sec_update(uint8 *key, uint8 *update_key)  sec_update(uint8 * key, uint8 * update_key)
218  {  {
219          uint8 shasig[20];          uint8 shasig[20];
220          SHA_CTX sha;          SHA_CTX sha;
# Line 210  sec_update(uint8 *key, uint8 *update_key Line 222  sec_update(uint8 *key, uint8 *update_key
222          RC4_KEY update;          RC4_KEY update;
223    
224          SHA1_Init(&sha);          SHA1_Init(&sha);
225          SHA1_Update(&sha, update_key, 8);          SHA1_Update(&sha, update_key, rc4_key_len);
226          SHA1_Update(&sha, pad_54, 40);          SHA1_Update(&sha, pad_54, 40);
227          SHA1_Update(&sha, key, 8);          SHA1_Update(&sha, key, rc4_key_len);
228          SHA1_Final(shasig, &sha);          SHA1_Final(shasig, &sha);
229    
230          MD5_Init(&md5);          MD5_Init(&md5);
231          MD5_Update(&md5, update_key, 8);          MD5_Update(&md5, update_key, rc4_key_len);
232          MD5_Update(&md5, pad_92, 48);          MD5_Update(&md5, pad_92, 48);
233          MD5_Update(&md5, shasig, 20);          MD5_Update(&md5, shasig, 20);
234          MD5_Final(key, &md5);          MD5_Final(key, &md5);
# Line 230  sec_update(uint8 *key, uint8 *update_key Line 242  sec_update(uint8 *key, uint8 *update_key
242    
243  /* Encrypt data using RC4 */  /* Encrypt data using RC4 */
244  static void  static void
245  sec_encrypt(uint8 *data, int length)  sec_encrypt(uint8 * data, int length)
246  {  {
247          static int use_count;          static int use_count;
248    
# Line 246  sec_encrypt(uint8 *data, int length) Line 258  sec_encrypt(uint8 *data, int length)
258  }  }
259    
260  /* Decrypt data using RC4 */  /* Decrypt data using RC4 */
261  static void  void
262  sec_decrypt(uint8 *data, int length)  sec_decrypt(uint8 * data, int length)
263  {  {
264          static int use_count;          static int use_count;
265    
# Line 262  sec_decrypt(uint8 *data, int length) Line 274  sec_decrypt(uint8 *data, int length)
274          use_count++;          use_count++;
275  }  }
276    
 /* Read in a NUMBER from a buffer */  
 static void  
 sec_read_number(NUMBER * num, uint8 *buffer, int len)  
 {  
         INT *data = num->n_part;  
         int i, j;  
   
         for (i = 0, j = 0; j < len; i++, j += 2)  
                 data[i] = buffer[j] | (buffer[j + 1] << 8);  
   
         num->n_len = i;  
 }  
   
 /* Write a NUMBER to a buffer */  
277  static void  static void
278  sec_write_number(NUMBER * num, uint8 *buffer, int len)  reverse(uint8 * p, int len)
279  {  {
         INT *data = num->n_part;  
280          int i, j;          int i, j;
281            uint8 temp;
282    
283          for (i = 0, j = 0; j < len; i++, j += 2)          for (i = 0, j = len - 1; i < j; i++, j--)
284          {          {
285                  buffer[j] = data[i] & 0xff;                  temp = p[i];
286                  buffer[j + 1] = data[i] >> 8;                  p[i] = p[j];
287                    p[j] = temp;
288          }          }
289  }  }
290    
291  /* Perform an RSA public key encryption operation */  /* Perform an RSA public key encryption operation */
292  static void  static void
293  sec_rsa_encrypt(uint8 *out, uint8 *in, int len,  sec_rsa_encrypt(uint8 * out, uint8 * in, int len, uint8 * modulus, uint8 * exponent)
                 uint8 *modulus, uint8 *exponent)  
294  {  {
295          NUMBER data, key;          BN_CTX *ctx;
296            BIGNUM mod, exp, x, y;
297          /* Set modulus for arithmetic */          uint8 inr[SEC_MODULUS_SIZE];
298          sec_read_number(&key, modulus, SEC_MODULUS_SIZE);          int outlen;
299          m_init(&key, NULL);  
300            reverse(modulus, SEC_MODULUS_SIZE);
301          /* Exponentiate */          reverse(exponent, SEC_EXPONENT_SIZE);
302          sec_read_number(&data, in, len);          memcpy(inr, in, len);
303          sec_read_number(&key, exponent, SEC_EXPONENT_SIZE);          reverse(inr, len);
304          m_exp(&data, &key, &data);  
305          sec_write_number(&data, out, SEC_MODULUS_SIZE);          ctx = BN_CTX_new();
306            BN_init(&mod);
307            BN_init(&exp);
308            BN_init(&x);
309            BN_init(&y);
310    
311            BN_bin2bn(modulus, SEC_MODULUS_SIZE, &mod);
312            BN_bin2bn(exponent, SEC_EXPONENT_SIZE, &exp);
313            BN_bin2bn(inr, len, &x);
314            BN_mod_exp(&y, &x, &exp, &mod, ctx);
315            outlen = BN_bn2bin(&y, out);
316            reverse(out, outlen);
317            if (outlen < SEC_MODULUS_SIZE)
318                    memset(out + outlen, 0, SEC_MODULUS_SIZE - outlen);
319    
320            BN_free(&y);
321            BN_clear_free(&x);
322            BN_free(&exp);
323            BN_free(&mod);
324            BN_CTX_free(ctx);
325  }  }
326    
327  /* Initialise secure transport packet */  /* Initialise secure transport packet */
# Line 314  sec_init(uint32 flags, int maxlen) Line 331  sec_init(uint32 flags, int maxlen)
331          int hdrlen;          int hdrlen;
332          STREAM s;          STREAM s;
333    
334          if (!licence_issued)          if (!g_licence_issued)
335                  hdrlen = (flags & SEC_ENCRYPT) ? 12 : 4;                  hdrlen = (flags & SEC_ENCRYPT) ? 12 : 4;
336          else          else
337                  hdrlen = (flags & SEC_ENCRYPT) ? 12 : 0;                  hdrlen = (flags & SEC_ENCRYPT) ? 12 : 0;
# Line 324  sec_init(uint32 flags, int maxlen) Line 341  sec_init(uint32 flags, int maxlen)
341          return s;          return s;
342  }  }
343    
344  /* Transmit secure transport packet */  /* Transmit secure transport packet over specified channel */
345  void  void
346  sec_send(STREAM s, uint32 flags)  sec_send_to_channel(STREAM s, uint32 flags, uint16 channel)
347  {  {
348          int datalen;          int datalen;
349    
350          s_pop_layer(s, sec_hdr);          s_pop_layer(s, sec_hdr);
351          if (!licence_issued || (flags & SEC_ENCRYPT))          if (!g_licence_issued || (flags & SEC_ENCRYPT))
352                  out_uint32_le(s, flags);                  out_uint32_le(s, flags);
353    
354          if (flags & SEC_ENCRYPT)          if (flags & SEC_ENCRYPT)
# Line 344  sec_send(STREAM s, uint32 flags) Line 361  sec_send(STREAM s, uint32 flags)
361                  hexdump(s->p + 8, datalen);                  hexdump(s->p + 8, datalen);
362  #endif  #endif
363    
364                  sec_sign(s->p, sec_sign_key, 8, s->p + 8, datalen);                  sec_sign(s->p, 8, sec_sign_key, rc4_key_len, s->p + 8, datalen);
365                  sec_encrypt(s->p + 8, datalen);                  sec_encrypt(s->p + 8, datalen);
366          }          }
367    
368          mcs_send(s);          mcs_send_to_channel(s, channel);
369  }  }
370    
371    /* Transmit secure transport packet */
372    
373    void
374    sec_send(STREAM s, uint32 flags)
375    {
376            sec_send_to_channel(s, flags, MCS_GLOBAL_CHANNEL);
377    }
378    
379    
380  /* Transfer the client random to the server */  /* Transfer the client random to the server */
381  static void  static void
382  sec_establish_key()  sec_establish_key(void)
383  {  {
384          uint32 length = SEC_MODULUS_SIZE + SEC_PADDING_SIZE;          uint32 length = SEC_MODULUS_SIZE + SEC_PADDING_SIZE;
385          uint32 flags = SEC_CLIENT_RANDOM;          uint32 flags = SEC_CLIENT_RANDOM;
# Line 373  sec_establish_key() Line 399  sec_establish_key()
399  static void  static void
400  sec_out_mcs_data(STREAM s)  sec_out_mcs_data(STREAM s)
401  {  {
402            uint16 num_channels = get_num_channels();
403          int hostlen = 2 * strlen(hostname);          int hostlen = 2 * strlen(hostname);
404            int length = 158 + 76 + 12 + 4 + (CHANNEL_TAGDATA_SIZE * num_channels);
405            uint16 i;
406            rdp5_channel *channel;
407    
408            if (0 < num_channels)
409            {
410                    length += +4 + 4;
411            }
412    
413            if (hostlen > 30)
414                    hostlen = 30;
415    
416          out_uint16_be(s, 5);    /* unknown */          out_uint16_be(s, 5);    /* unknown */
417          out_uint16_be(s, 0x14);          out_uint16_be(s, 0x14);
418          out_uint8(s, 0x7c);          out_uint8(s, 0x7c);
419          out_uint16_be(s, 1);          out_uint16_be(s, 1);
420    
421          out_uint16_be(s, (158 | 0x8000));       /* remaining length */          out_uint16_be(s, (length | 0x8000));    /* remaining length */
422    
423          out_uint16_be(s, 8);    /* length? */          out_uint16_be(s, 8);    /* length? */
424          out_uint16_be(s, 16);          out_uint16_be(s, 16);
# Line 389  sec_out_mcs_data(STREAM s) Line 427  sec_out_mcs_data(STREAM s)
427          out_uint8(s, 0);          out_uint8(s, 0);
428    
429          out_uint32_le(s, 0x61637544);   /* "Duca" ?! */          out_uint32_le(s, 0x61637544);   /* "Duca" ?! */
430          out_uint16_be(s, (144 | 0x8000));       /* remaining length */          out_uint16_be(s, ((length - 14) | 0x8000));     /* remaining length */
431    
432          /* Client information */          /* Client information */
433          out_uint16_le(s, SEC_TAG_CLI_INFO);          out_uint16_le(s, SEC_TAG_CLI_INFO);
434          out_uint16_le(s, 136);  /* length */          out_uint16_le(s, 212);  /* length */
435          out_uint16_le(s, 1);          out_uint16_le(s, use_rdp5 ? 4 : 1);     /* RDP version. 1 == RDP4, 4 == RDP5. */
436          out_uint16_le(s, 8);          out_uint16_le(s, 8);
437          out_uint16_le(s, width);          out_uint16_le(s, width);
438          out_uint16_le(s, height);          out_uint16_le(s, height);
439          out_uint16_le(s, 0xca01);          out_uint16_le(s, 0xca01);
440          out_uint16_le(s, 0xaa03);          out_uint16_le(s, 0xaa03);
441          out_uint32_le(s, keylayout);          out_uint32_le(s, keylayout);
442          out_uint32_le(s, 419);  /* client build? we are 419 compatible :-) */          out_uint32_le(s, 2600); /* Client build. We are now 2600 compatible :-) */
443    
444          /* Unicode name of client, padded to 32 bytes */          /* Unicode name of client, padded to 32 bytes */
445          rdp_out_unistr(s, hostname, hostlen);          rdp_out_unistr(s, hostname, hostlen);
# Line 412  sec_out_mcs_data(STREAM s) Line 450  sec_out_mcs_data(STREAM s)
450          out_uint32_le(s, 12);          out_uint32_le(s, 12);
451          out_uint8s(s, 64);      /* reserved? 4 + 12 doublewords */          out_uint8s(s, 64);      /* reserved? 4 + 12 doublewords */
452    
453          out_uint16(s, 0xca01);          switch (server_bpp)
454          out_uint16(s, 0);          {
455                    case 8:
456                            out_uint16_le(s, 0xca01);
457                            break;
458                    case 15:
459                            out_uint16_le(s, 0xca02);
460                            break;
461                    case 16:
462                            out_uint16_le(s, 0xca03);
463                            break;
464                    case 24:
465                            out_uint16_le(s, 0xca04);
466                            break;
467            }
468            out_uint16_le(s, 1);
469    
470            out_uint32(s, 0);
471            out_uint8(s, server_bpp);
472            out_uint16_le(s, 0x0700);
473            out_uint8(s, 0);
474            out_uint32_le(s, 1);
475            out_uint8s(s, 64);      /* End of client info */
476    
477            out_uint16_le(s, SEC_TAG_CLI_4);
478            out_uint16_le(s, 12);
479            out_uint32_le(s, 9);
480            out_uint32(s, 0);
481    
482          /* Client encryption settings */          /* Client encryption settings */
483          out_uint16_le(s, SEC_TAG_CLI_CRYPT);          out_uint16_le(s, SEC_TAG_CLI_CRYPT);
484          out_uint16(s, 8);       /* length */          out_uint16_le(s, 12);   /* length */
485          out_uint32_le(s, encryption ? 1 : 0);   /* encryption enabled */          out_uint32_le(s, encryption ? 0x3 : 0); /* encryption supported, 128-bit supported */
486            out_uint32(s, 0);       /* Unknown */
487    
488            DEBUG_RDP5(("num_channels is %d\n", num_channels));
489            if (0 < num_channels)
490            {
491                    out_uint16_le(s, SEC_TAG_CLI_CHANNELS);
492                    out_uint16_le(s, num_channels * CHANNEL_TAGDATA_SIZE + 4 + 4);  /* length */
493                    out_uint32_le(s, num_channels); /* number of virtual channels */
494                    for (i = 0; i < num_channels; i++)
495                    {
496                            channel = find_channel_by_num(i);
497                            DEBUG_RDP5(("Requesting channel %s\n", channel->name));
498                            out_uint8p(s, channel->name, 8);
499                            out_uint32_be(s, channel->channelflags);
500                    }
501            }
502    
503          s_mark_end(s);          s_mark_end(s);
504  }  }
505    
506  /* Parse a public key structure */  /* Parse a public key structure */
507  static BOOL  static BOOL
508  sec_parse_public_key(STREAM s, uint8 **modulus, uint8 **exponent)  sec_parse_public_key(STREAM s, uint8 ** modulus, uint8 ** exponent)
509  {  {
510          uint32 magic, modulus_len;          uint32 magic, modulus_len;
511    
# Line 450  sec_parse_public_key(STREAM s, uint8 **m Line 531  sec_parse_public_key(STREAM s, uint8 **m
531          return s_check(s);          return s_check(s);
532  }  }
533    
534    static BOOL
535    sec_parse_x509_key(X509 * cert)
536    {
537            EVP_PKEY *epk = NULL;
538            /* By some reason, Microsoft sets the OID of the Public RSA key to
539               the oid for "MD5 with RSA Encryption" instead of "RSA Encryption"
540    
541               Kudos to Richard Levitte for the following (. intiutive .)
542               lines of code that resets the OID and let's us extract the key. */
543            if (OBJ_obj2nid(cert->cert_info->key->algor->algorithm) == NID_md5WithRSAEncryption)
544            {
545                    DEBUG_RDP5(("Re-setting algorithm type to RSA in server certificate\n"));
546                    cert->cert_info->key->algor->algorithm = OBJ_nid2obj(NID_rsaEncryption);
547            }
548            epk = X509_get_pubkey(cert);
549            if (NULL == epk)
550            {
551                    error("Failed to extract public key from certificate\n");
552                    return False;
553            }
554    
555            server_public_key = (RSA *) epk->pkey.ptr;
556    
557            return True;
558    }
559    
560    
561  /* Parse a crypto information structure */  /* Parse a crypto information structure */
562  static BOOL  static BOOL
563  sec_parse_crypt_info(STREAM s, uint32 *rc4_key_size,  sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
564                       uint8 **server_random, uint8 **modulus, uint8 **exponent)                       uint8 ** server_random, uint8 ** modulus, uint8 ** exponent)
565  {  {
566          uint32 crypt_level, random_len, rsa_info_len;          uint32 crypt_level, random_len, rsa_info_len;
567            uint32 cacert_len, cert_len, flags;
568            X509 *cacert, *server_cert;
569          uint16 tag, length;          uint16 tag, length;
570          uint8 *next_tag, *end;          uint8 *next_tag, *end;
571    
572          in_uint32_le(s, *rc4_key_size); /* 1 = 40-bit, 2 = 128-bit */          in_uint32_le(s, *rc4_key_size); /* 1 = 40-bit, 2 = 128-bit */
573          in_uint32_le(s, crypt_level);   /* 1 = low, 2 = medium, 3 = high */          in_uint32_le(s, crypt_level);   /* 1 = low, 2 = medium, 3 = high */
574            if (crypt_level == 0)   /* no encryption */
575                    return False;
576          in_uint32_le(s, random_len);          in_uint32_le(s, random_len);
577          in_uint32_le(s, rsa_info_len);          in_uint32_le(s, rsa_info_len);
578    
579          if (random_len != SEC_RANDOM_SIZE)          if (random_len != SEC_RANDOM_SIZE)
580          {          {
581                  error("random len %d\n", random_len);                  error("random len %d, expected %d\n", random_len, SEC_RANDOM_SIZE);
582                  return False;                  return False;
583          }          }
584    
# Line 477  sec_parse_crypt_info(STREAM s, uint32 *r Line 589  sec_parse_crypt_info(STREAM s, uint32 *r
589          if (end > s->end)          if (end > s->end)
590                  return False;                  return False;
591    
592          in_uint8s(s, 12);       /* unknown */          in_uint32_le(s, flags); /* 1 = RDP4-style, 0x80000002 = X.509 */
593            if (flags & 1)
594            {
595                    DEBUG_RDP5(("We're going for the RDP4-style encryption\n"));
596                    in_uint8s(s, 8);        /* unknown */
597    
598                    while (s->p < end)
599                    {
600                            in_uint16_le(s, tag);
601                            in_uint16_le(s, length);
602    
603          while (s->p < end)                          next_tag = s->p + length;
604    
605                            switch (tag)
606                            {
607                                    case SEC_TAG_PUBKEY:
608                                            if (!sec_parse_public_key(s, modulus, exponent))
609                                                    return False;
610                                            DEBUG_RDP5(("Got Public key, RDP4-style\n"));
611    
612                                            break;
613    
614                                    case SEC_TAG_KEYSIG:
615                                            /* Is this a Microsoft key that we just got? */
616                                            /* Care factor: zero! */
617                                            /* Actually, it would probably be a good idea to check if the public key is signed with this key, and then store this
618                                               key as a known key of the hostname. This would prevent some MITM-attacks. */
619                                            break;
620    
621                                    default:
622                                            unimpl("crypt tag 0x%x\n", tag);
623                            }
624    
625                            s->p = next_tag;
626                    }
627            }
628            else
629          {          {
630                  in_uint16_le(s, tag);                  DEBUG_RDP5(("We're going for the RDP5-style encryption\n"));
631                  in_uint16_le(s, length);                  in_uint8s(s, 4);        /* Number of certificates */
632    
633                  next_tag = s->p + length;                  /* Do da funky X.509 stuffy
634    
635                  switch (tag)                     "How did I find out about this?  I looked up and saw a
636                       bright light and when I came to I had a scar on my forehead
637                       and knew about X.500"
638                       - Peter Gutman in a early version of
639                       http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
640                     */
641    
642                    in_uint32_le(s, cacert_len);
643                    cacert = d2i_X509(NULL, &(s->p), cacert_len);
644                    /* Note: We don't need to move s->p here - d2i_X509 is
645                       "kind" enough to do it for us */
646                    if (NULL == cacert)
647                  {                  {
648                          case SEC_TAG_PUBKEY:                          error("Couldn't load CA Certificate from server\n");
649                                  if (!sec_parse_public_key                          return False;
650                                      (s, modulus, exponent))                  }
                                         return False;  
651    
652                                  break;                  /* Currently, we don't use the CA Certificate.
653                       FIXME:
654                       *) Verify the server certificate (server_cert) with the
655                       CA certificate.
656                       *) Store the CA Certificate with the hostname of the
657                       server we are connecting to as key, and compare it
658                       when we connect the next time, in order to prevent
659                       MITM-attacks.
660                     */
661    
662                    in_uint32_le(s, cert_len);
663                    server_cert = d2i_X509(NULL, &(s->p), cert_len);
664                    if (NULL == server_cert)
665                    {
666                            error("Couldn't load Certificate from server\n");
667                            return False;
668                    }
669    
670                          case SEC_TAG_KEYSIG:                  in_uint8s(s, 16);       /* Padding */
                                 /* Is this a Microsoft key that we just got? */  
                                 /* Care factor: zero! */  
                                 break;  
671    
672                          default:                  /* Note: Verifying the server certificate must be done here,
673                                  unimpl("crypt tag 0x%x\n", tag);                     before sec_parse_public_key since we'll have to apply
674                  }                     serious violence to the key after this */
675    
676                  s->p = next_tag;                  if (!sec_parse_x509_key(server_cert))
677                    {
678                            DEBUG_RDP5(("Didn't parse X509 correctly\n"));
679                            return False;
680                    }
681                    return True;    /* There's some garbage here we don't care about */
682          }          }
   
683          return s_check_end(s);          return s_check_end(s);
684  }  }
685    
# Line 517  sec_process_crypt_info(STREAM s) Line 690  sec_process_crypt_info(STREAM s)
690          uint8 *server_random, *modulus, *exponent;          uint8 *server_random, *modulus, *exponent;
691          uint8 client_random[SEC_RANDOM_SIZE];          uint8 client_random[SEC_RANDOM_SIZE];
692          uint32 rc4_key_size;          uint32 rc4_key_size;
693            uint8 inr[SEC_MODULUS_SIZE];
694    
695          if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random,          if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random, &modulus, &exponent))
696                                    &modulus, &exponent))          {
697                    DEBUG(("Failed to parse crypt info\n"));
698                  return;                  return;
699            }
700    
701            DEBUG(("Generating client random\n"));
702          /* Generate a client random, and hence determine encryption keys */          /* Generate a client random, and hence determine encryption keys */
703            // This is what the MS client do:
704            memset(inr, 0, SEC_RANDOM_SIZE);
705            /*  *ARIGL!* Plaintext attack, anyone?
706               I tried doing:
707               generate_random(inr);
708               ..but that generates connection errors now and then (yes,
709               "now and then". Something like 0 to 3 attempts needed before a
710               successful connection. Nice. Not!
711             */
712    
713          generate_random(client_random);          generate_random(client_random);
714          sec_rsa_encrypt(sec_crypted_random, client_random,          if (NULL != server_public_key)
715                          SEC_RANDOM_SIZE, modulus, exponent);          {                       /* Which means we should use
716                                       RDP5-style encryption */
717    
718                    memcpy(inr + SEC_RANDOM_SIZE, client_random, SEC_RANDOM_SIZE);
719                    reverse(inr + SEC_RANDOM_SIZE, SEC_RANDOM_SIZE);
720    
721                    RSA_public_encrypt(SEC_MODULUS_SIZE,
722                                       inr, sec_crypted_random, server_public_key, RSA_NO_PADDING);
723    
724                    reverse(sec_crypted_random, SEC_MODULUS_SIZE);
725    
726            }
727            else
728            {                       /* RDP4-style encryption */
729                    sec_rsa_encrypt(sec_crypted_random,
730                                    client_random, SEC_RANDOM_SIZE, modulus, exponent);
731            }
732          sec_generate_keys(client_random, server_random, rc4_key_size);          sec_generate_keys(client_random, server_random, rc4_key_size);
733  }  }
734    
735  /* Process connect response data blob */  
736    /* Process SRV_INFO, find RDP version supported by server */
737  static void  static void
738    sec_process_srv_info(STREAM s)
739    {
740            in_uint16_le(s, server_rdp_version);
741            DEBUG_RDP5(("Server RDP version is %d\n", server_rdp_version));
742    }
743    
744    
745    /* Process connect response data blob */
746    void
747  sec_process_mcs_data(STREAM s)  sec_process_mcs_data(STREAM s)
748  {  {
749          uint16 tag, length;          uint16 tag, length;
750          uint8 *next_tag;          uint8 *next_tag;
751            uint8 len;
752    
753          in_uint8s(s, 23);       /* header */          in_uint8s(s, 21);       /* header (T.124 stuff, probably) */
754            in_uint8(s, len);
755            if (len & 0x80)
756                    in_uint8(s, len);
757    
758          while (s->p < s->end)          while (s->p < s->end)
759          {          {
# Line 551  sec_process_mcs_data(STREAM s) Line 768  sec_process_mcs_data(STREAM s)
768                  switch (tag)                  switch (tag)
769                  {                  {
770                          case SEC_TAG_SRV_INFO:                          case SEC_TAG_SRV_INFO:
771                                    sec_process_srv_info(s);
772                                    break;
773    
774                          case SEC_TAG_SRV_3:                          case SEC_TAG_SRV_3:
775                                  break;                                  break;
776    
# Line 568  sec_process_mcs_data(STREAM s) Line 788  sec_process_mcs_data(STREAM s)
788    
789  /* Receive secure transport packet */  /* Receive secure transport packet */
790  STREAM  STREAM
791  sec_recv()  sec_recv(void)
792  {  {
793          uint32 sec_flags;          uint32 sec_flags;
794            uint16 channel;
795          STREAM s;          STREAM s;
796    
797          while ((s = mcs_recv()) != NULL)          while ((s = mcs_recv(&channel)) != NULL)
798          {          {
799                  if (encryption || !licence_issued)                  if (encryption || !g_licence_issued)
800                  {                  {
801                          in_uint32_le(s, sec_flags);                          in_uint32_le(s, sec_flags);
802    
803                          if (sec_flags & SEC_LICENCE_NEG)                          if (sec_flags & SEC_LICENCE_NEG)
804                          {                          {
805                                    if (sec_flags & SEC_ENCRYPT)
806                                    {
807                                            DEBUG_RDP5(("Encrypted license detected\n"));
808                                    }
809                                  licence_process(s);                                  licence_process(s);
810                                  continue;                                  continue;
811                          }                          }
# Line 592  sec_recv() Line 817  sec_recv()
817                          }                          }
818                  }                  }
819    
820                  return s;                  if (MCS_GLOBAL_CHANNEL == channel)
821                    {
822                            return s;
823                    }
824                    else
825                            rdp5_process_channel(s, channel);
826    
827          }          }
828    
829          return NULL;          return NULL;
# Line 600  sec_recv() Line 831  sec_recv()
831    
832  /* Establish a secure connection */  /* Establish a secure connection */
833  BOOL  BOOL
834  sec_connect(char *server)  sec_connect(char *server, char *username)
835  {  {
836          struct stream mcs_data;          struct stream mcs_data;
837    
838          /* We exchange some RDP data during the MCS-Connect */          /* We exchange some RDP data during the MCS-Connect */
839          mcs_data.size = 512;          mcs_data.size = 512;
840          mcs_data.p = mcs_data.data = xmalloc(mcs_data.size);          mcs_data.p = mcs_data.data = (uint8 *) xmalloc(mcs_data.size);
841          sec_out_mcs_data(&mcs_data);          sec_out_mcs_data(&mcs_data);
842    
843          if (!mcs_connect(server, &mcs_data))          if (!mcs_connect(server, &mcs_data, username))
844                  return False;                  return False;
845    
846          sec_process_mcs_data(&mcs_data);          //      sec_process_mcs_data(&mcs_data);
847          if (encryption)          if (encryption)
848                  sec_establish_key();                  sec_establish_key();
849            xfree(mcs_data.data);
850          return True;          return True;
851  }  }
852    
853  /* Disconnect a connection */  /* Disconnect a connection */
854  void  void
855  sec_disconnect()  sec_disconnect(void)
856  {  {
857          mcs_disconnect();          mcs_disconnect();
858  }  }

Legend:
Removed from v.30  
changed lines
  Added in v.412

  ViewVC Help
Powered by ViewVC 1.1.26