ReactOS 0.4.16-dev-338-g34e76ad
secure.c File Reference
#include "rdesktop.h"
#include <string.h>
#include <openssl/rc4.h>
#include <openssl/md5.h>
#include <openssl/sha.h>
#include <openssl/bn.h>
#include <openssl/x509v3.h>
Include dependency graph for secure.c:

Go to the source code of this file.

Functions

void sec_hash_48 (uint8 *out, uint8 *in, uint8 *salt1, uint8 *salt2, uint8 salt)
 
void sec_hash_16 (uint8 *out, uint8 *in, uint8 *salt1, uint8 *salt2)
 
static void sec_make_40bit (uint8 *key)
 
static void sec_generate_keys (RDPCLIENT *This, uint8 *client_random, uint8 *server_random, int rc4_key_size)
 
void buf_out_uint32 (uint8 *buffer, uint32 value)
 
void sec_sign (uint8 *signature, int siglen, uint8 *session_key, int keylen, uint8 *data, int datalen)
 
static void sec_update (RDPCLIENT *This, uint8 *key, uint8 *update_key)
 
static void sec_encrypt (RDPCLIENT *This, uint8 *data, int length)
 
void sec_decrypt (RDPCLIENT *This, uint8 *data, int length)
 
static void reverse (uint8 *p, int len)
 
static void sec_rsa_encrypt (uint8 *out, uint8 *in, int len, uint32 modulus_size, uint8 *modulus, uint8 *exponent)
 
STREAM sec_init (RDPCLIENT *This, uint32 flags, int maxlen)
 
BOOL sec_send_to_channel (RDPCLIENT *This, STREAM s, uint32 flags, uint16 channel)
 
BOOL sec_send (RDPCLIENT *This, STREAM s, uint32 flags)
 
static void sec_establish_key (RDPCLIENT *This)
 
static void sec_out_mcs_data (RDPCLIENT *This, STREAM s, wchar_t *hostname)
 
static BOOL sec_parse_public_key (RDPCLIENT *This, STREAM s, uint8 **modulus, uint8 **exponent)
 
static BOOL sec_parse_x509_key (RDPCLIENT *This, X509 *cert)
 
static BOOL sec_parse_crypt_info (RDPCLIENT *This, STREAM s, uint32 *rc4_key_size, uint8 **server_random, uint8 **modulus, uint8 **exponent)
 
static void sec_process_crypt_info (RDPCLIENT *This, STREAM s)
 
static void sec_process_srv_info (RDPCLIENT *This, STREAM s)
 
void sec_process_mcs_data (RDPCLIENT *This, STREAM s)
 
STREAM sec_recv (RDPCLIENT *This, uint8 *rdpver)
 
BOOL sec_connect (RDPCLIENT *This, char *server, wchar_t *hostname, char *cookie)
 
BOOL sec_reconnect (RDPCLIENT *This, char *server, wchar_t *hostname, char *cookie)
 
void sec_disconnect (RDPCLIENT *This)
 
void sec_reset_state (RDPCLIENT *This)
 

Variables

static const uint8 pad_54 [40]
 
static const uint8 pad_92 [48]
 

Function Documentation

◆ buf_out_uint32()

void buf_out_uint32 ( uint8 buffer,
uint32  value 
)

Definition at line 158 of file secure.c.

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}
GLuint buffer
Definition: glext.h:5915
Definition: pdh_main.c:94

Referenced by cliprdr_send_data_request(), cliprdr_send_simple_native_format_announce(), and licence_generate_hwid().

◆ reverse()

static void reverse ( uint8 p,
int  len 
)
static

Definition at line 253 of file secure.c.

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}
unsigned char uint8
Definition: types.h:28
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 calc_node_t temp
Definition: rpn_ieee.c:38

Referenced by sec_process_crypt_info(), and sec_rsa_encrypt().

◆ sec_connect()

BOOL sec_connect ( RDPCLIENT This,
char server,
wchar_t hostname,
char cookie 
)

