Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

secure.cpp

Go to the documentation of this file.
00001 /*
00002    rdesktop: A Remote Desktop Protocol client.
00003    Protocol services - RDP encryption and licensing
00004    Copyright (C) Matthew Chapman 1999-2002
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
00017    along with this program; if not, write to the Free Software
00018    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019 */
00020 
00021 #include "rdesktop.h"
00022 
00023 //#ifdef WITH_OPENSSL
00024 #include <openssl/rc4.h>
00025 #include <openssl/md5.h>
00026 #include <openssl/sha.h>
00027 #include <openssl/bn.h>
00028 //#else
00029 //#include "crypto/rc4.h"
00030 //#include "crypto/md5.h"
00031 //#include "crypto/sha.h"
00032 //#include "crypto/bn.h"
00033 //#endif
00034 
00035 extern char hostname[16];
00036 extern int g_width;
00037 extern int g_height;
00038 extern int keylayout;
00039 extern BOOL encryption;
00040 extern BOOL licence_issued;
00041 extern int server_bpp;
00042 
00043 static int rc4_key_len;
00044 static RC4_KEY rc4_decrypt_key;
00045 static RC4_KEY rc4_encrypt_key;
00046 
00047 static uint8 sec_sign_key[16];
00048 static uint8 sec_decrypt_key[16];
00049 static uint8 sec_encrypt_key[16];
00050 static uint8 sec_decrypt_update_key[16];
00051 static uint8 sec_encrypt_update_key[16];
00052 static uint8 sec_crypted_random[SEC_MODULUS_SIZE];
00053 
00054 /*
00055  * General purpose 48-byte transformation, using two 32-byte salts (generally,
00056  * a client and server salt) and a global salt value used for padding.
00057  * Both SHA1 and MD5 algorithms are used.
00058  */
00059 void
00060 sec_hash_48(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2, uint8 salt)
00061 {
00062         uint8 shasig[20];
00063         uint8 pad[4];
00064         SHA_CTX sha;
00065         MD5_CTX md5;
00066         int i;
00067 
00068         for (i = 0; i < 3; i++)
00069         {
00070                 memset(pad, salt + i, i + 1);
00071 
00072                 SHA1_Init(&sha);
00073                 SHA1_Update(&sha, pad, i + 1);
00074                 SHA1_Update(&sha, in, 48);
00075                 SHA1_Update(&sha, salt1, 32);
00076                 SHA1_Update(&sha, salt2, 32);
00077                 SHA1_Final(shasig, &sha);
00078 
00079                 MD5_Init(&md5);
00080                 MD5_Update(&md5, in, 48);
00081                 MD5_Update(&md5, shasig, 20);
00082                 MD5_Final(&out[i * 16], &md5);
00083         }
00084 }
00085 
00086 /*
00087  * Weaker 16-byte transformation, also using two 32-byte salts, but
00088  * only using a single round of MD5.
00089  */
00090 void
00091 sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2)
00092 {
00093         MD5_CTX md5;
00094 
00095         MD5_Init(&md5);
00096         MD5_Update(&md5, in, 16);
00097         MD5_Update(&md5, salt1, 32);
00098         MD5_Update(&md5, salt2, 32);
00099         MD5_Final(out, &md5);
00100 }
00101 
00102 /* Reduce key entropy from 64 to 40 bits */
00103 static void
00104 sec_make_40bit(uint8 * key)
00105 {
00106         key[0] = 0xd1;
00107         key[1] = 0x26;
00108         key[2] = 0x9e;
00109 }
00110 
00111 /* Generate a session key and RC4 keys, given client and server randoms */
00112 static void
00113 sec_generate_keys(uint8 * client_key, uint8 * server_key, int rc4_key_size)
00114 {
00115         uint8 session_key[48];
00116         uint8 temp_hash[48];
00117         uint8 input[48];
00118 
00119         /* Construct input data to hash */
00120         memcpy(input, client_key, 24);
00121         memcpy(input + 24, server_key, 24);
00122 
00123         /* Generate session key - two rounds of sec_hash_48 */
00124         sec_hash_48(temp_hash, input, client_key, server_key, 65);
00125         sec_hash_48(session_key, temp_hash, client_key, server_key, 88);
00126 
00127         /* Store first 16 bytes of session key, for generating signatures */
00128         memcpy(sec_sign_key, session_key, 16);
00129 
00130         /* Generate RC4 keys */
00131         sec_hash_16(sec_decrypt_key, &session_key[16], client_key, server_key);
00132         sec_hash_16(sec_encrypt_key, &session_key[32], client_key, server_key);
00133 
00134         if (rc4_key_size == 1)
00135         {
00136                 DEBUG(("40-bit encryption enabled\n"));
00137                 sec_make_40bit(sec_sign_key);
00138                 sec_make_40bit(sec_decrypt_key);
00139                 sec_make_40bit(sec_encrypt_key);
00140                 rc4_key_len = 8;
00141         }
00142         else
00143         {
00144                 DEBUG(("128-bit encryption enabled\n"));
00145                 rc4_key_len = 16;
00146         }
00147 
00148         /* Save initial RC4 keys as update keys */
00149         memcpy(sec_decrypt_update_key, sec_decrypt_key, 16);
00150         memcpy(sec_encrypt_update_key, sec_encrypt_key, 16);
00151 
00152         /* Initialise RC4 state arrays */
00153         RC4_set_key(&rc4_decrypt_key, rc4_key_len, sec_decrypt_key);
00154         RC4_set_key(&rc4_encrypt_key, rc4_key_len, sec_encrypt_key);
00155 }
00156 
00157 static uint8 pad_54[40] = {
00158         54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
00159         54, 54, 54,
00160         54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
00161         54, 54, 54
00162 };
00163 
00164 static uint8 pad_92[48] = {
00165         92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
00166         92, 92, 92, 92, 92, 92, 92,
00167         92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
00168         92, 92, 92, 92, 92, 92, 92
00169 };
00170 
00171 /* Output a uint32 into a buffer (little-endian) */
00172 void
00173 buf_out_uint32(uint8 * buffer, uint32 value)
00174 {
00175         buffer[0] = (value) & 0xff;
00176         buffer[1] = (value >> 8) & 0xff;
00177         buffer[2] = (value >> 16) & 0xff;
00178         buffer[3] = (value >> 24) & 0xff;
00179 }
00180 
00181 /* Generate a signature hash, using a combination of SHA1 and MD5 */
00182 void
00183 sec_sign(uint8 * signature, int siglen, uint8 * session_key, int keylen, uint8 * data, int datalen)
00184 {
00185         uint8 shasig[20];
00186         uint8 md5sig[16];
00187         uint8 lenhdr[4];
00188         SHA_CTX sha;
00189         MD5_CTX md5;
00190 
00191         buf_out_uint32(lenhdr, datalen);
00192 
00193         SHA1_Init(&sha);
00194         SHA1_Update(&sha, session_key, keylen);
00195         SHA1_Update(&sha, pad_54, 40);
00196         SHA1_Update(&sha, lenhdr, 4);
00197         SHA1_Update(&sha, data, datalen);
00198         SHA1_Final(shasig, &sha);
00199 
00200         MD5_Init(&md5);
00201         MD5_Update(&md5, session_key, keylen);
00202         MD5_Update(&md5, pad_92, 48);
00203         MD5_Update(&md5, shasig, 20);
00204         MD5_Final(md5sig, &md5);
00205 
00206         memcpy(signature, md5sig, siglen);
00207 }
00208 
00209 /* Update an encryption key - similar to the signing process */
00210 static void
00211 sec_update(uint8 * key, uint8 * update_key)
00212 {
00213         uint8 shasig[20];
00214         SHA_CTX sha;
00215         MD5_CTX md5;
00216         RC4_KEY update;
00217 
00218         SHA1_Init(&sha);
00219         SHA1_Update(&sha, update_key, rc4_key_len);
00220         SHA1_Update(&sha, pad_54, 40);
00221         SHA1_Update(&sha, key, rc4_key_len);
00222         SHA1_Final(shasig, &sha);
00223 
00224         MD5_Init(&md5);
00225         MD5_Update(&md5, update_key, rc4_key_len);
00226         MD5_Update(&md5, pad_92, 48);
00227         MD5_Update(&md5, shasig, 20);
00228         MD5_Final(key, &md5);
00229 
00230         RC4_set_key(&update, rc4_key_len, key);
00231         RC4(&update, rc4_key_len, key, key);
00232 
00233         if (rc4_key_len == 8)
00234                 sec_make_40bit(key);
00235 }
00236 
00237 /* Encrypt data using RC4 */
00238 static void
00239 sec_encrypt(uint8 * data, int length)
00240 {
00241         static int use_count;
00242 
00243         if (use_count == 4096)
00244         {
00245                 sec_update(sec_encrypt_key, sec_encrypt_update_key);
00246                 RC4_set_key(&rc4_encrypt_key, rc4_key_len, sec_encrypt_key);
00247                 use_count = 0;
00248         }
00249 
00250         RC4(&rc4_encrypt_key, length, data, data);
00251         use_count++;
00252 }
00253 
00254 /* Decrypt data using RC4 */
00255 static void
00256 sec_decrypt(uint8 * data, int length)
00257 {
00258         static int use_count;
00259 
00260         if (use_count == 4096)
00261         {
00262                 sec_update(sec_decrypt_key, sec_decrypt_update_key);
00263                 RC4_set_key(&rc4_decrypt_key, rc4_key_len, sec_decrypt_key);
00264                 use_count = 0;
00265         }
00266 
00267         RC4(&rc4_decrypt_key, length, data, data);
00268         use_count++;
00269 }
00270 
00271 static void
00272 reverse(uint8 * p, int len)
00273 {
00274         int i, j;
00275         uint8 temp;
00276 
00277         for (i = 0, j = len - 1; i < j; i++, j--)
00278         {
00279                 temp = p[i];
00280                 p[i] = p[j];
00281                 p[j] = temp;
00282         }
00283 }
00284 
00285 /* Perform an RSA public key encryption operation */
00286 static void
00287 sec_rsa_encrypt(uint8 * out, uint8 * in, int len, uint8 * modulus, uint8 * exponent)
00288 {
00289         BN_CTX *ctx;
00290         BIGNUM mod, exp, x, y;
00291         uint8 inr[SEC_MODULUS_SIZE];
00292         int outlen;
00293 
00294         reverse(modulus, SEC_MODULUS_SIZE);
00295         reverse(exponent, SEC_EXPONENT_SIZE);
00296         memcpy(inr, in, len);
00297         reverse(inr, len);
00298 
00299         ctx = BN_CTX_new();
00300         BN_init(&mod);
00301         BN_init(&exp);
00302         BN_init(&x);
00303         BN_init(&y);
00304 
00305         BN_bin2bn(modulus, SEC_MODULUS_SIZE, &mod);
00306         BN_bin2bn(exponent, SEC_EXPONENT_SIZE, &exp);
00307         BN_bin2bn(inr, len, &x);
00308         BN_mod_exp(&y, &x, &exp, &mod, ctx);
00309         outlen = BN_bn2bin(&y, out);
00310         reverse(out, outlen);
00311         if (outlen < SEC_MODULUS_SIZE)
00312                 memset(out + outlen, 0, SEC_MODULUS_SIZE - outlen);
00313 
00314         BN_free(&y);
00315         BN_clear_free(&x);
00316         BN_free(&exp);
00317         BN_free(&mod);
00318         BN_CTX_free(ctx);
00319 }
00320 
00321 /* Initialise secure transport packet */
00322 STREAM
00323 sec_init(uint32 flags, int maxlen)
00324 {
00325         int hdrlen;
00326         STREAM s;
00327 
00328         if (!licence_issued)
00329                 hdrlen = (flags & SEC_ENCRYPT) ? 12 : 4;
00330         else
00331                 hdrlen = (flags & SEC_ENCRYPT) ? 12 : 0;
00332         s = mcs_init(maxlen + hdrlen);
00333         s_push_layer(s, sec_hdr, hdrlen);
00334 
00335         return s;
00336 }
00337 
00338 /* Transmit secure transport packet */
00339 void
00340 sec_send(STREAM s, uint32 flags)
00341 {
00342         int datalen;
00343 
00344         s_pop_layer(s, sec_hdr);
00345         if (!licence_issued || (flags & SEC_ENCRYPT))
00346                 out_uint32_le(s, flags);
00347 
00348         if (flags & SEC_ENCRYPT)
00349         {
00350                 flags &= ~SEC_ENCRYPT;
00351                 datalen = s->end - s->p - 8;
00352 
00353 #if WITH_DEBUG
00354                 DEBUG(("Sending encrypted packet:\n"));
00355                 hexdump(s->p + 8, datalen);
00356 #endif
00357 
00358                 sec_sign(s->p, 8, sec_sign_key, rc4_key_len, s->p + 8, datalen);
00359                 sec_encrypt(s->p + 8, datalen);
00360         }
00361 
00362         mcs_send(s);
00363 }
00364 
00365 /* Transfer the client random to the server */
00366 static void
00367 sec_establish_key(void)
00368 {
00369         uint32 length = SEC_MODULUS_SIZE + SEC_PADDING_SIZE;
00370         uint32 flags = SEC_CLIENT_RANDOM;
00371         STREAM s;
00372 
00373         s = sec_init(flags, 76);
00374 
00375         out_uint32_le(s, length);
00376         out_uint8p(s, sec_crypted_random, SEC_MODULUS_SIZE);
00377         out_uint8s(s, SEC_PADDING_SIZE);
00378 
00379         s_mark_end(s);
00380         sec_send(s, flags);
00381 }
00382 
00383 /* Output connect initial data blob */
00384 static void
00385 sec_out_mcs_data(STREAM s)
00386 {
00387         int hostlen = 2 * strlen(hostname);
00388 
00389    if (hostlen > 30)
00390                 hostlen = 30;
00391 
00392         out_uint16_be(s, 5);    /* unknown */
00393         out_uint16_be(s, 0x14);
00394         out_uint8(s, 0x7c);
00395         out_uint16_be(s, 1);
00396 
00397         out_uint16_be(s, (158 | 0x8000));       /* remaining length */
00398 
00399         out_uint16_be(s, 8);    /* length? */
00400         out_uint16_be(s, 16);
00401         out_uint8(s, 0);
00402         out_uint16_le(s, 0xc001);
00403         out_uint8(s, 0);
00404 
00405         out_uint32_le(s, 0x61637544);   /* "Duca" ?! */
00406         out_uint16_be(s, (144 | 0x8000));       /* remaining length */
00407 
00408         /* Client information */
00409         out_uint16_le(s, SEC_TAG_CLI_INFO);
00410         out_uint16_le(s, 136);  /* length */
00411         out_uint16_le(s, 1);
00412         out_uint16_le(s, 8);
00413         out_uint16_le(s, g_width);
00414         out_uint16_le(s, g_height);
00415         out_uint16_le(s, 0xca01);
00416         out_uint16_le(s, 0xaa03);
00417         out_uint32_le(s, keylayout);
00418         out_uint32_le(s, 419);  /* client build? we are 419 compatible :-) */
00419 
00420         /* Unicode name of client, padded to 32 bytes */
00421         rdp_out_unistr(s, hostname, hostlen);
00422         out_uint8s(s, 30 - hostlen);
00423 
00424         out_uint32_le(s, 4);
00425         out_uint32(s, 0);
00426         out_uint32_le(s, 12);
00427         out_uint8s(s, 64);      /* reserved? 4 + 12 doublewords */
00428 
00429         switch (server_bpp)
00430         {
00431                 case 8:
00432                         out_uint16_le(s, 0xca01);
00433                         break;
00434                 case 15:
00435                         out_uint16_le(s, 0xca02);
00436                         break;
00437                 case 16:
00438                         out_uint16_le(s, 0xca03);
00439                         break;
00440                 case 24:
00441                         out_uint16_le(s, 0xca04);
00442                         break;
00443         }
00444         out_uint16(s, 0);
00445 
00446         /* Client encryption settings */
00447         out_uint16_le(s, SEC_TAG_CLI_CRYPT);
00448         out_uint16_le(s, 8);    /* length */
00449         out_uint32_le(s, encryption ? 0x3 : 0); /* encryption supported, 128-bit supported */
00450         s_mark_end(s);
00451 }
00452 
00453 /* Parse a public key structure */
00454 static BOOL
00455 sec_parse_public_key(STREAM s, uint8 ** modulus, uint8 ** exponent)
00456 {
00457         uint32 magic, modulus_len;
00458 
00459         in_uint32_le(s, magic);
00460         if (magic != SEC_RSA_MAGIC)
00461         {
00462                 error("RSA magic 0x%x\n", magic);
00463                 return False;
00464         }
00465 
00466         in_uint32_le(s, modulus_len);
00467         if (modulus_len != SEC_MODULUS_SIZE + SEC_PADDING_SIZE)
00468         {
00469                 error("modulus len 0x%x\n", modulus_len);
00470                 return False;
00471         }
00472 
00473         in_uint8s(s, 8);        /* modulus_bits, unknown */
00474         in_uint8p(s, *exponent, SEC_EXPONENT_SIZE);
00475         in_uint8p(s, *modulus, SEC_MODULUS_SIZE);
00476         in_uint8s(s, SEC_PADDING_SIZE);
00477 
00478         return s_check(s);
00479 }
00480 
00481 /* Parse a crypto information structure */
00482 static BOOL
00483 sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
00484                      uint8 ** server_random, uint8 ** modulus, uint8 ** exponent)
00485 {
00486         uint32 crypt_level, random_len, rsa_info_len;
00487         uint16 tag, length;
00488         uint8 *next_tag, *end;
00489 
00490         in_uint32_le(s, *rc4_key_size); /* 1 = 40-bit, 2 = 128-bit */
00491         in_uint32_le(s, crypt_level);   /* 1 = low, 2 = medium, 3 = high */
00492         if (crypt_level == 0)   /* no encryptation */
00493                 return False;
00494         in_uint32_le(s, random_len);
00495         in_uint32_le(s, rsa_info_len);
00496 
00497         if (random_len != SEC_RANDOM_SIZE)
00498         {
00499                 error("random len %d\n", random_len);
00500                 return False;
00501         }
00502 
00503         in_uint8p(s, *server_random, random_len);
00504 
00505         /* RSA info */
00506         end = s->p + rsa_info_len;
00507         if (end > s->end)
00508                 return False;
00509 
00510         in_uint8s(s, 12);       /* unknown */
00511 
00512         while (s->p < end)
00513         {
00514                 in_uint16_le(s, tag);
00515                 in_uint16_le(s, length);
00516 
00517                 next_tag = s->p + length;
00518 
00519                 switch (tag)
00520                 {
00521                         case SEC_TAG_PUBKEY:
00522                                 if (!sec_parse_public_key(s, modulus, exponent))
00523                                         return False;
00524 
00525                                 break;
00526 
00527                         case SEC_TAG_KEYSIG:
00528                                 /* Is this a Microsoft key that we just got? */
00529                                 /* Care factor: zero! */
00530                                 break;
00531 
00532                         default:
00533                                 unimpl("crypt tag 0x%x\n", tag);
00534                 }
00535 
00536                 s->p = next_tag;
00537         }
00538 
00539         return s_check_end(s);
00540 }
00541 
00542 /* Process crypto information blob */
00543 static void
00544 sec_process_crypt_info(STREAM s)
00545 {
00546         uint8 *server_random, *modulus, *exponent;
00547         uint8 client_random[SEC_RANDOM_SIZE];
00548         uint32 rc4_key_size;
00549 
00550         if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random, &modulus, &exponent))
00551                 return;
00552 
00553         /* Generate a client random, and hence determine encryption keys */
00554         generate_random(client_random);
00555         sec_rsa_encrypt(sec_crypted_random, client_random, SEC_RANDOM_SIZE, modulus, exponent);
00556         sec_generate_keys(client_random, server_random, rc4_key_size);
00557 }
00558 
00559 /* Process connect response data blob */
00560 static void
00561 sec_process_mcs_data(STREAM s)
00562 {
00563         uint16 tag, length;
00564         uint8 *next_tag;
00565         uint8 len;
00566 
00567         in_uint8s(s, 21);       /* header */
00568         in_uint8(s, len);
00569         if (len & 0x80)
00570                 in_uint8(s, len);
00571 
00572         while (s->p < s->end)
00573         {
00574                 in_uint16_le(s, tag);
00575                 in_uint16_le(s, length);
00576 
00577                 if (length <= 4)
00578                         return;
00579 
00580                 next_tag = s->p + length - 4;
00581 
00582                 switch (tag)
00583                 {
00584                         case SEC_TAG_SRV_INFO:
00585                         case SEC_TAG_SRV_3:
00586                                 break;
00587 
00588                         case SEC_TAG_SRV_CRYPT:
00589                                 sec_process_crypt_info(s);
00590                                 break;
00591 
00592                         default:
00593                                 unimpl("response tag 0x%x\n", tag);
00594                 }
00595 
00596                 s->p = next_tag;
00597         }
00598 }
00599 
00600 /* Receive secure transport packet */
00601 STREAM
00602 sec_recv(void)
00603 {
00604         uint32 sec_flags;
00605         STREAM s;
00606 
00607         while ((s = mcs_recv()) != NULL)
00608         {
00609                 if (encryption || !licence_issued)
00610                 {
00611                         in_uint32_le(s, sec_flags);
00612 
00613                         if (sec_flags & SEC_LICENCE_NEG)
00614                         {
00615                                 licence_process(s);
00616                                 continue;
00617                         }
00618 
00619                         if (sec_flags & SEC_ENCRYPT)
00620                         {
00621                                 in_uint8s(s, 8);        /* signature */
00622                                 sec_decrypt(s->p, s->end - s->p);
00623                         }
00624                 }
00625 
00626                 return s;
00627         }
00628 
00629         return NULL;
00630 }
00631 
00632 /* Establish a secure connection */
00633 BOOL
00634 sec_connect(char *server)
00635 {
00636         struct stream mcs_data;
00637 
00638         /* We exchange some RDP data during the MCS-Connect */
00639         mcs_data.size = 512;
00640         mcs_data.p = mcs_data.data = (unsigned char*)xmalloc(mcs_data.size);
00641         sec_out_mcs_data(&mcs_data);
00642 
00643         if (!mcs_connect(server, &mcs_data))
00644                 return False;
00645 
00646         sec_process_mcs_data(&mcs_data);
00647         if (encryption)
00648                 sec_establish_key();
00649         xfree(mcs_data.data);
00650         return True;
00651 }
00652 
00653 /* Disconnect a connection */
00654 void
00655 sec_disconnect(void)
00656 {
00657         mcs_disconnect();
00658 }

Generated on Sat Nov 5 16:17:42 2005 for OPIE by  doxygen 1.4.2