Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygensecure.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
1.7.6.1
|