Definition at line 905 of file secure.c.

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}
static void sec_out_mcs_data(STREAM s, uint32 selected_protocol)
Definition: secure.c:498
static void sec_establish_key(void)
Definition: secure.c:480
#define False
Definition: types.h:25
#define True
Definition: types.h:24
char * hostname
Definition: ftp.c:88
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
BOOL mcs_connect(RDPCLIENT *This, char *server, char *cookie, STREAM mcs_data)
Definition: mcs.c:388
Definition: cookie.c:34
Definition: parse.h:23
static rfbScreenInfoPtr server
Definition: vnc.c:74

◆ sec_decrypt()

void sec_decrypt ( RDPCLIENT This,
uint8 data,
int  length 
)

Definition at line 239 of file secure.c.

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}
static void sec_update(uint8 *key, uint8 *update_key)
Definition: secure.c:346
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLuint GLsizei GLsizei * length
Definition: glext.h:6040

◆ sec_disconnect()

void sec_disconnect ( RDPCLIENT This)

Definition at line 961 of file secure.c.

962{
964}
void mcs_disconnect(void)
Definition: mcs.c:356

◆ sec_encrypt()

static void sec_encrypt ( RDPCLIENT This,
uint8 data,
int  length 
)
static

Definition at line 224 of file secure.c.

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}

◆ sec_establish_key()

static void sec_establish_key ( RDPCLIENT This)
static

Definition at line 364 of file secure.c.

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}
#define SEC_PADDING_SIZE
Definition: constants.h:94
#define s_mark_end(s)
Definition: parse.h:41
#define out_uint32_le(s, v)
Definition: parse.h:59
#define out_uint8s(s, n)
Definition: parse.h:95
#define out_uint8p(s, v, n)
Definition: parse.h:93
void sec_send(STREAM s, uint32 flags)
Definition: secure.c:472
STREAM sec_init(uint32 flags, int maxlen)
Definition: secure.c:419
unsigned int uint32
Definition: types.h:32
GLdouble s
Definition: gl.h:2039
GLbitfield flags
Definition: glext.h:7161
#define SEC_CLIENT_RANDOM
Definition: constants.h:69

◆ sec_generate_keys()

static void sec_generate_keys ( RDPCLIENT This,
uint8 client_random,
uint8 server_random,
int  rc4_key_size 
)
static

Definition at line 98 of file secure.c.

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}
#define DEBUG(args)
Definition: rdesktop.h:129
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 sec_hash_16(uint8 *out, uint8 *in, uint8 *salt1, uint8 *salt2)
Definition: secure.c:187
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878

◆ sec_hash_16()

void sec_hash_16 ( uint8 out,
uint8 in,
uint8 salt1,
uint8 salt2 
)

Definition at line 76 of file secure.c.

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}
#define md5
Definition: compat-1.3.h:2034
GLuint in
Definition: glext.h:9616
static FILE * out
Definition: regtests2xml.c:44
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

Referenced by licence_generate_keys().

◆ sec_hash_48()

void sec_hash_48 ( uint8 out,
uint8 in,
uint8 salt1,
uint8 salt2,
uint8  salt 
)

Definition at line 46 of file secure.c.

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}
static const WCHAR sha[]
Definition: oid.c:1218
#define memset(x, y, z)
Definition: compat.h:39
Definition: addons.c:69

Referenced by licence_generate_keys().

◆ sec_init()

STREAM sec_init ( RDPCLIENT This,
uint32  flags,
int  maxlen 
)

Definition at line 305 of file secure.c.

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}
#define SEC_ENCRYPT
Definition: constants.h:101
STREAM mcs_init(int length)
Definition: mcs.c:242
#define s_push_layer(s, h, n)
Definition: parse.h:39

◆ sec_make_40bit()

static void sec_make_40bit ( uint8 key)
static

Definition at line 89 of file secure.c.

90{
91 key[0] = 0xd1;
92 key[1] = 0x26;
93 key[2] = 0x9e;
94}
Definition: copy.c:22

◆ sec_out_mcs_data()

static void sec_out_mcs_data ( RDPCLIENT This,
STREAM  s,
wchar_t hostname 
)
static

