ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

secure.c
Go to the documentation of this file.
00001 /* -*- c-basic-offset: 8 -*-
00002    rdesktop: A Remote Desktop Protocol client.
00003    Protocol services - RDP encryption and licensing
00004    Copyright (C) Matthew Chapman 1999-2005
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010 
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015 
00016    You should have received a copy of the GNU General Public License along
00017    with this program; if not, write to the Free Software Foundation, Inc.,
00018    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00019 */
00020 
00021 #include <precomp.h>
00022 
00023 //#include <openssl/rc4.h>
00024 //#include <openssl/md5.h>
00025 //#include <openssl/sha.h>
00026 //#include <openssl/bn.h>
00027 //#include <openssl/x509v3.h>
00028 
00029 void *
00030 ssl_sha1_info_create(void);
00031 void
00032 ssl_sha1_info_delete(void * sha1_info);
00033 void
00034 ssl_sha1_clear(void * sha1_info);
00035 void
00036 ssl_sha1_transform(void * sha1_info, char * data, int len);
00037 void
00038 ssl_sha1_complete(void * sha1_info, char * data);
00039 void *
00040 ssl_md5_info_create(void);
00041 void
00042 ssl_md5_info_delete(void * md5_info);
00043 void *
00044 ssl_md5_info_create(void);
00045 void
00046 ssl_md5_info_delete(void * md5_info);
00047 void
00048 ssl_md5_clear(void * md5_info);
00049 void
00050 ssl_md5_transform(void * md5_info, char * data, int len);
00051 void
00052 ssl_md5_complete(void * md5_info, char * data);
00053 void *
00054 ssl_rc4_info_create(void);
00055 void
00056 ssl_rc4_info_delete(void * rc4_info);
00057 void
00058 ssl_rc4_set_key(void * rc4_info, char * key, int len);
00059 void
00060 ssl_rc4_crypt(void * rc4_info, char * in_data, char * out_data, int len);
00061 int
00062 ssl_mod_exp(char* out, int out_len, char* in, int in_len,
00063             char* mod, int mod_len, char* exp, int exp_len);
00064 
00065 extern char g_hostname[];
00066 extern int g_width;
00067 extern int g_height;
00068 extern unsigned int g_keylayout;
00069 extern int g_keyboard_type;
00070 extern int g_keyboard_subtype;
00071 extern int g_keyboard_functionkeys;
00072 extern BOOL g_encryption;
00073 extern BOOL g_licence_issued;
00074 extern BOOL g_use_rdp5;
00075 extern BOOL g_console_session;
00076 extern int g_server_depth;
00077 extern uint16 mcs_userid;
00078 extern VCHANNEL g_channels[];
00079 extern unsigned int g_num_channels;
00080 
00081 static int rc4_key_len;
00082 static void * rc4_decrypt_key = 0;
00083 static void * rc4_encrypt_key = 0;
00084 //static RSA *server_public_key;
00085 static void * server_public_key;
00086 
00087 static uint8 sec_sign_key[16];
00088 static uint8 sec_decrypt_key[16];
00089 static uint8 sec_encrypt_key[16];
00090 static uint8 sec_decrypt_update_key[16];
00091 static uint8 sec_encrypt_update_key[16];
00092 static uint8 sec_crypted_random[SEC_MODULUS_SIZE];
00093 
00094 uint16 g_server_rdp_version = 0;
00095 
00096 /* These values must be available to reset state - Session Directory */
00097 static int sec_encrypt_use_count = 0;
00098 static int sec_decrypt_use_count = 0;
00099 
00100 /*
00101  * I believe this is based on SSLv3 with the following differences:
00102  *  MAC algorithm (5.2.3.1) uses only 32-bit length in place of seq_num/type/length fields
00103  *  MAC algorithm uses SHA1 and MD5 for the two hash functions instead of one or other
00104  *  key_block algorithm (6.2.2) uses 'X', 'YY', 'ZZZ' instead of 'A', 'BB', 'CCC'
00105  *  key_block partitioning is different (16 bytes each: MAC secret, decrypt key, encrypt key)
00106  *  encryption/decryption keys updated every 4096 packets
00107  * See http://wp.netscape.com/eng/ssl3/draft302.txt
00108  */
00109 
00110 /*
00111  * 48-byte transformation used to generate master secret (6.1) and key material (6.2.2).
00112  * Both SHA1 and MD5 algorithms are used.
00113  */
00114 void
00115 sec_hash_48(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2, uint8 salt)
00116 {
00117     uint8 shasig[20];
00118     uint8 pad[4];
00119     void * sha;
00120     void * md5;
00121     int i;
00122 
00123     for (i = 0; i < 3; i++)
00124     {
00125         memset(pad, salt + i, i + 1);
00126         sha = ssl_sha1_info_create();
00127         ssl_sha1_clear(sha);
00128         ssl_sha1_transform(sha, (char *)pad, i + 1);
00129         ssl_sha1_transform(sha, (char *)in, 48);
00130         ssl_sha1_transform(sha, (char *)salt1, 32);
00131         ssl_sha1_transform(sha, (char *)salt2, 32);
00132         ssl_sha1_complete(sha, (char *)shasig);
00133         ssl_sha1_info_delete(sha);
00134         md5 = ssl_md5_info_create();
00135         ssl_md5_clear(md5);
00136         ssl_md5_transform(md5, (char *)in, 48);
00137         ssl_md5_transform(md5, (char *)shasig, 20);
00138         ssl_md5_complete(md5, (char *)out + i * 16);
00139         ssl_md5_info_delete(md5);
00140     }
00141 }
00142 
00143 /*
00144  * 16-byte transformation used to generate export keys (6.2.2).
00145  */
00146 void
00147 sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2)
00148 {
00149     void * md5;
00150     
00151     md5 = ssl_md5_info_create();
00152     ssl_md5_clear(md5);
00153     ssl_md5_transform(md5, (char *)in, 16);
00154     ssl_md5_transform(md5, (char *)salt1, 32);
00155     ssl_md5_transform(md5, (char *)salt2, 32);
00156     ssl_md5_complete(md5, (char *)out);
00157     ssl_md5_info_delete(md5);
00158 }
00159 
00160 /* Reduce key entropy from 64 to 40 bits */
00161 static void
00162 sec_make_40bit(uint8 * key)
00163 {
00164     key[0] = 0xd1;
00165     key[1] = 0x26;
00166     key[2] = 0x9e;
00167 }
00168 
00169 /* Generate encryption keys given client and server randoms */
00170 static void
00171 sec_generate_keys(uint8 * client_random, uint8 * server_random, int rc4_key_size)
00172 {
00173     uint8 pre_master_secret[48];
00174     uint8 master_secret[48];
00175     uint8 key_block[48];
00176 
00177     /* Construct pre-master secret */
00178     memcpy(pre_master_secret, client_random, 24);
00179     memcpy(pre_master_secret + 24, server_random, 24);
00180 
00181     /* Generate master secret and then key material */
00182     sec_hash_48(master_secret, pre_master_secret, client_random, server_random, 'A');
00183     sec_hash_48(key_block, master_secret, client_random, server_random, 'X');
00184 
00185     /* First 16 bytes of key material is MAC secret */
00186     memcpy(sec_sign_key, key_block, 16);
00187 
00188     /* Generate export keys from next two blocks of 16 bytes */
00189     sec_hash_16(sec_decrypt_key, &key_block[16], client_random, server_random);
00190     sec_hash_16(sec_encrypt_key, &key_block[32], client_random, server_random);
00191 
00192     if (rc4_key_size == 1)
00193     {
00194         DEBUG(("40-bit encryption enabled\n"));
00195         sec_make_40bit(sec_sign_key);
00196         sec_make_40bit(sec_decrypt_key);
00197         sec_make_40bit(sec_encrypt_key);
00198         rc4_key_len = 8;
00199     }
00200     else
00201     {
00202         DEBUG(("rc_4_key_size == %d, 128-bit encryption enabled\n", rc4_key_size));
00203         rc4_key_len = 16;
00204     }
00205 
00206     /* Save initial RC4 keys as update keys */
00207     memcpy(sec_decrypt_update_key, sec_decrypt_key, 16);
00208     memcpy(sec_encrypt_update_key, sec_encrypt_key, 16);
00209 
00210     /* Initialise RC4 state arrays */
00211 
00212     ssl_rc4_info_delete(rc4_decrypt_key);
00213     rc4_decrypt_key = ssl_rc4_info_create(); 
00214     ssl_rc4_set_key(rc4_decrypt_key, (char *)sec_decrypt_key, rc4_key_len); 
00215 
00216     ssl_rc4_info_delete(rc4_encrypt_key);
00217     rc4_encrypt_key = ssl_rc4_info_create(); 
00218     ssl_rc4_set_key(rc4_encrypt_key, (char *)sec_encrypt_key, rc4_key_len); 
00219 }
00220 
00221 static uint8 pad_54[40] = {
00222     54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
00223     54, 54, 54,
00224     54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
00225     54, 54, 54
00226 };
00227 
00228 static uint8 pad_92[48] = {
00229     92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
00230     92, 92, 92, 92, 92, 92, 92,
00231     92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
00232     92, 92, 92, 92, 92, 92, 92
00233 };
00234 
00235 /* Output a uint32 into a buffer (little-endian) */
00236 void
00237 buf_out_uint32(uint8 * buffer, uint32 value)
00238 {
00239     buffer[0] = (value) & 0xff;
00240     buffer[1] = (value >> 8) & 0xff;
00241     buffer[2] = (value >> 16) & 0xff;
00242     buffer[3] = (value >> 24) & 0xff;
00243 }
00244 
00245 /* Generate a MAC hash (5.2.3.1), using a combination of SHA1 and MD5 */
00246 void
00247 sec_sign(uint8 * signature, int siglen, uint8 * session_key, int keylen, uint8 * data, int datalen)
00248 {
00249     uint8 shasig[20];
00250     uint8 md5sig[16];
00251     uint8 lenhdr[4];
00252     void * sha;
00253     void * md5;
00254 
00255     buf_out_uint32(lenhdr, datalen);
00256 
00257     sha = ssl_sha1_info_create();
00258     ssl_sha1_clear(sha);
00259     ssl_sha1_transform(sha, (char *)session_key, keylen);
00260     ssl_sha1_transform(sha, (char *)pad_54, 40);
00261     ssl_sha1_transform(sha, (char *)lenhdr, 4);
00262     ssl_sha1_transform(sha, (char *)data, datalen);
00263     ssl_sha1_complete(sha, (char *)shasig);
00264     ssl_sha1_info_delete(sha);
00265 
00266     md5 = ssl_md5_info_create();
00267     ssl_md5_clear(md5);
00268     ssl_md5_transform(md5, (char *)session_key, keylen);
00269     ssl_md5_transform(md5, (char *)pad_92, 48);
00270     ssl_md5_transform(md5, (char *)shasig, 20);
00271     ssl_md5_complete(md5, (char *)md5sig);
00272     ssl_md5_info_delete(md5);
00273 
00274     memcpy(signature, md5sig, siglen);
00275 }
00276 
00277 /* Update an encryption key */
00278 static void
00279 sec_update(uint8 * key, uint8 * update_key)
00280 {
00281     uint8 shasig[20];
00282     void * sha;
00283     void * md5;
00284     void * update;
00285 
00286     sha = ssl_sha1_info_create();
00287     ssl_sha1_clear(sha);
00288     ssl_sha1_transform(sha, (char *)update_key, rc4_key_len);
00289     ssl_sha1_transform(sha, (char *)pad_54, 40);
00290     ssl_sha1_transform(sha, (char *)key, rc4_key_len);
00291     ssl_sha1_complete(sha, (char *)shasig);
00292     ssl_sha1_info_delete(sha);
00293 
00294     md5 = ssl_md5_info_create();
00295     ssl_md5_clear(md5);
00296     ssl_md5_transform(md5, (char *)update_key, rc4_key_len);
00297     ssl_md5_transform(md5, (char *)pad_92, 48);
00298     ssl_md5_transform(md5, (char *)shasig, 20);
00299     ssl_md5_complete(md5, (char *)key);
00300     ssl_md5_info_delete(md5);
00301 
00302 
00303     update = ssl_rc4_info_create();
00304     ssl_rc4_set_key(update, (char *)key, rc4_key_len);
00305     ssl_rc4_crypt(update, (char *)key, (char *)key, rc4_key_len);
00306     ssl_rc4_info_delete(update);
00307     
00308     if (rc4_key_len == 8)
00309         sec_make_40bit(key);
00310 }
00311 
00312 /* Encrypt data using RC4 */
00313 static void
00314 sec_encrypt(uint8 * data, int length)
00315 {
00316     if (sec_encrypt_use_count == 4096)
00317     {
00318         sec_update(sec_encrypt_key, sec_encrypt_update_key);
00319         ssl_rc4_set_key(rc4_encrypt_key, (char *)sec_encrypt_key, rc4_key_len);
00320         sec_encrypt_use_count = 0;
00321     }
00322     ssl_rc4_crypt(rc4_encrypt_key, (char *)data, (char *)data, length);
00323     sec_encrypt_use_count++;
00324 }
00325 
00326 /* Decrypt data using RC4 */
00327 void
00328 sec_decrypt(uint8 * data, int length)
00329 {
00330     if (sec_decrypt_use_count == 4096)
00331     {
00332         sec_update(sec_decrypt_key, sec_decrypt_update_key);
00333         ssl_rc4_set_key(rc4_decrypt_key, (char *)sec_decrypt_key, rc4_key_len);
00334         sec_decrypt_use_count = 0;
00335     }
00336     ssl_rc4_crypt(rc4_decrypt_key, (char *)data, (char *)data, length);
00337     sec_decrypt_use_count++;
00338 }
00339 
00340 /*static void
00341 reverse(uint8 * p, int len)
00342 {
00343     int i, j;
00344     uint8 temp;
00345 
00346     for (i = 0, j = len - 1; i < j; i++, j--)
00347     {
00348         temp = p[i];
00349         p[i] = p[j];
00350         p[j] = temp;
00351     }
00352 }*/
00353 
00354 /* Perform an RSA public key encryption operation */
00355 static void
00356 sec_rsa_encrypt(uint8 * out, uint8 * in, int len, uint8 * modulus, uint8 * exponent)
00357 {
00358     ssl_mod_exp((char *)out, 64, (char *)in, 32, (char *)modulus, 64, (char *)exponent, 4);
00359 /*
00360     BN_CTX *ctx;
00361     BIGNUM mod, exp, x, y;
00362     uint8 inr[SEC_MODULUS_SIZE];
00363     int outlen;
00364 
00365     reverse(modulus, SEC_MODULUS_SIZE);
00366     reverse(exponent, SEC_EXPONENT_SIZE);
00367     memcpy(inr, in, len);
00368     reverse(inr, len);
00369 
00370     ctx = BN_CTX_new();
00371     BN_init(&mod);
00372     BN_init(&exp);
00373     BN_init(&x);
00374     BN_init(&y);
00375 
00376     BN_bin2bn(modulus, SEC_MODULUS_SIZE, &mod);
00377     BN_bin2bn(exponent, SEC_EXPONENT_SIZE, &exp);
00378     BN_bin2bn(inr, len, &x);
00379     BN_mod_exp(&y, &x, &exp, &mod, ctx);
00380     outlen = BN_bn2bin(&y, out);
00381     reverse(out, outlen);
00382     if (outlen < SEC_MODULUS_SIZE)
00383         memset(out + outlen, 0, SEC_MODULUS_SIZE - outlen);
00384 
00385     BN_free(&y);
00386     BN_clear_free(&x);
00387     BN_free(&exp);
00388     BN_free(&mod);
00389     BN_CTX_free(ctx);*/
00390 }
00391 
00392 /* Initialise secure transport packet */
00393 STREAM
00394 sec_init(uint32 flags, int maxlen)
00395 {
00396     int hdrlen;
00397     STREAM s;
00398 
00399     if (!g_licence_issued)
00400         hdrlen = (flags & SEC_ENCRYPT) ? 12 : 4;
00401     else
00402         hdrlen = (flags & SEC_ENCRYPT) ? 12 : 0;
00403     s = mcs_init(maxlen + hdrlen);
00404     s_push_layer(s, sec_hdr, hdrlen);
00405 
00406     return s;
00407 }
00408 
00409 /* Transmit secure transport packet over specified channel */
00410 void
00411 sec_send_to_channel(STREAM s, uint32 flags, uint16 channel)
00412 {
00413     int datalen;
00414 
00415     s_pop_layer(s, sec_hdr);
00416     if (!g_licence_issued || (flags & SEC_ENCRYPT))
00417         out_uint32_le(s, flags);
00418 
00419     if (flags & SEC_ENCRYPT)
00420     {
00421         flags &= ~SEC_ENCRYPT;
00422         datalen = s->end - s->p - 8;
00423 
00424 #ifdef WITH_DEBUG
00425         DEBUG(("Sending encrypted packet:\n"));
00426         hexdump(s->p + 8, datalen);
00427 #endif
00428 
00429         sec_sign(s->p, 8, sec_sign_key, rc4_key_len, s->p + 8, datalen);
00430         sec_encrypt(s->p + 8, datalen);
00431     }
00432 
00433     mcs_send_to_channel(s, channel);
00434 }
00435 
00436 /* Transmit secure transport packet */
00437 
00438 void
00439 sec_send(STREAM s, uint32 flags)
00440 {
00441     sec_send_to_channel(s, flags, MCS_GLOBAL_CHANNEL);
00442 }
00443 
00444 
00445 /* Transfer the client random to the server */
00446 static void
00447 sec_establish_key(void)
00448 {
00449     uint32 length = SEC_MODULUS_SIZE + SEC_PADDING_SIZE;
00450     uint32 flags = SEC_CLIENT_RANDOM;
00451     STREAM s;
00452 
00453     s = sec_init(flags, 76);
00454 
00455     out_uint32_le(s, length);
00456     out_uint8p(s, sec_crypted_random, SEC_MODULUS_SIZE);
00457     out_uint8s(s, SEC_PADDING_SIZE);
00458 
00459     s_mark_end(s);
00460     sec_send(s, flags);
00461 }
00462 
00463 /* Output connect initial data blob */
00464 static void
00465 sec_out_mcs_data(STREAM s)
00466 {
00467     int hostlen = 2 * strlen(g_hostname);
00468     int length = 158 + 76 + 12 + 4;
00469     unsigned int i;
00470 
00471     if (g_num_channels > 0)
00472         length += g_num_channels * 12 + 8;
00473 
00474     if (hostlen > 30)
00475         hostlen = 30;
00476 
00477     /* Generic Conference Control (T.124) ConferenceCreateRequest */
00478     out_uint16_be(s, 5);
00479     out_uint16_be(s, 0x14);
00480     out_uint8(s, 0x7c);
00481     out_uint16_be(s, 1);
00482 
00483     out_uint16_be(s, (length | 0x8000));    /* remaining length */
00484 
00485     out_uint16_be(s, 8);    /* length? */
00486     out_uint16_be(s, 16);
00487     out_uint8(s, 0);
00488     out_uint16_le(s, 0xc001);
00489     out_uint8(s, 0);
00490 
00491     out_uint32_le(s, 0x61637544);   /* OEM ID: "Duca", as in Ducati. */
00492     out_uint16_be(s, ((length - 14) | 0x8000)); /* remaining length */
00493 
00494     /* Client information */
00495     out_uint16_le(s, SEC_TAG_CLI_INFO);
00496     out_uint16_le(s, 212);  /* length */
00497     out_uint16_le(s, g_use_rdp5 ? 4 : 1);   /* RDP version. 1 == RDP4, 4 == RDP5. */
00498     out_uint16_le(s, 8);
00499     out_uint16_le(s, g_width);
00500     out_uint16_le(s, g_height);
00501     out_uint16_le(s, 0xca01);
00502     out_uint16_le(s, 0xaa03);
00503     out_uint32_le(s, g_keylayout);
00504     out_uint32_le(s, 2600); /* Client build. We are now 2600 compatible :-) */
00505 
00506     /* Unicode name of client, padded to 32 bytes */
00507     rdp_out_unistr(s, g_hostname, hostlen);
00508     out_uint8s(s, 30 - hostlen);
00509 
00510     /* See
00511        http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wceddk40/html/cxtsksupportingremotedesktopprotocol.asp */
00512     out_uint32_le(s, g_keyboard_type);
00513     out_uint32_le(s, g_keyboard_subtype);
00514     out_uint32_le(s, g_keyboard_functionkeys);
00515     out_uint8s(s, 64);  /* reserved? 4 + 12 doublewords */
00516     out_uint16_le(s, 0xca01);   /* colour depth? */
00517     out_uint16_le(s, 1);
00518 
00519     out_uint32(s, 0);
00520     out_uint8(s, g_server_depth);
00521     out_uint16_le(s, 0x0700);
00522     out_uint8(s, 0);
00523     out_uint32_le(s, 1);
00524     out_uint8s(s, 64);  /* End of client info */
00525 
00526     out_uint16_le(s, SEC_TAG_CLI_4);
00527     out_uint16_le(s, 12);
00528     out_uint32_le(s, g_console_session ? 0xb : 9);
00529     out_uint32(s, 0);
00530 
00531     /* Client encryption settings */
00532     out_uint16_le(s, SEC_TAG_CLI_CRYPT);
00533     out_uint16_le(s, 12);   /* length */
00534     out_uint32_le(s, g_encryption ? 0x3 : 0);   /* encryption supported, 128-bit supported */
00535     out_uint32(s, 0);   /* Unknown */
00536 
00537     DEBUG_RDP5(("g_num_channels is %d\n", g_num_channels));
00538     if (g_num_channels > 0)
00539     {
00540         out_uint16_le(s, SEC_TAG_CLI_CHANNELS);
00541         out_uint16_le(s, g_num_channels * 12 + 8);  /* length */
00542         out_uint32_le(s, g_num_channels);   /* number of virtual channels */
00543         for (i = 0; i < g_num_channels; i++)
00544         {
00545             DEBUG_RDP5(("Requesting channel %s\n", g_channels[i].name));
00546             out_uint8a(s, g_channels[i].name, 8);
00547             out_uint32_be(s, g_channels[i].flags);
00548         }
00549     }
00550 
00551     s_mark_end(s);
00552 }
00553 
00554 /* Parse a public key structure */
00555 static BOOL
00556 sec_parse_public_key(STREAM s, uint8 ** modulus, uint8 ** exponent)
00557 {
00558     uint32 magic, modulus_len;
00559 
00560     in_uint32_le(s, magic);
00561     if (magic != SEC_RSA_MAGIC)
00562     {
00563         error("RSA magic 0x%x\n", magic);
00564         return False;
00565     }
00566 
00567     in_uint32_le(s, modulus_len);
00568     if (modulus_len != SEC_MODULUS_SIZE + SEC_PADDING_SIZE)
00569     {
00570         error("modulus len 0x%x\n", modulus_len);
00571         return False;
00572     }
00573 
00574     in_uint8s(s, 8);    /* modulus_bits, unknown */
00575     in_uint8p(s, *exponent, SEC_EXPONENT_SIZE);
00576     in_uint8p(s, *modulus, SEC_MODULUS_SIZE);
00577     in_uint8s(s, SEC_PADDING_SIZE);
00578 
00579     return s_check(s);
00580 }
00581 
00582 /* Parse a crypto information structure */
00583 static BOOL
00584 sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
00585              uint8 ** server_random, uint8 ** modulus, uint8 ** exponent)
00586 {
00587     uint32 crypt_level, random_len, rsa_info_len;
00588     uint32 /*cacert_len, cert_len,*/ flags;
00589     //X509 *cacert, *server_cert;
00590     uint16 tag, length;
00591     uint8 *next_tag, *end;
00592 
00593     in_uint32_le(s, *rc4_key_size); /* 1 = 40-bit, 2 = 128-bit */
00594     in_uint32_le(s, crypt_level);   /* 1 = low, 2 = medium, 3 = high */
00595     if (crypt_level == 0)   /* no encryption */
00596         return False;
00597     in_uint32_le(s, random_len);
00598     in_uint32_le(s, rsa_info_len);
00599 
00600     if (random_len != SEC_RANDOM_SIZE)
00601     {
00602         error("random len %d, expected %d\n", random_len, SEC_RANDOM_SIZE);
00603         return False;
00604     }
00605 
00606     in_uint8p(s, *server_random, random_len);
00607 
00608     /* RSA info */
00609     end = s->p + rsa_info_len;
00610     if (end > s->end)
00611         return False;
00612 
00613     in_uint32_le(s, flags); /* 1 = RDP4-style, 0x80000002 = X.509 */
00614     if (flags & 1)
00615     {
00616         DEBUG_RDP5(("We're going for the RDP4-style encryption\n"));
00617         in_uint8s(s, 8);    /* unknown */
00618 
00619         while (s->p < end)
00620         {
00621             in_uint16_le(s, tag);
00622             in_uint16_le(s, length);
00623 
00624             next_tag = s->p + length;
00625 
00626             switch (tag)
00627             {
00628                 case SEC_TAG_PUBKEY:
00629                     if (!sec_parse_public_key(s, modulus, exponent))
00630                         return False;
00631                     DEBUG_RDP5(("Got Public key, RDP4-style\n"));
00632 
00633                     break;
00634 
00635                 case SEC_TAG_KEYSIG:
00636                     /* Is this a Microsoft key that we just got? */
00637                     /* Care factor: zero! */
00638                     /* Actually, it would probably be a good idea to check if the public key is signed with this key, and then store this 
00639                        key as a known key of the hostname. This would prevent some MITM-attacks. */
00640                     break;
00641 
00642                 default:
00643                     unimpl("crypt tag 0x%x\n", tag);
00644             }
00645 
00646             s->p = next_tag;
00647         }
00648     }
00649     else
00650     { 
00651 #if 0
00652         uint32 certcount;
00653 
00654         DEBUG_RDP5(("We're going for the RDP5-style encryption\n"));
00655         in_uint32_le(s, certcount); /* Number of certificates */
00656 
00657         if (certcount < 2)
00658         {
00659             error("Server didn't send enough X509 certificates\n");
00660             return False;
00661         }
00662 
00663         for (; certcount > 2; certcount--)
00664         {       /* ignore all the certificates between the root and the signing CA */
00665             uint32 ignorelen;
00666             X509 *ignorecert;
00667 
00668             DEBUG_RDP5(("Ignored certs left: %d\n", certcount));
00669 
00670             in_uint32_le(s, ignorelen);
00671             DEBUG_RDP5(("Ignored Certificate length is %d\n", ignorelen));
00672             ignorecert = d2i_X509(NULL, &(s->p), ignorelen);
00673 
00674             if (ignorecert == NULL)
00675             {   /* XXX: error out? */
00676                 DEBUG_RDP5(("got a bad cert: this will probably screw up the rest of the communication\n"));
00677             }
00678 
00679 #ifdef WITH_DEBUG_RDP5
00680             DEBUG_RDP5(("cert #%d (ignored):\n", certcount));
00681             X509_print_fp(stdout, ignorecert);
00682 #endif
00683         }
00684 
00685         /* Do da funky X.509 stuffy 
00686 
00687            "How did I find out about this?  I looked up and saw a
00688            bright light and when I came to I had a scar on my forehead
00689            and knew about X.500"
00690            - Peter Gutman in a early version of 
00691            http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
00692          */
00693 
00694         in_uint32_le(s, cacert_len);
00695         DEBUG_RDP5(("CA Certificate length is %d\n", cacert_len));
00696         cacert = d2i_X509(NULL, &(s->p), cacert_len);
00697         /* Note: We don't need to move s->p here - d2i_X509 is
00698            "kind" enough to do it for us */
00699         if (NULL == cacert)
00700         {
00701             error("Couldn't load CA Certificate from server\n");
00702             return False;
00703         }
00704 
00705         /* Currently, we don't use the CA Certificate. 
00706            FIXME: 
00707            *) Verify the server certificate (server_cert) with the 
00708            CA certificate.
00709            *) Store the CA Certificate with the hostname of the 
00710            server we are connecting to as key, and compare it
00711            when we connect the next time, in order to prevent
00712            MITM-attacks.
00713          */
00714 
00715         X509_free(cacert);
00716 
00717         in_uint32_le(s, cert_len);
00718         DEBUG_RDP5(("Certificate length is %d\n", cert_len));
00719         server_cert = d2i_X509(NULL, &(s->p), cert_len);
00720         if (NULL == server_cert)
00721         {
00722             error("Couldn't load Certificate from server\n");
00723             return False;
00724         }
00725 
00726         in_uint8s(s, 16);   /* Padding */
00727 
00728         /* Note: Verifying the server certificate must be done here, 
00729            before sec_parse_public_key since we'll have to apply
00730            serious violence to the key after this */
00731 
00732         if (!sec_parse_x509_key(server_cert))
00733         {
00734             DEBUG_RDP5(("Didn't parse X509 correctly\n"));
00735             X509_free(server_cert);
00736             return False;
00737         }
00738         X509_free(server_cert);
00739         return True;    /* There's some garbage here we don't care about */
00740 #endif
00741     }
00742     return s_check_end(s);
00743 }
00744 
00745 /* Process crypto information blob */
00746 static void
00747 sec_process_crypt_info(STREAM s)
00748 {
00749     uint8 *server_random, *modulus = NULL, *exponent = NULL;
00750     uint8 client_random[SEC_RANDOM_SIZE];
00751     uint32 rc4_key_size;
00752     uint8 inr[SEC_MODULUS_SIZE];
00753 
00754     if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random, &modulus, &exponent))
00755     {
00756         DEBUG(("Failed to parse crypt info\n"));
00757         return;
00758     }
00759 
00760     DEBUG(("Generating client random\n"));
00761     /* Generate a client random, and hence determine encryption keys */
00762     /* This is what the MS client do: */
00763     memset(inr, 0, SEC_RANDOM_SIZE);
00764     /*  *ARIGL!* Plaintext attack, anyone?
00765        I tried doing:
00766        generate_random(inr);
00767        ..but that generates connection errors now and then (yes, 
00768        "now and then". Something like 0 to 3 attempts needed before a 
00769        successful connection. Nice. Not! 
00770      */
00771 
00772     generate_random(client_random);
00773     if (NULL != server_public_key)
00774     {           /* Which means we should use 
00775                    RDP5-style encryption */
00776 #if 0
00777         memcpy(inr + SEC_RANDOM_SIZE, client_random, SEC_RANDOM_SIZE);
00778         reverse(inr + SEC_RANDOM_SIZE, SEC_RANDOM_SIZE);
00779 
00780         RSA_public_encrypt(SEC_MODULUS_SIZE,
00781                    inr, sec_crypted_random, server_public_key, RSA_NO_PADDING);
00782 
00783         reverse(sec_crypted_random, SEC_MODULUS_SIZE);
00784 
00785         RSA_free(server_public_key);
00786         server_public_key = NULL;
00787 #endif
00788     }
00789     else
00790     {           /* RDP4-style encryption */
00791         sec_rsa_encrypt(sec_crypted_random,
00792                 client_random, SEC_RANDOM_SIZE, modulus, exponent);
00793     }
00794     sec_generate_keys(client_random, server_random, rc4_key_size);
00795 }
00796 
00797 
00798 /* Process SRV_INFO, find RDP version supported by server */
00799 static void
00800 sec_process_srv_info(STREAM s)
00801 {
00802     in_uint16_le(s, g_server_rdp_version);
00803     DEBUG_RDP5(("Server RDP version is %d\n", g_server_rdp_version));
00804     if (1 == g_server_rdp_version)
00805     {
00806         g_use_rdp5 = 0;
00807         g_server_depth = 8;
00808     }
00809 }
00810 
00811 
00812 /* Process connect response data blob */
00813 void
00814 sec_process_mcs_data(STREAM s)
00815 {
00816     uint16 tag, length;
00817     uint8 *next_tag;
00818     uint8 len;
00819 
00820     in_uint8s(s, 21);   /* header (T.124 ConferenceCreateResponse) */
00821     in_uint8(s, len);
00822     if (len & 0x80)
00823         in_uint8(s, len);
00824 
00825     while (s->p < s->end)
00826     {
00827         in_uint16_le(s, tag);
00828         in_uint16_le(s, length);
00829 
00830         if (length <= 4)
00831             return;
00832 
00833         next_tag = s->p + length - 4;
00834 
00835         switch (tag)
00836         {
00837             case SEC_TAG_SRV_INFO:
00838                 sec_process_srv_info(s);
00839                 break;
00840 
00841             case SEC_TAG_SRV_CRYPT:
00842                 sec_process_crypt_info(s);
00843                 break;
00844 
00845             case SEC_TAG_SRV_CHANNELS:
00846                 /* FIXME: We should parse this information and
00847                    use it to map RDP5 channels to MCS 
00848                    channels */
00849                 break;
00850 
00851             default:
00852                 unimpl("response tag 0x%x\n", tag);
00853         }
00854 
00855         s->p = next_tag;
00856     }
00857 }
00858 
00859 /* Receive secure transport packet */
00860 STREAM
00861 sec_recv(uint8 * rdpver)
00862 {
00863     uint32 sec_flags;
00864     uint16 channel;
00865     STREAM s;
00866 
00867     while ((s = mcs_recv(&channel, rdpver)) != NULL)
00868     {
00869         if (rdpver != NULL)
00870         {
00871             if (*rdpver != 3)
00872             {
00873                 if (*rdpver & 0x80)
00874                 {
00875                     in_uint8s(s, 8);    /* signature */
00876                     sec_decrypt(s->p, s->end - s->p);
00877                 }
00878                 return s;
00879             }
00880         }
00881         if (g_encryption || !g_licence_issued)
00882         {
00883             in_uint32_le(s, sec_flags);
00884 
00885             if (sec_flags & SEC_ENCRYPT)
00886             {
00887                 in_uint8s(s, 8);    /* signature */
00888                 sec_decrypt(s->p, s->end - s->p);
00889             }
00890 
00891             if (sec_flags & SEC_LICENCE_NEG)
00892             {
00893                 licence_process(s);
00894                 continue;
00895             }
00896 
00897             if (sec_flags & 0x0400) /* SEC_REDIRECT_ENCRYPT */
00898             {
00899                 uint8 swapbyte;
00900 
00901                 in_uint8s(s, 8);    /* signature */
00902                 sec_decrypt(s->p, s->end - s->p);
00903 
00904                 /* Check for a redirect packet, starts with 00 04 */
00905                 if (s->p[0] == 0 && s->p[1] == 4)
00906                 {
00907                     /* for some reason the PDU and the length seem to be swapped.
00908                        This isn't good, but we're going to do a byte for byte
00909                        swap.  So the first foure value appear as: 00 04 XX YY,
00910                        where XX YY is the little endian length. We're going to
00911                        use 04 00 as the PDU type, so after our swap this will look
00912                        like: XX YY 04 00 */
00913                     swapbyte = s->p[0];
00914                     s->p[0] = s->p[2];
00915                     s->p[2] = swapbyte;
00916 
00917                     swapbyte = s->p[1];
00918                     s->p[1] = s->p[3];
00919                     s->p[3] = swapbyte;
00920 
00921                     swapbyte = s->p[2];
00922                     s->p[2] = s->p[3];
00923                     s->p[3] = swapbyte;
00924                 }
00925 #ifdef WITH_DEBUG
00926                 /* warning!  this debug statement will show passwords in the clear! */
00927                 hexdump(s->p, s->end - s->p);
00928 #endif
00929             }
00930 
00931         }
00932 
00933         if (channel != MCS_GLOBAL_CHANNEL)
00934         {
00935             channel_process(s, channel);
00936             *rdpver = 0xff;
00937             return s;
00938         }
00939 
00940         return s;
00941     }
00942 
00943     return NULL;
00944 }
00945 
00946 /* Establish a secure connection */
00947 BOOL
00948 sec_connect(char *server, char *username)
00949 {
00950     struct stream mcs_data;
00951 
00952     /* We exchange some RDP data during the MCS-Connect */
00953     mcs_data.size = 512;
00954     mcs_data.p = mcs_data.data = (uint8 *) xmalloc(mcs_data.size);
00955     sec_out_mcs_data(&mcs_data);
00956 
00957     if (!mcs_connect(server, &mcs_data, username))
00958         return False;
00959 
00960     /*      sec_process_mcs_data(&mcs_data); */
00961     if (g_encryption)
00962         sec_establish_key();
00963     xfree(mcs_data.data);
00964     return True;
00965 }
00966 
00967 /* Establish a secure connection */
00968 BOOL
00969 sec_reconnect(char *server)
00970 {
00971     struct stream mcs_data;
00972 
00973     /* We exchange some RDP data during the MCS-Connect */
00974     mcs_data.size = 512;
00975     mcs_data.p = mcs_data.data = (uint8 *) xmalloc(mcs_data.size);
00976     sec_out_mcs_data(&mcs_data);
00977 
00978     if (!mcs_reconnect(server, &mcs_data))
00979         return False;
00980 
00981     /*      sec_process_mcs_data(&mcs_data); */
00982     if (g_encryption)
00983         sec_establish_key();
00984     xfree(mcs_data.data);
00985     return True;
00986 }
00987 
00988 /* Disconnect a connection */
00989 void
00990 sec_disconnect(void)
00991 {
00992     mcs_disconnect();
00993 }
00994 
00995 /* reset the state of the sec layer */
00996 void
00997 sec_reset_state(void)
00998 {
00999     g_server_rdp_version = 0;
01000     sec_encrypt_use_count = 0;
01001     sec_decrypt_use_count = 0;
01002     mcs_reset_state();
01003 }

Generated on Fri May 25 2012 04:15:28 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.