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
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.
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.
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.
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>
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
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.
46 sec_hash_48(uint8
* out
, uint8
* in
, uint8
* salt1
, uint8
* salt2
, uint8 salt
)
54 for (i
= 0; i
< 3; i
++)
56 memset(pad
, salt
+ i
, i
+ 1);
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
);
66 MD5_Update(&md5
, in
, 48);
67 MD5_Update(&md5
, shasig
, 20);
68 MD5_Final(&out
[i
* 16], &md5
);
73 * 16-byte transformation used to generate export keys (6.2.2).
76 sec_hash_16(uint8
* out
, uint8
* in
, uint8
* salt1
, uint8
* salt2
)
81 MD5_Update(&md5
, in
, 16);
82 MD5_Update(&md5
, salt1
, 32);
83 MD5_Update(&md5
, salt2
, 32);
87 /* Reduce key entropy from 64 to 40 bits */
89 sec_make_40bit(uint8
* key
)
96 /* Generate encryption keys given client and server randoms */
98 sec_generate_keys(RDPCLIENT
* This
, uint8
* client_random
, uint8
* server_random
, int rc4_key_size
)
100 uint8 pre_master_secret
[48];
101 uint8 master_secret
[48];
104 /* Construct pre-master secret */
105 memcpy(pre_master_secret
, client_random
, 24);
106 memcpy(pre_master_secret
+ 24, server_random
, 24);
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');
112 /* First 16 bytes of key material is MAC secret */
113 memcpy(This
->secure
.sign_key
, key_block
, 16);
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
);
119 if (rc4_key_size
== 1)
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;
129 DEBUG(("rc_4_key_size == %d, 128-bit encryption enabled\n", rc4_key_size
));
130 This
->secure
.rc4_key_len
= 16;
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);
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
);
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,
145 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
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
156 /* Output a uint32 into a buffer (little-endian) */
158 buf_out_uint32(uint8
* buffer
, uint32 value
)
160 buffer
[0] = (value
) & 0xff;
161 buffer
[1] = (value
>> 8) & 0xff;
162 buffer
[2] = (value
>> 16) & 0xff;
163 buffer
[3] = (value
>> 24) & 0xff;
166 /* Generate a MAC hash (5.2.3.1), using a combination of SHA1 and MD5 */
168 sec_sign(uint8
* signature
, int siglen
, uint8
* session_key
, int keylen
, uint8
* data
, int datalen
)
176 buf_out_uint32(lenhdr
, datalen
);
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
);
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
);
191 memcpy(signature
, md5sig
, siglen
);
194 /* Update an encryption key */
196 sec_update(RDPCLIENT
* This
, uint8
* key
, uint8
* update_key
)
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
);
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
);
215 RC4_set_key(&update
, This
->secure
.rc4_key_len
, key
);
216 RC4(&update
, This
->secure
.rc4_key_len
, key
, key
);
218 if (This
->secure
.rc4_key_len
== 8)
222 /* Encrypt data using RC4 */
224 sec_encrypt(RDPCLIENT
* This
, uint8
* data
, int length
)
226 if (This
->secure
.encrypt_use_count
== 4096)
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;
233 RC4(&This
->secure
.rc4_encrypt_key
, length
, data
, data
);
234 This
->secure
.encrypt_use_count
++;
237 /* Decrypt data using RC4 */
239 sec_decrypt(RDPCLIENT
* This
, uint8
* data
, int length
)
241 if (This
->secure
.decrypt_use_count
== 4096)
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;
248 RC4(&This
->secure
.rc4_decrypt_key
, length
, data
, data
);
249 This
->secure
.decrypt_use_count
++;
253 reverse(uint8
* p
, int len
)
258 for (i
= 0, j
= len
- 1; i
< j
; i
++, j
--)
266 /* Perform an RSA public key encryption operation */
268 sec_rsa_encrypt(uint8
* out
, uint8
* in
, int len
, uint32 modulus_size
, uint8
* modulus
,
272 BIGNUM mod
, exp
, x
, y
;
273 uint8 inr
[SEC_MAX_MODULUS_SIZE
];
276 reverse(modulus
, modulus_size
);
277 reverse(exponent
, SEC_EXPONENT_SIZE
);
278 memcpy(inr
, in
, len
);
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
);
303 /* Initialise secure transport packet */
305 sec_init(RDPCLIENT
* This
, uint32 flags
, int maxlen
)
310 if (!This
->licence_issued
)
311 hdrlen
= (flags
& SEC_ENCRYPT
) ? 12 : 4;
313 hdrlen
= (flags
& SEC_ENCRYPT
) ? 12 : 0;
314 s
= mcs_init(This
, maxlen
+ hdrlen
);
319 s_push_layer(s
, sec_hdr
, hdrlen
);
324 /* Transmit secure transport packet over specified channel */
326 // !!! we need a lock here !!!
328 sec_send_to_channel(RDPCLIENT
* This
, STREAM s
, uint32 flags
, uint16 channel
)
332 s_pop_layer(s
, sec_hdr
);
333 if (!This
->licence_issued
|| (flags
& SEC_ENCRYPT
))
334 out_uint32_le(s
, flags
);
336 if (flags
& SEC_ENCRYPT
)
338 flags
&= ~SEC_ENCRYPT
;
339 datalen
= (int)(s
->end
- s
->p
- 8);
342 DEBUG(("Sending encrypted packet:\n"));
343 hexdump(s
->p
+ 8, datalen
);
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
);
350 return mcs_send_to_channel(This
, s
, channel
);
353 /* Transmit secure transport packet */
356 sec_send(RDPCLIENT
* This
, STREAM s
, uint32 flags
)
358 return sec_send_to_channel(This
, s
, flags
, MCS_GLOBAL_CHANNEL
);
362 /* Transfer the client random to the server */
364 sec_establish_key(RDPCLIENT
* This
)
366 uint32 length
= This
->secure
.server_public_key_len
+ SEC_PADDING_SIZE
;
367 uint32 flags
= SEC_CLIENT_RANDOM
;
370 s
= sec_init(This
, flags
, length
+ 4);
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
);
377 sec_send(This
, s
, flags
);
380 /* Output connect initial data blob */
382 sec_out_mcs_data(RDPCLIENT
* This
, STREAM s
, wchar_t * hostname
)
384 int hostlen
= 2 * (int)wcslen(hostname
);
385 int length
= 158 + 76 + 12 + 4;
388 if (This
->num_channels
> 0)
389 length
+= This
->num_channels
* 12 + 8;
394 /* Generic Conference Control (T.124) ConferenceCreateRequest */
396 out_uint16_be(s
, 0x14);
400 out_uint16_be(s
, (length
| 0x8000)); /* remaining length */
402 out_uint16_be(s
, 8); /* length? */
403 out_uint16_be(s
, 16);
405 out_uint16_le(s
, 0xc001);
408 out_uint32_le(s
, 0x61637544); /* OEM ID: "Duca", as in Ducati. */
409 out_uint16_be(s
, ((length
- 14) | 0x8000)); /* remaining length */
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. */
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 :-) */
423 /* Unicode name of client, padded to 32 bytes */
424 rdp_out_unistr(This
, s
, hostname
, hostlen
);
425 out_uint8s(s
, 30 - hostlen
);
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? */
437 out_uint8(s
, This
->server_depth
);
438 out_uint16_le(s
, 0x0700);
441 out_uint8s(s
, 64); /* End of client info */
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);
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 */
454 DEBUG_RDP5(("This->num_channels is %d\n", This
->num_channels
));
455 if (This
->num_channels
> 0)
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
++)
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
);
471 /* Parse a public key structure */
473 sec_parse_public_key(RDPCLIENT
* This
, STREAM s
, uint8
** modulus
, uint8
** exponent
)
475 uint32 magic
, modulus_len
;
477 in_uint32_le(s
, magic
);
478 if (magic
!= SEC_RSA_MAGIC
)
480 error("RSA magic 0x%x\n", magic
);
484 in_uint32_le(s
, modulus_len
);
485 modulus_len
-= SEC_PADDING_SIZE
;
486 if ((modulus_len
< 64) || (modulus_len
> SEC_MAX_MODULUS_SIZE
))
488 error("Bad server public key size (%u bits)\n", modulus_len
* 8);
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
;
502 sec_parse_x509_key(RDPCLIENT
* This
, X509
* cert
)
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"
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
)
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
);
516 epk
= X509_get_pubkey(cert
);
519 error("Failed to extract public key from certificate\n");
523 This
->secure
.server_public_key
= RSAPublicKey_dup((RSA
*) epk
->pkey
.ptr
);
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
))
529 error("Bad server public key size (%u bits)\n", This
->secure
.server_public_key_len
* 8);
537 /* Parse a crypto information structure */
539 sec_parse_crypt_info(RDPCLIENT
* This
, STREAM s
, uint32
* rc4_key_size
,
540 uint8
** server_random
, uint8
** modulus
, uint8
** exponent
)
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
;
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 */
552 in_uint32_le(s
, random_len
);
553 in_uint32_le(s
, rsa_info_len
);
555 if (random_len
!= SEC_RANDOM_SIZE
)
557 error("random len %d, expected %d\n", random_len
, SEC_RANDOM_SIZE
);
561 in_uint8p(s
, *server_random
, random_len
);
564 end
= s
->p
+ rsa_info_len
;
568 in_uint32_le(s
, flags
); /* 1 = RDP4-style, 0x80000002 = X.509 */
571 DEBUG_RDP5(("We're going for the RDP4-style encryption\n"));
572 in_uint8s(s
, 8); /* unknown */
576 in_uint16_le(s
, tag
);
577 in_uint16_le(s
, length
);
579 next_tag
= s
->p
+ length
;
584 if (!sec_parse_public_key(This
, s
, modulus
, exponent
))
586 DEBUG_RDP5(("Got Public key, RDP4-style\n"));
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. */
598 unimpl("crypt tag 0x%x\n", tag
);
608 DEBUG_RDP5(("We're going for the RDP5-style encryption\n"));
609 in_uint32_le(s
, certcount
); /* Number of certificates */
613 error("Server didn't send enough X509 certificates\n");
614 This
->disconnect_reason
= 1798;
618 for (; certcount
> 2; certcount
--)
619 { /* ignore all the certificates between the root and the signing CA */
623 DEBUG_RDP5(("Ignored certs left: %d\n", certcount
));
625 in_uint32_le(s
, ignorelen
);
626 DEBUG_RDP5(("Ignored Certificate length is %d\n", ignorelen
));
627 ignorecert
= d2i_X509(NULL
, &(s
->p
), ignorelen
);
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"));
634 #ifdef WITH_DEBUG_RDP5
635 DEBUG_RDP5(("cert #%d (ignored):\n", certcount
));
636 X509_print_fp(stdout
, ignorecert
);
640 /* Do da funky X.509 stuffy
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
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 */
656 error("Couldn't load CA Certificate from server\n");
657 This
->disconnect_reason
= 1798;
661 /* Currently, we don't use the CA Certificate.
663 *) Verify the server certificate (server_cert) with the
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
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
)
678 error("Couldn't load Certificate from server\n");
679 This
->disconnect_reason
= 1798;
683 in_uint8s(s
, 16); /* Padding */
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 */
689 if (!sec_parse_x509_key(This
, server_cert
))
691 DEBUG_RDP5(("Didn't parse X509 correctly\n"));
692 X509_free(server_cert
);
693 This
->disconnect_reason
= 1798;
696 X509_free(server_cert
);
697 return True
; /* There's some garbage here we don't care about */
699 return s_check_end(s
);
702 /* Process crypto information blob */
704 sec_process_crypt_info(RDPCLIENT
* This
, STREAM s
)
706 uint8
*server_random
, *modulus
, *exponent
;
707 uint8 client_random
[SEC_RANDOM_SIZE
];
710 if (!sec_parse_crypt_info(This
, s
, &rc4_key_size
, &server_random
, &modulus
, &exponent
))
712 DEBUG(("Failed to parse crypt info\n"));
716 DEBUG(("Generating client random\n"));
717 generate_random(client_random
);
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
;
725 /* This is what the MS client do: */
726 memset(inr
, 0, padding_len
);
727 /* *ARIGL!* Plaintext attack, anyone?
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!
734 memcpy(inr
+ padding_len
, client_random
, SEC_RANDOM_SIZE
);
735 reverse(inr
+ padding_len
, SEC_RANDOM_SIZE
);
737 RSA_public_encrypt(This
->secure
.server_public_key_len
,
738 inr
, This
->secure
.crypted_random
, This
->secure
.server_public_key
, RSA_NO_PADDING
);
740 reverse(This
->secure
.crypted_random
, This
->secure
.server_public_key_len
);
742 RSA_free(This
->secure
.server_public_key
);
743 This
->secure
.server_public_key
= NULL
;
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
,
751 sec_generate_keys(This
, client_random
, server_random
, rc4_key_size
);
755 /* Process SRV_INFO, find RDP version supported by server */
757 sec_process_srv_info(RDPCLIENT
* This
, STREAM s
)
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
)
764 This
->server_depth
= 8;
769 /* Process connect response data blob */
771 sec_process_mcs_data(RDPCLIENT
* This
, STREAM s
)
777 in_uint8s(s
, 21); /* header (T.124 ConferenceCreateResponse) */
782 while (s
->p
< s
->end
)
784 in_uint16_le(s
, tag
);
785 in_uint16_le(s
, length
);
790 next_tag
= s
->p
+ length
- 4;
794 case SEC_TAG_SRV_INFO
:
795 sec_process_srv_info(This
, s
);
798 case SEC_TAG_SRV_CRYPT
:
799 sec_process_crypt_info(This
, s
);
802 case SEC_TAG_SRV_CHANNELS
:
803 /* FIXME: We should parse this information and
804 use it to map RDP5 channels to MCS
809 unimpl("response tag 0x%x\n", tag
);
816 /* Receive secure transport packet */
818 sec_recv(RDPCLIENT
* This
, uint8
* rdpver
)
824 while ((s
= mcs_recv(This
, &channel
, rdpver
)) != NULL
)
832 in_uint8s(s
, 8); /* signature */
833 sec_decrypt(This
, s
->p
, (int)(s
->end
- s
->p
));
838 if (This
->encryption
|| !This
->licence_issued
)
840 in_uint32_le(s
, sec_flags
);
842 if (sec_flags
& SEC_ENCRYPT
)
844 in_uint8s(s
, 8); /* signature */
845 sec_decrypt(This
, s
->p
, (int)(s
->end
- s
->p
));
848 if (sec_flags
& SEC_LICENCE_NEG
)
850 licence_process(This
, s
);
854 if (sec_flags
& 0x0400) /* SEC_REDIRECT_ENCRYPT */
858 in_uint8s(s
, 8); /* signature */
859 sec_decrypt(This
, s
->p
, (int)(s
->end
- s
->p
));
861 /* Check for a redirect packet, starts with 00 04 */
862 if (s
->p
[0] == 0 && s
->p
[1] == 4)
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
883 /* warning! this debug statement will show passwords in the clear! */
884 hexdump(s
->p
, s
->end
- s
->p
);
890 if (channel
!= MCS_GLOBAL_CHANNEL
)
892 channel_process(This
, s
, channel
);
903 /* Establish a secure connection */
905 sec_connect(RDPCLIENT
* This
, char *server
, wchar_t *hostname
, char *cookie
)
907 struct stream mcs_data
;
908 void * p
= malloc(512);
912 This
->disconnect_reason
= 262;
916 /* We exchange some RDP data during the MCS-Connect */
918 mcs_data
.p
= mcs_data
.data
= (uint8
*) p
;
919 sec_out_mcs_data(This
, &mcs_data
, hostname
);
921 if (!mcs_connect(This
, server
, cookie
, &mcs_data
))
924 /* sec_process_mcs_data(&mcs_data); */
925 if (This
->encryption
)
926 sec_establish_key(This
);
931 /* Establish a secure connection */
933 sec_reconnect(RDPCLIENT
* This
, char *server
, wchar_t *hostname
, char *cookie
)
935 struct stream mcs_data
;
936 void * p
= malloc(512);
940 This
->disconnect_reason
= 262;
944 /* We exchange some RDP data during the MCS-Connect */
946 mcs_data
.p
= mcs_data
.data
= (uint8
*) p
;
947 sec_out_mcs_data(This
, &mcs_data
, hostname
);
949 if (!mcs_reconnect(This
, server
, cookie
, &mcs_data
))
952 /* sec_process_mcs_data(&mcs_data); */
953 if (This
->encryption
)
954 sec_establish_key(This
);
959 /* Disconnect a connection */
961 sec_disconnect(RDPCLIENT
* This
)
963 mcs_disconnect(This
);
966 /* reset the state of the sec layer */
968 sec_reset_state(RDPCLIENT
* This
)
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
);