Definition at line 382 of file secure.c.

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}
#define SEC_TAG_CLI_CRYPT
Definition: constants.h:120
#define SEC_TAG_CLI_CHANNELS
Definition: constants.h:121
#define SEC_TAG_CLI_INFO
Definition: constants.h:119
#define out_uint32_be(s, v)
Definition: parse.h:78
#define out_uint8(s, v)
Definition: parse.h:92
#define out_uint16_be(s, v)
Definition: parse.h:77
#define out_uint16_le(s, v)
Definition: parse.h:58
#define out_uint32(s, v)
Definition: parse.h:85
#define out_uint8a(s, v, n)
Definition: parse.h:94
void rdp_out_unistr(STREAM s, char *string, int len)
Definition: rdp.c:188
#define DEBUG_RDP5(args)
Definition: rdesktop.h:141
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define SEC_TAG_CLI_4
Definition: constants.h:82

◆ sec_parse_crypt_info()

static BOOL sec_parse_crypt_info ( RDPCLIENT This,
STREAM  s,
uint32 rc4_key_size,
uint8 **  server_random,
uint8 **  modulus,
uint8 **  exponent 
)
static

Definition at line 539 of file secure.c.

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}
#define SEC_TAG_KEYSIG
Definition: constants.h:125
#define SEC_TAG_PUBKEY
Definition: constants.h:124
#define SEC_RANDOM_SIZE
Definition: constants.h:91
#define in_uint16_le(s, v)
Definition: parse.h:55
#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 in_uint32_le(s, v)
Definition: parse.h:56
void unimpl(char *format,...)
Definition: uimain.c:801
static RD_BOOL sec_parse_public_key(STREAM s, uint8 *modulus, uint8 *exponent)
Definition: secure.c:599
unsigned short uint16
Definition: types.h:30
GLuint GLuint end
Definition: gl.h:1545
#define stdout
Definition: stdio.h:99
#define error(str)
Definition: mkdosfs.c:1605
static BOOL sec_parse_x509_key(RDPCLIENT *This, X509 *cert)
Definition: secure.c:502
Definition: ecma_167.h:138

◆ sec_parse_public_key()

static BOOL sec_parse_public_key ( RDPCLIENT This,
STREAM  s,
uint8 **  modulus,
uint8 **  exponent 
)
static

Definition at line 473 of file secure.c.

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);
496 This->secure.server_public_key_len = modulus_len;
497
498 return s_check(s);
499}
#define SEC_EXPONENT_SIZE
Definition: constants.h:95
#define SEC_RSA_MAGIC
Definition: constants.h:127
#define SEC_MAX_MODULUS_SIZE
Definition: constants.h:93
#define s_check(s)
Definition: parse.h:42

◆ sec_parse_x509_key()

static BOOL sec_parse_x509_key ( RDPCLIENT This,
X509 *  cert 
)
static

Definition at line 502 of file secure.c.

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}
static const WCHAR RSA[]
Definition: oid.c:1223
static BYTE cert[]
Definition: msg.c:1437

Referenced by sec_parse_crypt_info().

◆ sec_process_crypt_info()

static void sec_process_crypt_info ( RDPCLIENT This,
STREAM  s 
)
static

Definition at line 704 of file secure.c.

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}
void generate_random(uint8 *random)
Definition: uimain.c:709
static void sec_generate_keys(uint8 *client_random, uint8 *server_random, int rc4_key_size)
Definition: secure.c:238
static RD_BOOL sec_parse_crypt_info(STREAM s, uint32 *rc4_key_size, uint8 **server_random, uint8 *modulus, uint8 *exponent)
Definition: secure.c:652
static void sec_rsa_encrypt(uint8 *out, uint8 *in, int len, uint32 modulus_size, uint8 *modulus, uint8 *exponent)
Definition: secure.c:411
static void reverse(uint8 *p, int len)
Definition: secure.c:253

◆ sec_process_mcs_data()

void sec_process_mcs_data ( RDPCLIENT This,
STREAM  s 
)

Definition at line 771 of file secure.c.

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}
#define SEC_TAG_SRV_INFO
Definition: constants.h:115
#define SEC_TAG_SRV_CRYPT
Definition: constants.h:116
#define SEC_TAG_SRV_CHANNELS
Definition: constants.h:117
#define in_uint8(s, v)
Definition: parse.h:88
static void sec_process_srv_info(STREAM s)
Definition: secure.c:842
static void sec_process_crypt_info(STREAM s)
Definition: secure.c:818

