- Fix the LARGE_SIZE constant so it uses the lookaside list for mbuf ext buffers...
[reactos.git] / base / applications / tsclient / rdesktop / secure.c
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 */
45 void
46 sec_hash_48(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2, uint8 salt)
47 {
48 uint8 shasig[20];
49 uint8 pad[4];
50 SHA_CTX sha;
51 MD5_CTX md5;
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 */
75 void
76 sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2)
77 {
78 MD5_CTX md5;
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 */
88 static void
89 sec_make_40bit(uint8 * key)
90 {
91 key[0] = 0xd1;
92 key[1] = 0x26;
93 key[2] = 0x9e;
94 }
95
96 /* Generate encryption keys given client and server randoms */
97 static void
98 sec_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
142 static 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
149 static 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) */
157 void
158 buf_out_uint32(uint8 * buffer, uint32 value)
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 */
167 void
168 sec_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 */
195 static void
196 sec_update(RDPCLIENT * This, uint8 * key, uint8 * update_key)
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)
219 sec_make_40bit(key);
220 }
221
222 /* Encrypt data using RC4 */
223 static void
224 sec_encrypt(RDPCLIENT * This, uint8 * data, int length)
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 */
238 void
239 sec_decrypt(RDPCLIENT * This, uint8 * data, int length)
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
252 static void
253 reverse(uint8 * p, int len)
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 */
267 static void
268 sec_rsa_encrypt(uint8 * out, uint8 * in, int len, uint32 modulus_size, uint8 * modulus,
269 uint8 * exponent)
270 {
271 BN_CTX *ctx;
272 BIGNUM mod, exp, x, y;
273 uint8 inr[SEC_MAX_MODULUS_SIZE];
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 */
304 STREAM
305 sec_init(RDPCLIENT * This, uint32 flags, int maxlen)
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 !!!
327 BOOL
328 sec_send_to_channel(RDPCLIENT * This, STREAM s, uint32 flags, uint16 channel)
329 {
330 int datalen;
331
332 s_pop_layer(s, sec_hdr);
333 if (!This->licence_issued || (flags & SEC_ENCRYPT))
334 out_uint32_le(s, flags);
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
355 BOOL
356 sec_send(RDPCLIENT * This, STREAM s, uint32 flags)
357 {
358 return sec_send_to_channel(This, s, flags, MCS_GLOBAL_CHANNEL);
359 }
360
361
362 /* Transfer the client random to the server */
363 static void
364 sec_establish_key(RDPCLIENT * This)
365 {
366 uint32 length = This->secure.server_public_key_len + SEC_PADDING_SIZE;
367 uint32 flags = SEC_CLIENT_RANDOM;
368 STREAM s;
369
370 s = sec_init(This, flags, length + 4);
371
372 out_uint32_le(s, length);
373 out_uint8p(s, This->secure.crypted_random, This->secure.server_public_key_len);
374 out_uint8s(s, SEC_PADDING_SIZE);
375
376 s_mark_end(s);
377 sec_send(This, s, flags);
378 }
379
380 /* Output connect initial data blob */
381 static void
382 sec_out_mcs_data(RDPCLIENT * This, STREAM s, wchar_t * hostname)
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 */
412 out_uint16_le(s, SEC_TAG_CLI_INFO);
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
443 out_uint16_le(s, SEC_TAG_CLI_4);
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 */
449 out_uint16_le(s, SEC_TAG_CLI_CRYPT);
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 {
457 out_uint16_le(s, SEC_TAG_CLI_CHANNELS);
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 */
472 static BOOL
473 sec_parse_public_key(RDPCLIENT * This, STREAM s, uint8 ** modulus, uint8 ** exponent)
474 {
475 uint32 magic, modulus_len;
476
477 in_uint32_le(s, magic);
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);
495 in_uint8s(s, SEC_PADDING_SIZE);
496 This->secure.server_public_key_len = modulus_len;
497
498 return s_check(s);
499 }
500
501 static BOOL
502 sec_parse_x509_key(RDPCLIENT * This, X509 * cert)
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 */
538 static BOOL
539 sec_parse_crypt_info(RDPCLIENT * This, STREAM s, uint32 * rc4_key_size,
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;
545 uint16 tag, length;
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 {
576 in_uint16_le(s, tag);
577 in_uint16_le(s, length);
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 */
703 static void
704 sec_process_crypt_info(RDPCLIENT * This, STREAM s)
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 */
722 uint8 inr[SEC_MAX_MODULUS_SIZE];
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 */
756 static void
757 sec_process_srv_info(RDPCLIENT * This, STREAM s)
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 */
770 void
771 sec_process_mcs_data(RDPCLIENT * This, STREAM s)
772 {
773 uint16 tag, length;
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 {
784 in_uint16_le(s, tag);
785 in_uint16_le(s, length);
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:
795 sec_process_srv_info(This, s);
796 break;
797
798 case SEC_TAG_SRV_CRYPT:
799 sec_process_crypt_info(This, s);
800 break;
801
802 case SEC_TAG_SRV_CHANNELS:
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 */
817 STREAM
818 sec_recv(RDPCLIENT * This, uint8 * rdpver)
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 {
850 licence_process(This, s);
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 */
904 BOOL
905 sec_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)
926 sec_establish_key(This);
927 free(mcs_data.data);
928 return True;
929 }
930
931 /* Establish a secure connection */
932 BOOL
933 sec_reconnect(RDPCLIENT * This, char *server, wchar_t *hostname, char *cookie)
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)
954 sec_establish_key(This);
955 free(mcs_data.data);
956 return True;
957 }
958
959 /* Disconnect a connection */
960 void
961 sec_disconnect(RDPCLIENT * This)
962 {
963 mcs_disconnect(This);
964 }
965
966 /* reset the state of the sec layer */
967 void
968 sec_reset_state(RDPCLIENT * This)
969 {
970 This->server_rdp_version = 0;
971 This->secure.encrypt_use_count = 0;
972 This->secure.decrypt_use_count = 0;
973 mcs_reset_state(This);
974 }