ReactOS 0.4.15-dev-8131-g4988de4
secure.c
Go to the documentation of this file.
1/* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Protocol services - RDP encryption and licensing
4 Copyright (C) Matthew Chapman 1999-2005
5
6 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
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20
21#include "rdesktop.h"
22#include <string.h>
23
24// TODO: remove dependency on OpenSSL
25#include <openssl/rc4.h>
26#include <openssl/md5.h>
27#include <openssl/sha.h>
28#include <openssl/bn.h>
29#include <openssl/x509v3.h>
30
31/*
32 * I believe this is based on SSLv3 with the following differences:
33 * MAC algorithm (5.2.3.1) uses only 32-bit length in place of seq_num/type/length fields
34 * MAC algorithm uses SHA1 and MD5 for the two hash functions instead of one or other
35 * key_block algorithm (6.2.2) uses 'X', 'YY', 'ZZZ' instead of 'A', 'BB', 'CCC'
36 * key_block partitioning is different (16 bytes each: MAC secret, decrypt key, encrypt key)
37 * encryption/decryption keys updated every 4096 packets
38 * See http://wp.netscape.com/eng/ssl3/draft302.txt
39 */
40
41/*
42 * 48-byte transformation used to generate master secret (6.1) and key material (6.2.2).
43 * Both SHA1 and MD5 algorithms are used.
44 */
45void
46sec_hash_48(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2, uint8 salt)
47{
48 uint8 shasig[20];
49 uint8 pad[4];
52 int i;
53
54 for (i = 0; i < 3; i++)
55 {
56 memset(pad, salt + i, i + 1);
57
58 SHA1_Init(&sha);
59 SHA1_Update(&sha, pad, i + 1);
60 SHA1_Update(&sha, in, 48);
61 SHA1_Update(&sha, salt1, 32);
62 SHA1_Update(&sha, salt2, 32);
63 SHA1_Final(shasig, &sha);
64
65 MD5_Init(&md5);
66 MD5_Update(&md5, in, 48);
67 MD5_Update(&md5, shasig, 20);
68 MD5_Final(&out[i * 16], &md5);
69 }
70}
71
72/*
73 * 16-byte transformation used to generate export keys (6.2.2).
74 */
75void
76sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2)
77{
79
80 MD5_Init(&md5);
81 MD5_Update(&md5, in, 16);
82 MD5_Update(&md5, salt1, 32);
83 MD5_Update(&md5, salt2, 32);
84 MD5_Final(out, &md5);
85}
86
87/* Reduce key entropy from 64 to 40 bits */
88static void
90{
91 key[0] = 0xd1;
92 key[1] = 0x26;
93 key[2] = 0x9e;
94}
95
96/* Generate encryption keys given client and server randoms */
97static void
98sec_generate_keys(RDPCLIENT * This, uint8 * client_random, uint8 * server_random, int rc4_key_size)
99{
100 uint8 pre_master_secret[48];
101 uint8 master_secret[48];
102 uint8 key_block[48];
103
104 /* Construct pre-master secret */
105 memcpy(pre_master_secret, client_random, 24);
106 memcpy(pre_master_secret + 24, server_random, 24);
107
108 /* Generate master secret and then key material */
109 sec_hash_48(master_secret, pre_master_secret, client_random, server_random, 'A');
110 sec_hash_48(key_block, master_secret, client_random, server_random, 'X');
111
112 /* First 16 bytes of key material is MAC secret */
113 memcpy(This->secure.sign_key, key_block, 16);
114
115 /* Generate export keys from next two blocks of 16 bytes */
116 sec_hash_16(This->secure.decrypt_key, &key_block[16], client_random, server_random);
117 sec_hash_16(This->secure.encrypt_key, &key_block[32], client_random, server_random);
118
119 if (rc4_key_size == 1)
120 {
121 DEBUG(("40-bit encryption enabled\n"));
122 sec_make_40bit(This->secure.sign_key);
123 sec_make_40bit(This->secure.decrypt_key);
124 sec_make_40bit(This->secure.encrypt_key);
125 This->secure.rc4_key_len = 8;
126 }
127 else
128 {
129 DEBUG(("rc_4_key_size == %d, 128-bit encryption enabled\n", rc4_key_size));
130 This->secure.rc4_key_len = 16;
131 }
132
133 /* Save initial RC4 keys as update keys */
134 memcpy(This->secure.decrypt_update_key, This->secure.decrypt_key, 16);
135 memcpy(This->secure.encrypt_update_key, This->secure.encrypt_key, 16);
136
137 /* Initialise RC4 state arrays */
138 RC4_set_key(&This->secure.rc4_decrypt_key, This->secure.rc4_key_len, This->secure.decrypt_key);
139 RC4_set_key(&This->secure.rc4_encrypt_key, This->secure.rc4_key_len, This->secure.encrypt_key);
140}
141
142static const uint8 pad_54[40] = {
143 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
144 54, 54, 54,
145 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
146 54, 54, 54
147};
148
149static const uint8 pad_92[48] = {
150 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
151 92, 92, 92, 92, 92, 92, 92,
152 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
153 92, 92, 92, 92, 92, 92, 92
154};
155
156/* Output a uint32 into a buffer (little-endian) */
157void
159{
160 buffer[0] = (value) & 0xff;
161 buffer[1] = (value >> 8) & 0xff;
162 buffer[2] = (value >> 16) & 0xff;
163 buffer[3] = (value >> 24) & 0xff;
164}
165
166/* Generate a MAC hash (5.2.3.1), using a combination of SHA1 and MD5 */
167void
168sec_sign(uint8 * signature, int siglen, uint8 * session_key, int keylen, uint8 * data, int datalen)
169{
170 uint8 shasig[20];
171 uint8 md5sig[16];
172 uint8 lenhdr[4];
173 SHA_CTX sha;
174 MD5_CTX md5;
175
176 buf_out_uint32(lenhdr, datalen);
177
178 SHA1_Init(&sha);
179 SHA1_Update(&sha, session_key, keylen);
180 SHA1_Update(&sha, pad_54, 40);
181 SHA1_Update(&sha, lenhdr, 4);
182 SHA1_Update(&sha, data, datalen);
183 SHA1_Final(shasig, &sha);
184
185 MD5_Init(&md5);
186 MD5_Update(&md5, session_key, keylen);
187 MD5_Update(&md5, pad_92, 48);
188 MD5_Update(&md5, shasig, 20);
189 MD5_Final(md5sig, &md5);
190
191 memcpy(signature, md5sig, siglen);
192}
193
194/* Update an encryption key */
195static void
197{
198 uint8 shasig[20];
199 SHA_CTX sha;
200 MD5_CTX md5;
201 RC4_KEY update;
202
203 SHA1_Init(&sha);
204 SHA1_Update(&sha, update_key, This->secure.rc4_key_len);
205 SHA1_Update(&sha, pad_54, 40);
206 SHA1_Update(&sha, key, This->secure.rc4_key_len);
207 SHA1_Final(shasig, &sha);
208
209 MD5_Init(&md5);
210 MD5_Update(&md5, update_key, This->secure.rc4_key_len);
211 MD5_Update(&md5, pad_92, 48);
212 MD5_Update(&md5, shasig, 20);
213 MD5_Final(key, &md5);
214
215 RC4_set_key(&update, This->secure.rc4_key_len, key);
216 RC4(&update, This->secure.rc4_key_len, key, key);
217
218 if (This->secure.rc4_key_len == 8)
220}
221
222/* Encrypt data using RC4 */
223static void
225{
226 if (This->secure.encrypt_use_count == 4096)
227 {
228 sec_update(This, This->secure.encrypt_key, This->secure.encrypt_update_key);
229 RC4_set_key(&This->secure.rc4_encrypt_key, This->secure.rc4_key_len, This->secure.encrypt_key);
230 This->secure.encrypt_use_count = 0;
231 }
232
233 RC4(&This->secure.rc4_encrypt_key, length, data, data);
234 This->secure.encrypt_use_count++;
235}
236
237/* Decrypt data using RC4 */
238void
240{
241 if (This->secure.decrypt_use_count == 4096)
242 {
243 sec_update(This, This->secure.decrypt_key, This->secure.decrypt_update_key);
244 RC4_set_key(&This->secure.rc4_decrypt_key, This->secure.rc4_key_len, This->secure.decrypt_key);
245 This->secure.decrypt_use_count = 0;
246 }
247
248 RC4(&This->secure.rc4_decrypt_key, length, data, data);
249 This->secure.decrypt_use_count++;
250}
251
252static void
254{
255 int i, j;
256 uint8 temp;
257
258 for (i = 0, j = len - 1; i < j; i++, j--)
259 {
260 temp = p[i];
261 p[i] = p[j];
262 p[j] = temp;
263 }
264}
265
266/* Perform an RSA public key encryption operation */
267static void
269 uint8 * exponent)
270{
271 BN_CTX *ctx;
272 BIGNUM mod, exp, x, y;
274 int outlen;
275
276 reverse(modulus, modulus_size);
277 reverse(exponent, SEC_EXPONENT_SIZE);
278 memcpy(inr, in, len);
279 reverse(inr, len);
280
281 ctx = BN_CTX_new();
282 BN_init(&mod);
283 BN_init(&exp);
284 BN_init(&x);
285 BN_init(&y);
286
287 BN_bin2bn(modulus, modulus_size, &mod);
288 BN_bin2bn(exponent, SEC_EXPONENT_SIZE, &exp);
289 BN_bin2bn(inr, len, &x);
290 BN_mod_exp(&y, &x, &exp, &mod, ctx);
291 outlen = BN_bn2bin(&y, out);
292 reverse(out, outlen);
293 if ((uint32)outlen < modulus_size)
294 memset(out + outlen, 0, modulus_size - outlen);
295
296 BN_free(&y);
297 BN_clear_free(&x);
298 BN_free(&exp);
299 BN_free(&mod);
300 BN_CTX_free(ctx);
301}
302
303/* Initialise secure transport packet */
304STREAM
306{
307 int hdrlen;
308 STREAM s;
309
310 if (!This->licence_issued)
311 hdrlen = (flags & SEC_ENCRYPT) ? 12 : 4;
312 else
313 hdrlen = (flags & SEC_ENCRYPT) ? 12 : 0;
314 s = mcs_init(This, maxlen + hdrlen);
315
316 if(s == NULL)
317 return s;
318
319 s_push_layer(s, sec_hdr, hdrlen);
320
321 return s;
322}
323
324/* Transmit secure transport packet over specified channel */
325
326// !!! we need a lock here !!!
327BOOL
329{
330 int datalen;
331
332 s_pop_layer(s, sec_hdr);
333 if (!This->licence_issued || (flags & SEC_ENCRYPT))
335
336 if (flags & SEC_ENCRYPT)
337 {
338 flags &= ~SEC_ENCRYPT;
339 datalen = (int)(s->end - s->p - 8);
340
341#if WITH_DEBUG
342 DEBUG(("Sending encrypted packet:\n"));
343 hexdump(s->p + 8, datalen);
344#endif
345
346 sec_sign(s->p, 8, This->secure.sign_key, This->secure.rc4_key_len, s->p + 8, datalen);
347 sec_encrypt(This, s->p + 8, datalen);
348 }
349
350 return mcs_send_to_channel(This, s, channel);
351}
352
353/* Transmit secure transport packet */
354
355BOOL
357{
359}
360
361
362/* Transfer the client random to the server */
363static void
365{
366 uint32 length = This->secure.server_public_key_len + SEC_PADDING_SIZE;
368 STREAM s;
369
370 s = sec_init(This, flags, length + 4);
371
373 out_uint8p(s, This->secure.crypted_random, This->secure.server_public_key_len);
375
376 s_mark_end(s);
377 sec_send(This, s, flags);
378}
379
380/* Output connect initial data blob */
381static void
383{
384 int hostlen = 2 * (int)wcslen(hostname);
385 int length = 158 + 76 + 12 + 4;
386 unsigned int i;
387
388 if (This->num_channels > 0)
389 length += This->num_channels * 12 + 8;
390
391 if (hostlen > 30)
392 hostlen = 30;
393
394 /* Generic Conference Control (T.124) ConferenceCreateRequest */
395 out_uint16_be(s, 5);
396 out_uint16_be(s, 0x14);
397 out_uint8(s, 0x7c);
398 out_uint16_be(s, 1);
399
400 out_uint16_be(s, (length | 0x8000)); /* remaining length */
401
402 out_uint16_be(s, 8); /* length? */
403 out_uint16_be(s, 16);
404 out_uint8(s, 0);
405 out_uint16_le(s, 0xc001);
406 out_uint8(s, 0);
407
408 out_uint32_le(s, 0x61637544); /* OEM ID: "Duca", as in Ducati. */
409 out_uint16_be(s, ((length - 14) | 0x8000)); /* remaining length */
410
411 /* Client information */
413 out_uint16_le(s, 212); /* length */
414 out_uint16_le(s, This->use_rdp5 ? 4 : 1); /* RDP version. 1 == RDP4, 4 == RDP5. */
415 out_uint16_le(s, 8);
416 out_uint16_le(s, This->width);
417 out_uint16_le(s, This->height);
418 out_uint16_le(s, 0xca01);
419 out_uint16_le(s, 0xaa03);
420 out_uint32_le(s, This->keylayout);
421 out_uint32_le(s, 2600); /* Client build. We are now 2600 compatible :-) */
422
423 /* Unicode name of client, padded to 32 bytes */
424 rdp_out_unistr(This, s, hostname, hostlen);
425 out_uint8s(s, 30 - hostlen);
426
427 /* See
428 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wceddk40/html/cxtsksupportingremotedesktopprotocol.asp */
429 out_uint32_le(s, This->keyboard_type);
430 out_uint32_le(s, This->keyboard_subtype);
431 out_uint32_le(s, This->keyboard_functionkeys);
432 out_uint8s(s, 64); /* reserved? 4 + 12 doublewords */
433 out_uint16_le(s, 0xca01); /* colour depth? */
434 out_uint16_le(s, 1);
435
436 out_uint32(s, 0);
437 out_uint8(s, This->server_depth);
438 out_uint16_le(s, 0x0700);
439 out_uint8(s, 0);
440 out_uint32_le(s, 1);
441 out_uint8s(s, 64); /* End of client info */
442
444 out_uint16_le(s, 12);
445 out_uint32_le(s, This->console_session ? 0xb : 9);
446 out_uint32(s, 0);
447
448 /* Client encryption settings */
450 out_uint16_le(s, 12); /* length */
451 out_uint32_le(s, This->encryption ? 0x3 : 0); /* encryption supported, 128-bit supported */
452 out_uint32(s, 0); /* Unknown */
453
454 DEBUG_RDP5(("This->num_channels is %d\n", This->num_channels));
455 if (This->num_channels > 0)
456 {
458 out_uint16_le(s, This->num_channels * 12 + 8); /* length */
459 out_uint32_le(s, This->num_channels); /* number of virtual channels */
460 for (i = 0; i < This->num_channels; i++)
461 {
462 DEBUG_RDP5(("Requesting channel %s\n", This->channels[i].name));
463 out_uint8a(s, This->channel_defs[i].name, 8);
464 out_uint32_be(s, This->channel_defs[i].options);
465 }
466 }
467
468 s_mark_end(s);
469}
470
471/* Parse a public key structure */
472static BOOL
474{
475 uint32 magic, modulus_len;
476
478 if (magic != SEC_RSA_MAGIC)
479 {
480 error("RSA magic 0x%x\n", magic);
481 return False;
482 }
483
484 in_uint32_le(s, modulus_len);
485 modulus_len -= SEC_PADDING_SIZE;
486 if ((modulus_len < 64) || (modulus_len > SEC_MAX_MODULUS_SIZE))
487 {
488 error("Bad server public key size (%u bits)\n", modulus_len * 8);
489 return False;
490 }
491
492 in_uint8s(s, 8); /* modulus_bits, unknown */
493 in_uint8p(s, *exponent, SEC_EXPONENT_SIZE);
494 in_uint8p(s, *modulus, modulus_len);
496 This->secure.server_public_key_len = modulus_len;
497
498 return s_check(s);
499}
500
501static BOOL
503{
504 EVP_PKEY *epk = NULL;
505 /* By some reason, Microsoft sets the OID of the Public RSA key to
506 the oid for "MD5 with RSA Encryption" instead of "RSA Encryption"
507
508 Kudos to Richard Levitte for the following (. intiutive .)
509 lines of code that resets the OID and let's us extract the key. */
510 if (OBJ_obj2nid(cert->cert_info->key->algor->algorithm) == NID_md5WithRSAEncryption)
511 {
512 DEBUG_RDP5(("Re-setting algorithm type to RSA in server certificate\n"));
513 ASN1_OBJECT_free(cert->cert_info->key->algor->algorithm);
514 cert->cert_info->key->algor->algorithm = OBJ_nid2obj(NID_rsaEncryption);
515 }
516 epk = X509_get_pubkey(cert);
517 if (NULL == epk)
518 {
519 error("Failed to extract public key from certificate\n");
520 return False;
521 }
522
523 This->secure.server_public_key = RSAPublicKey_dup((RSA *) epk->pkey.ptr);
524 EVP_PKEY_free(epk);
525
526 This->secure.server_public_key_len = RSA_size(This->secure.server_public_key);
527 if ((This->secure.server_public_key_len < 64) || (This->secure.server_public_key_len > SEC_MAX_MODULUS_SIZE))
528 {
529 error("Bad server public key size (%u bits)\n", This->secure.server_public_key_len * 8);
530 return False;
531 }
532
533 return True;
534}
535
536
537/* Parse a crypto information structure */
538static BOOL
540 uint8 ** server_random, uint8 ** modulus, uint8 ** exponent)
541{
542 uint32 crypt_level, random_len, rsa_info_len;
543 uint32 cacert_len, cert_len, flags;
544 X509 *cacert, *server_cert;
546 uint8 *next_tag, *end;
547
548 in_uint32_le(s, *rc4_key_size); /* 1 = 40-bit, 2 = 128-bit */
549 in_uint32_le(s, crypt_level); /* 1 = low, 2 = medium, 3 = high */
550 if (crypt_level == 0) /* no encryption */
551 return False;
552 in_uint32_le(s, random_len);
553 in_uint32_le(s, rsa_info_len);
554
555 if (random_len != SEC_RANDOM_SIZE)
556 {
557 error("random len %d, expected %d\n", random_len, SEC_RANDOM_SIZE);
558 return False;
559 }
560
561 in_uint8p(s, *server_random, random_len);
562
563 /* RSA info */
564 end = s->p + rsa_info_len;
565 if (end > s->end)
566 return False;
567
568 in_uint32_le(s, flags); /* 1 = RDP4-style, 0x80000002 = X.509 */
569 if (flags & 1)
570 {
571 DEBUG_RDP5(("We're going for the RDP4-style encryption\n"));
572 in_uint8s(s, 8); /* unknown */
573
574 while (s->p < end)
575 {
578
579 next_tag = s->p + length;
580
581 switch (tag)
582 {
583 case SEC_TAG_PUBKEY:
584 if (!sec_parse_public_key(This, s, modulus, exponent))
585 return False;
586 DEBUG_RDP5(("Got Public key, RDP4-style\n"));
587
588 break;
589
590 case SEC_TAG_KEYSIG:
591 /* Is this a Microsoft key that we just got? */
592 /* Care factor: zero! */
593 /* Actually, it would probably be a good idea to check if the public key is signed with this key, and then store this
594 key as a known key of the hostname. This would prevent some MITM-attacks. */
595 break;
596
597 default:
598 unimpl("crypt tag 0x%x\n", tag);
599 }
600
601 s->p = next_tag;
602 }
603 }
604 else
605 {
606 uint32 certcount;
607
608 DEBUG_RDP5(("We're going for the RDP5-style encryption\n"));
609 in_uint32_le(s, certcount); /* Number of certificates */
610
611 if (certcount < 2)
612 {
613 error("Server didn't send enough X509 certificates\n");
614 This->disconnect_reason = 1798;
615 return False;
616 }
617
618 for (; certcount > 2; certcount--)
619 { /* ignore all the certificates between the root and the signing CA */
620 uint32 ignorelen;
621 X509 *ignorecert;
622
623 DEBUG_RDP5(("Ignored certs left: %d\n", certcount));
624
625 in_uint32_le(s, ignorelen);
626 DEBUG_RDP5(("Ignored Certificate length is %d\n", ignorelen));
627 ignorecert = d2i_X509(NULL, &(s->p), ignorelen);
628
629 if (ignorecert == NULL)
630 { /* XXX: error out? */
631 DEBUG_RDP5(("got a bad cert: this will probably screw up the rest of the communication\n"));
632 }
633
634#ifdef WITH_DEBUG_RDP5
635 DEBUG_RDP5(("cert #%d (ignored):\n", certcount));
636 X509_print_fp(stdout, ignorecert);
637#endif
638 }
639
640 /* Do da funky X.509 stuffy
641
642 "How did I find out about this? I looked up and saw a
643 bright light and when I came to I had a scar on my forehead
644 and knew about X.500"
645 - Peter Gutman in a early version of
646 http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
647 */
648
649 in_uint32_le(s, cacert_len);
650 DEBUG_RDP5(("CA Certificate length is %d\n", cacert_len));
651 cacert = d2i_X509(NULL, &(s->p), cacert_len);
652 /* Note: We don't need to move s->p here - d2i_X509 is
653 "kind" enough to do it for us */
654 if (NULL == cacert)
655 {
656 error("Couldn't load CA Certificate from server\n");
657 This->disconnect_reason = 1798;
658 return False;
659 }
660
661 /* Currently, we don't use the CA Certificate.
662 FIXME:
663 *) Verify the server certificate (server_cert) with the
664 CA certificate.
665 *) Store the CA Certificate with the hostname of the
666 server we are connecting to as key, and compare it
667 when we connect the next time, in order to prevent
668 MITM-attacks.
669 */
670
671 X509_free(cacert);
672
673 in_uint32_le(s, cert_len);
674 DEBUG_RDP5(("Certificate length is %d\n", cert_len));
675 server_cert = d2i_X509(NULL, &(s->p), cert_len);
676 if (NULL == server_cert)
677 {
678 error("Couldn't load Certificate from server\n");
679 This->disconnect_reason = 1798;
680 return False;
681 }
682
683 in_uint8s(s, 16); /* Padding */
684
685 /* Note: Verifying the server certificate must be done here,
686 before sec_parse_public_key since we'll have to apply
687 serious violence to the key after this */
688
689 if (!sec_parse_x509_key(This, server_cert))
690 {
691 DEBUG_RDP5(("Didn't parse X509 correctly\n"));
692 X509_free(server_cert);
693 This->disconnect_reason = 1798;
694 return False;
695 }
696 X509_free(server_cert);
697 return True; /* There's some garbage here we don't care about */
698 }
699 return s_check_end(s);
700}
701
702/* Process crypto information blob */
703static void
705{
706 uint8 *server_random, *modulus, *exponent;
707 uint8 client_random[SEC_RANDOM_SIZE];
708 uint32 rc4_key_size;
709
710 if (!sec_parse_crypt_info(This, s, &rc4_key_size, &server_random, &modulus, &exponent))
711 {
712 DEBUG(("Failed to parse crypt info\n"));
713 return;
714 }
715
716 DEBUG(("Generating client random\n"));
717 generate_random(client_random);
718
719 if (NULL != This->secure.server_public_key)
720 { /* Which means we should use
721 RDP5-style encryption */
723 uint32 padding_len = This->secure.server_public_key_len - SEC_RANDOM_SIZE;
724
725 /* This is what the MS client do: */
726 memset(inr, 0, padding_len);
727 /* *ARIGL!* Plaintext attack, anyone?
728 I tried doing:
729 generate_random(inr);
730 ..but that generates connection errors now and then (yes,
731 "now and then". Something like 0 to 3 attempts needed before a
732 successful connection. Nice. Not!
733 */
734 memcpy(inr + padding_len, client_random, SEC_RANDOM_SIZE);
735 reverse(inr + padding_len, SEC_RANDOM_SIZE);
736
737 RSA_public_encrypt(This->secure.server_public_key_len,
738 inr, This->secure.crypted_random, This->secure.server_public_key, RSA_NO_PADDING);
739
740 reverse(This->secure.crypted_random, This->secure.server_public_key_len);
741
742 RSA_free(This->secure.server_public_key);
743 This->secure.server_public_key = NULL;
744 }
745 else
746 { /* RDP4-style encryption */
747 sec_rsa_encrypt(This->secure.crypted_random,
748 client_random, SEC_RANDOM_SIZE, This->secure.server_public_key_len, modulus,
749 exponent);
750 }
751 sec_generate_keys(This, client_random, server_random, rc4_key_size);
752}
753
754
755/* Process SRV_INFO, find RDP version supported by server */
756static void
758{
759 in_uint16_le(s, This->server_rdp_version);
760 DEBUG_RDP5(("Server RDP version is %d\n", This->server_rdp_version));
761 if (1 == This->server_rdp_version)
762 {
763 This->use_rdp5 = 0;
764 This->server_depth = 8;
765 }
766}
767
768
769/* Process connect response data blob */
770void
772{
774 uint8 *next_tag;
775 uint8 len;
776
777 in_uint8s(s, 21); /* header (T.124 ConferenceCreateResponse) */
778 in_uint8(s, len);
779 if (len & 0x80)
780 in_uint8(s, len);
781
782 while (s->p < s->end)
783 {
786
787 if (length <= 4)
788 return;
789
790 next_tag = s->p + length - 4;
791
792 switch (tag)
793 {
794 case SEC_TAG_SRV_INFO:
796 break;
797
800 break;
801
803 /* FIXME: We should parse this information and
804 use it to map RDP5 channels to MCS
805 channels */
806 break;
807
808 default:
809 unimpl("response tag 0x%x\n", tag);
810 }
811
812 s->p = next_tag;
813 }
814}
815
816/* Receive secure transport packet */
817STREAM
819{
820 uint32 sec_flags;
821 uint16 channel;
822 STREAM s;
823
824 while ((s = mcs_recv(This, &channel, rdpver)) != NULL)
825 {
826 if (rdpver != NULL)
827 {
828 if (*rdpver != 3)
829 {
830 if (*rdpver & 0x80)
831 {
832 in_uint8s(s, 8); /* signature */
833 sec_decrypt(This, s->p, (int)(s->end - s->p));
834 }
835 return s;
836 }
837 }
838 if (This->encryption || !This->licence_issued)
839 {
840 in_uint32_le(s, sec_flags);
841
842 if (sec_flags & SEC_ENCRYPT)
843 {
844 in_uint8s(s, 8); /* signature */
845 sec_decrypt(This, s->p, (int)(s->end - s->p));
846 }
847
848 if (sec_flags & SEC_LICENCE_NEG)
849 {
851 continue;
852 }
853
854 if (sec_flags & 0x0400) /* SEC_REDIRECT_ENCRYPT */
855 {
856 uint8 swapbyte;
857
858 in_uint8s(s, 8); /* signature */
859 sec_decrypt(This, s->p, (int)(s->end - s->p));
860
861 /* Check for a redirect packet, starts with 00 04 */
862 if (s->p[0] == 0 && s->p[1] == 4)
863 {
864 /* for some reason the PDU and the length seem to be swapped.
865 This isn't good, but we're going to do a byte for byte
866 swap. So the first foure value appear as: 00 04 XX YY,
867 where XX YY is the little endian length. We're going to
868 use 04 00 as the PDU type, so after our swap this will look
869 like: XX YY 04 00 */
870 swapbyte = s->p[0];
871 s->p[0] = s->p[2];
872 s->p[2] = swapbyte;
873
874 swapbyte = s->p[1];
875 s->p[1] = s->p[3];
876 s->p[3] = swapbyte;
877
878 swapbyte = s->p[2];
879 s->p[2] = s->p[3];
880 s->p[3] = swapbyte;
881 }
882#ifdef WITH_DEBUG
883 /* warning! this debug statement will show passwords in the clear! */
884 hexdump(s->p, s->end - s->p);
885#endif
886 }
887
888 }
889
890 if (channel != MCS_GLOBAL_CHANNEL)
891 {
892 channel_process(This, s, channel);
893 *rdpver = 0xff;
894 return s;
895 }
896
897 return s;
898 }
899
900 return NULL;
901}
902
903/* Establish a secure connection */
904BOOL
905sec_connect(RDPCLIENT * This, char *server, wchar_t *hostname, char *cookie)
906{
907 struct stream mcs_data;
908 void * p = malloc(512);
909
910 if(p == NULL)
911 {
912 This->disconnect_reason = 262;
913 return False;
914 }
915
916 /* We exchange some RDP data during the MCS-Connect */
917 mcs_data.size = 512;
918 mcs_data.p = mcs_data.data = (uint8 *) p;
919 sec_out_mcs_data(This, &mcs_data, hostname);
920
921 if (!mcs_connect(This, server, cookie, &mcs_data))
922 return False;
923
924 /* sec_process_mcs_data(&mcs_data); */
925 if (This->encryption)
927 free(mcs_data.data);
928 return True;
929}
930
931/* Establish a secure connection */
932BOOL
934{
935 struct stream mcs_data;
936 void * p = malloc(512);
937
938 if(p == NULL)
939 {
940 This->disconnect_reason = 262;
941 return False;
942 }
943
944 /* We exchange some RDP data during the MCS-Connect */
945 mcs_data.size = 512;
946 mcs_data.p = mcs_data.data = (uint8 *) p;
947 sec_out_mcs_data(This, &mcs_data, hostname);
948
949 if (!mcs_reconnect(This, server, cookie, &mcs_data))
950 return False;
951
952 /* sec_process_mcs_data(&mcs_data); */
953 if (This->encryption)
955 free(mcs_data.data);
956 return True;
957}
958
959/* Disconnect a connection */
960void
962{
964}
965
966/* reset the state of the sec layer */
967void
969{
970 This->server_rdp_version = 0;
971 This->secure.encrypt_use_count = 0;
972 This->secure.decrypt_use_count = 0;
974}
void channel_process(STREAM s, uint16 mcs_channel)
Definition: channels.c:138
#define SEC_EXPONENT_SIZE
Definition: constants.h:95
#define SEC_PADDING_SIZE
Definition: constants.h:94
#define SEC_TAG_CLI_CRYPT
Definition: constants.h:120
#define SEC_TAG_SRV_INFO
Definition: constants.h:115
#define SEC_TAG_KEYSIG
Definition: constants.h:125
#define SEC_TAG_SRV_CRYPT
Definition: constants.h:116
#define SEC_TAG_SRV_CHANNELS
Definition: constants.h:117
#define SEC_TAG_PUBKEY
Definition: constants.h:124
#define SEC_ENCRYPT
Definition: constants.h:101
#define SEC_RSA_MAGIC
Definition: constants.h:127
#define SEC_TAG_CLI_CHANNELS
Definition: constants.h:121
#define SEC_MAX_MODULUS_SIZE
Definition: constants.h:93
#define SEC_TAG_CLI_INFO
Definition: constants.h:119
#define MCS_GLOBAL_CHANNEL
Definition: constants.h:87
#define SEC_RANDOM_SIZE
Definition: constants.h:91
void licence_process(STREAM s)
Definition: licence.c:378
STREAM mcs_init(int length)
Definition: mcs.c:242
void mcs_reset_state(void)
Definition: mcs.c:363
STREAM mcs_recv(uint16 *channel, uint8 *rdpver)
Definition: mcs.c:280
void mcs_disconnect(void)
Definition: mcs.c:356
void mcs_send_to_channel(STREAM s, uint16 channel)
Definition: mcs.c:254
#define s_mark_end(s)
Definition: parse.h:41
#define out_uint32_le(s, v)
Definition: parse.h:59
#define s_check(s)
Definition: parse.h:42
#define out_uint32_be(s, v)
Definition: parse.h:78
#define s_pop_layer(s, h)
Definition: parse.h:40
#define out_uint8(s, v)
Definition: parse.h:92
#define s_push_layer(s, h, n)
Definition: parse.h:39
#define in_uint16_le(s, v)
Definition: parse.h:55
#define out_uint16_be(s, v)
Definition: parse.h:77
#define in_uint8p(s, v, n)
Definition: parse.h:89
#define s_check_end(s)
Definition: parse.h:44
#define in_uint8s(s, n)
Definition: parse.h:91
#define out_uint8s(s, n)
Definition: parse.h:95
#define in_uint8(s, v)
Definition: parse.h:88
#define out_uint16_le(s, v)
Definition: parse.h:58
#define out_uint8p(s, v, n)
Definition: parse.h:93
#define out_uint32(s, v)
Definition: parse.h:85
#define in_uint32_le(s, v)
Definition: parse.h:56
#define out_uint8a(s, v, n)
Definition: parse.h:94
void unimpl(char *format,...)
Definition: uimain.c:801
void hexdump(unsigned char *p, unsigned int len)
Definition: shimdbg.c:234
void rdp_out_unistr(STREAM s, char *string, int len)
Definition: rdp.c:188
void generate_random(uint8 *random)
Definition: uimain.c:709
#define DEBUG_RDP5(args)
Definition: rdesktop.h:141
#define DEBUG(args)
Definition: rdesktop.h:129
void sec_process_mcs_data(STREAM s)
Definition: secure.c:856
static void sec_generate_keys(uint8 *client_random, uint8 *server_random, int rc4_key_size)
Definition: secure.c:238
void sec_hash_48(uint8 *out, uint8 *in, uint8 *salt1, uint8 *salt2, uint8 salt)
Definition: secure.c:155
static void sec_make_40bit(uint8 *key)
Definition: secure.c:229
void buf_out_uint32(uint8 *buffer, uint32 value)
Definition: secure.c:304
static RD_BOOL sec_parse_public_key(STREAM s, uint8 *modulus, uint8 *exponent)
Definition: secure.c:599
static void sec_out_mcs_data(STREAM s, uint32 selected_protocol)
Definition: secure.c:498
static uint8 pad_54[40]
Definition: secure.c:288
void sec_send(STREAM s, uint32 flags)
Definition: secure.c:472
static RD_BOOL sec_parse_crypt_info(STREAM s, uint32 *rc4_key_size, uint8 **server_random, uint8 *modulus, uint8 *exponent)
Definition: secure.c:652
RD_BOOL sec_connect(char *server, char *username, char *domain, char *password, RD_BOOL reconnect)
Definition: secure.c:1005
void sec_send_to_channel(STREAM s, uint32 flags, uint16 channel)
Definition: secure.c:436
void sec_reset_state(void)
Definition: secure.c:1039
void sec_disconnect(void)
Definition: secure.c:1032
static void sec_update(uint8 *key, uint8 *update_key)
Definition: secure.c:346
static uint8 pad_92[48]
Definition: secure.c:295
static void sec_establish_key(void)
Definition: secure.c:480
static void sec_rsa_encrypt(uint8 *out, uint8 *in, int len, uint32 modulus_size, uint8 *modulus, uint8 *exponent)
Definition: secure.c:411
void sec_hash_16(uint8 *out, uint8 *in, uint8 *salt1, uint8 *salt2)
Definition: secure.c:187
STREAM sec_recv(uint8 *rdpver)
Definition: secure.c:903
static void sec_process_srv_info(STREAM s)
Definition: secure.c:842
STREAM sec_init(uint32 flags, int maxlen)
Definition: secure.c:419
static void sec_process_crypt_info(STREAM s)
Definition: secure.c:818
static void sec_encrypt(uint8 *data, int length)
Definition: secure.c:381
void sec_sign(uint8 *signature, int siglen, uint8 *session_key, int keylen, uint8 *data, int datalen)
Definition: secure.c:314
void sec_decrypt(uint8 *data, int length)
Definition: secure.c:396
unsigned short uint16
Definition: types.h:30
unsigned int uint32
Definition: types.h:32
#define False
Definition: types.h:25
#define True
Definition: types.h:24
unsigned char uint8
Definition: types.h:28
char * hostname
Definition: ftp.c:88
#define md5
Definition: compat-1.3.h:2034
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
static const WCHAR RSA[]
Definition: oid.c:1223
static const WCHAR sha[]
Definition: oid.c:1218
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
unsigned int BOOL
Definition: ntddk_ex.h:94
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLdouble s
Definition: gl.h:2039
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLuint GLuint end
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLuint buffer
Definition: glext.h:5915
GLuint in
Definition: glext.h:9616
GLbitfield flags
Definition: glext.h:7161
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
static int mod
Definition: i386-dis.c:1288
#define stdout
Definition: stdio.h:99
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
int const JOCTET unsigned int datalen
Definition: jpeglib.h:1031
#define error(str)
Definition: mkdosfs.c:1605
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define SEC_TAG_CLI_4
Definition: constants.h:82
#define SEC_LICENCE_NEG
Definition: constants.h:72
#define SEC_CLIENT_RANDOM
Definition: constants.h:69
BOOL mcs_connect(RDPCLIENT *This, char *server, char *cookie, STREAM mcs_data)
Definition: mcs.c:388
BOOL mcs_reconnect(RDPCLIENT *This, char *server, char *cookie, STREAM mcs_data)
Definition: mcs.c:424
BOOL sec_reconnect(RDPCLIENT *This, char *server, wchar_t *hostname, char *cookie)
Definition: secure.c:933
static BOOL sec_parse_x509_key(RDPCLIENT *This, X509 *cert)
Definition: secure.c:502
static void reverse(uint8 *p, int len)
Definition: secure.c:253
static BYTE cert[]
Definition: msg.c:1437
DWORD exp
Definition: msg.c:16058
u32_t magic(void)
static FILE * out
Definition: regtests2xml.c:44
static calc_node_t temp
Definition: rpn_ieee.c:38
void MD5_Init(MD5_CTX *ctx)
Definition: md5.c:207
void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
Definition: md5.c:218
void MD5_Final(unsigned char *result, MD5_CTX *ctx)
Definition: md5.c:258
#define memset(x, y, z)
Definition: compat.h:39
Definition: msi.c:4013
Definition: addons.c:69
Definition: cookie.c:34
Definition: copy.c:22
Definition: parse.h:23
unsigned char * p
Definition: parse.h:24
unsigned int size
Definition: parse.h:27
unsigned char * data
Definition: parse.h:26
Definition: ecma_167.h:138
Definition: pdh_main.c:94
static rfbScreenInfoPtr server
Definition: vnc.c:74