◆ sec_process_srv_info()

static void sec_process_srv_info ( RDPCLIENT This,
STREAM  s 
)
static

Definition at line 757 of file secure.c.

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}

◆ sec_reconnect()

BOOL sec_reconnect ( RDPCLIENT This,
char server,
wchar_t hostname,
char cookie 
)

Definition at line 933 of file secure.c.

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}
BOOL mcs_reconnect(RDPCLIENT *This, char *server, char *cookie, STREAM mcs_data)
Definition: mcs.c:424

Referenced by rdp_reconnect().

◆ sec_recv()

STREAM sec_recv ( RDPCLIENT This,
uint8 rdpver 
)

Definition at line 818 of file secure.c.

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}
void channel_process(STREAM s, uint16 mcs_channel)
Definition: channels.c:138
#define MCS_GLOBAL_CHANNEL
Definition: constants.h:87
void licence_process(STREAM s)
Definition: licence.c:378
STREAM mcs_recv(uint16 *channel, uint8 *rdpver)
Definition: mcs.c:280
void hexdump(unsigned char *p, unsigned int len)
Definition: shimdbg.c:234
void sec_decrypt(uint8 *data, int length)
Definition: secure.c:396
#define SEC_LICENCE_NEG
Definition: constants.h:72

◆ sec_reset_state()

void sec_reset_state ( RDPCLIENT This)

Definition at line 968 of file secure.c.

969{
970 This->server_rdp_version = 0;
971 This->secure.encrypt_use_count = 0;
972 This->secure.decrypt_use_count = 0;
974}
void mcs_reset_state(void)
Definition: mcs.c:363

◆ sec_rsa_encrypt()

static void sec_rsa_encrypt ( uint8 out,
uint8 in,
int  len,
uint32  modulus_size,
uint8 modulus,
uint8 exponent 
)
static

Definition at line 268 of file secure.c.

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}
std::map< E_MODULE, HMODULE > mod
Definition: LocaleTests.cpp:66
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
DWORD exp
Definition: msg.c:16058

◆ sec_send()

BOOL sec_send ( RDPCLIENT This,
STREAM  s,
uint32  flags 
)

Definition at line 356 of file secure.c.

357{
359}
void sec_send_to_channel(STREAM s, uint32 flags, uint16 channel)
Definition: secure.c:436

◆ sec_send_to_channel()

BOOL sec_send_to_channel ( RDPCLIENT This,
STREAM  s,
uint32  flags,
uint16  channel 
)

Definition at line 328 of file secure.c.

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}
void mcs_send_to_channel(STREAM s, uint16 channel)
Definition: mcs.c:254
#define s_pop_layer(s, h)
Definition: parse.h:40
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
int const JOCTET unsigned int datalen
Definition: jpeglib.h:1031

◆ sec_sign()

void sec_sign ( uint8 signature,
int  siglen,
uint8 session_key,
int  keylen,
uint8 data,
int  datalen 
)

Definition at line 168 of file secure.c.

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}
void buf_out_uint32(uint8 *buffer, uint32 value)
Definition: secure.c:304
static uint8 pad_54[40]
Definition: secure.c:288
static uint8 pad_92[48]
Definition: secure.c:295

Referenced by licence_process_authreq(), licence_process_demand(), licence_process_platform_challenge(), and licence_process_request().

◆ sec_update()

static void sec_update ( RDPCLIENT This,
uint8 key,
uint8 update_key 
)
static

Definition at line 196 of file secure.c.

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}

Variable Documentation

◆ pad_54

const uint8 pad_54[40]
static
Initial value:
= {
54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
54, 54, 54,
54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
54, 54, 54
}

Definition at line 142 of file secure.c.

◆ pad_92

const uint8 pad_92[48]
static
Initial value:
= {
92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
92, 92, 92, 92, 92, 92, 92,
92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
92, 92, 92, 92, 92, 92, 92
}

Definition at line 149 of file secure.c.