summaryrefslogtreecommitdiffstats
path: root/libxrdp/xrdp_sec.c
diff options
context:
space:
mode:
Diffstat (limited to 'libxrdp/xrdp_sec.c')
-rw-r--r--libxrdp/xrdp_sec.c221
1 files changed, 143 insertions, 78 deletions
diff --git a/libxrdp/xrdp_sec.c b/libxrdp/xrdp_sec.c
index 693407a5..c1768022 100644
--- a/libxrdp/xrdp_sec.c
+++ b/libxrdp/xrdp_sec.c
@@ -292,6 +292,7 @@ xrdp_sec_delete(struct xrdp_sec *self)
ssl_rc4_info_delete(self->encrypt_rc4_info); /* TODO clear all data */
ssl_des3_info_delete(self->decrypt_fips_info);
ssl_des3_info_delete(self->encrypt_fips_info);
+ ssl_hmac_info_delete(self->sign_fips_info);
g_free(self->client_mcs_data.data);
g_free(self->server_mcs_data.data);
/* Crypto information must always be cleared */
@@ -375,50 +376,55 @@ xrdp_sec_update(char *key, char *update_key, int key_len)
/*****************************************************************************/
static void APP_CC
+xrdp_sec_fips_decrypt(struct xrdp_sec *self, char *data, int len)
+{
+ LLOGLN(10, ("xrdp_sec_fips_decrypt:"));
+ ssl_des3_decrypt(self->decrypt_fips_info, len, data, data);
+ self->decrypt_use_count++;
+}
+
+/*****************************************************************************/
+static void APP_CC
xrdp_sec_decrypt(struct xrdp_sec *self, char *data, int len)
{
- if (self->crypt_method == CRYPT_METHOD_FIPS)
+ LLOGLN(10, ("xrdp_sec_decrypt:"));
+ if (self->decrypt_use_count == 4096)
{
- ssl_des3_decrypt(self->decrypt_fips_info, len, data, data);
+ xrdp_sec_update(self->decrypt_key, self->decrypt_update_key,
+ self->rc4_key_len);
+ ssl_rc4_set_key(self->decrypt_rc4_info, self->decrypt_key,
+ self->rc4_key_len);
+ self->decrypt_use_count = 0;
}
- else
- {
- if (self->decrypt_use_count == 4096)
- {
- xrdp_sec_update(self->decrypt_key, self->decrypt_update_key,
- self->rc4_key_len);
- ssl_rc4_set_key(self->decrypt_rc4_info, self->decrypt_key,
- self->rc4_key_len);
- self->decrypt_use_count = 0;
- }
+ ssl_rc4_crypt(self->decrypt_rc4_info, data, len);
+ self->decrypt_use_count++;
+}
- ssl_rc4_crypt(self->decrypt_rc4_info, data, len);
- self->decrypt_use_count++;
- }
+/*****************************************************************************/
+static void APP_CC
+xrdp_sec_fips_encrypt(struct xrdp_sec *self, char *data, int len)
+{
+ LLOGLN(10, ("xrdp_sec_fips_encrypt:"));
+ ssl_des3_encrypt(self->encrypt_fips_info, len, data, data);
+ self->encrypt_use_count++;
}
/*****************************************************************************/
static void APP_CC
xrdp_sec_encrypt(struct xrdp_sec *self, char *data, int len)
{
- if (self->crypt_method == CRYPT_METHOD_FIPS)
+ LLOGLN(10, ("xrdp_sec_encrypt:"));
+ if (self->encrypt_use_count == 4096)
{
- ssl_des3_encrypt(self->encrypt_fips_info, len, data, data);
+ xrdp_sec_update(self->encrypt_key, self->encrypt_update_key,
+ self->rc4_key_len);
+ ssl_rc4_set_key(self->encrypt_rc4_info, self->encrypt_key,
+ self->rc4_key_len);
+ self->encrypt_use_count = 0;
}
- else
- {
- if (self->encrypt_use_count == 4096)
- {
- xrdp_sec_update(self->encrypt_key, self->encrypt_update_key,
- self->rc4_key_len);
- ssl_rc4_set_key(self->encrypt_rc4_info, self->encrypt_key,
- self->rc4_key_len);
- self->encrypt_use_count = 0;
- }
- ssl_rc4_crypt(self->encrypt_rc4_info, data, len);
- self->encrypt_use_count++;
- }
+ ssl_rc4_crypt(self->encrypt_rc4_info, data, len);
+ self->encrypt_use_count++;
}
/*****************************************************************************/
@@ -487,6 +493,8 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s)
{
/* must be or error */
DEBUG(("xrdp_sec_process_logon_info: flags wrong, major error"));
+ LLOGLN(0, ("xrdp_sec_process_logon_info: flags wrong, likely decrypt "
+ "not working"));
return 1;
}
@@ -663,8 +671,9 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s)
static int APP_CC
xrdp_sec_send_lic_initial(struct xrdp_sec *self)
{
- struct stream *s = (struct stream *)NULL;
+ struct stream *s;
+ LLOGLN(10, ("xrdp_sec_send_lic_initial:"));
make_stream(s);
init_stream(s, 8192);
@@ -845,53 +854,60 @@ fips_expand_key_bits(const char *in, char *out)
}
}
-/*****************************************************************************/
+/****************************************************************************/
+static void APP_CC
+xrdp_sec_fips_establish_keys(struct xrdp_sec *self)
+{
+ char server_encrypt_key[32];
+ char server_decrypt_key[32];
+ const char *fips_ivec;
+ void *sha1;
+
+ LLOGLN(0, ("xrdp_sec_fips_establish_keys:"));
+
+ sha1 = ssl_sha1_info_create();
+ ssl_sha1_clear(sha1);
+ ssl_sha1_transform(sha1, self->client_random + 16, 16);
+ ssl_sha1_transform(sha1, self->server_random + 16, 16);
+ ssl_sha1_complete(sha1, server_decrypt_key);
+
+ server_decrypt_key[20] = server_decrypt_key[0];
+ fips_expand_key_bits(server_decrypt_key, self->fips_decrypt_key);
+ ssl_sha1_info_delete(sha1);
+
+ sha1 = ssl_sha1_info_create();
+ ssl_sha1_clear(sha1);
+ ssl_sha1_transform(sha1, self->client_random, 16);
+ ssl_sha1_transform(sha1, self->server_random, 16);
+ ssl_sha1_complete(sha1, server_encrypt_key);
+ server_encrypt_key[20] = server_encrypt_key[0];
+ fips_expand_key_bits(server_encrypt_key, self->fips_encrypt_key);
+ ssl_sha1_info_delete(sha1);
+
+ sha1 = ssl_sha1_info_create();
+ ssl_sha1_clear(sha1);
+ ssl_sha1_transform(sha1, server_encrypt_key, 20);
+ ssl_sha1_transform(sha1, server_decrypt_key, 20);
+ ssl_sha1_complete(sha1, self->fips_sign_key);
+ ssl_sha1_info_delete(sha1);
+
+ fips_ivec = (const char *) g_fips_ivec;
+ self->encrypt_fips_info =
+ ssl_des3_encrypt_info_create(self->fips_encrypt_key, fips_ivec);
+ self->decrypt_fips_info =
+ ssl_des3_decrypt_info_create(self->fips_decrypt_key, fips_ivec);
+ self->sign_fips_info = ssl_hmac_info_create();
+}
+
+/****************************************************************************/
static void APP_CC
xrdp_sec_establish_keys(struct xrdp_sec *self)
{
char session_key[48];
char temp_hash[48];
char input[48];
- char client_encrypt_key[32];
- char client_decrypt_key[32];
- const char *fips_ivec;
- void *sha1;
- if (self->crypt_method == CRYPT_METHOD_FIPS)
- {
- LLOGLN(0, ("xrdp_sec_establish_keys: fips"));
- sha1 = ssl_sha1_info_create();
- ssl_sha1_transform(sha1, self->client_random + 16, 16);
- ssl_sha1_transform(sha1, self->server_random + 16, 16);
- ssl_sha1_complete(sha1, client_encrypt_key);
- client_encrypt_key[20] = client_encrypt_key[0];
- fips_expand_key_bits(client_encrypt_key, self->fips_encrypt_key);
- ssl_sha1_info_delete(sha1);
-
- sha1 = ssl_sha1_info_create();
- ssl_sha1_transform(sha1, self->client_random, 16);
- ssl_sha1_transform(sha1, self->server_random, 16);
- ssl_sha1_complete(sha1, client_decrypt_key);
- client_decrypt_key[20] = client_decrypt_key[0];
- fips_expand_key_bits(client_decrypt_key, self->fips_decrypt_key);
- ssl_sha1_info_delete(sha1);
-
- sha1 = ssl_sha1_info_create();
- ssl_sha1_transform(sha1, client_decrypt_key, 20);
- ssl_sha1_transform(sha1, client_encrypt_key, 20);
- ssl_sha1_complete(sha1, self->fips_sign_key);
- ssl_sha1_info_delete(sha1);
-
- fips_ivec = (const char *) g_fips_ivec;
- self->encrypt_fips_info =
- ssl_des3_encrypt_info_create(self->fips_encrypt_key, fips_ivec);
- self->decrypt_fips_info =
- ssl_des3_encrypt_info_create(self->fips_decrypt_key, fips_ivec);
- }
- else
- {
- LLOGLN(0, ("xrdp_sec_establish_keys: not fips"));
- }
+ LLOGLN(0, ("xrdp_sec_establish_keys:"));
g_memcpy(input, self->client_random, 24);
g_memcpy(input + 24, self->server_random, 24);
@@ -930,6 +946,8 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan)
{
int flags;
int len;
+ int ver;
+ int pad;
DEBUG((" in xrdp_sec_recv"));
@@ -954,8 +972,14 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan)
{
return 1;
}
- in_uint8s(s, 12); /* len(2), version(1), pad(1), signature(8) */
- xrdp_sec_decrypt(self, s->p, (int)(s->end - s->p));
+ in_uint16_le(s, len);
+ in_uint8(s, ver);
+ in_uint8(s, pad);
+ LLOGLN(10, ("xrdp_sec_recv: len %d ver %d pad %d", len, ver, pad));
+ in_uint8s(s, 8); /* signature(8) */
+ LLOGLN(10, ("xrdp_sec_recv: data len %d", (int)(s->end - s->p)));
+ xrdp_sec_fips_decrypt(self, s->p, (int)(s->end - s->p));
+ s->end -= pad;
}
else
{
@@ -978,7 +1002,14 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan)
in_uint8a(s, self->client_crypt_random, 64);
xrdp_sec_rsa_op(self->client_random, self->client_crypt_random,
self->pub_mod, self->pri_exp);
- xrdp_sec_establish_keys(self);
+ if (self->crypt_method == CRYPT_METHOD_FIPS)
+ {
+ xrdp_sec_fips_establish_keys(self);
+ }
+ else
+ {
+ xrdp_sec_establish_keys(self);
+ }
*chan = 1; /* just set a non existing channel and exit */
DEBUG((" out xrdp_sec_recv"));
return 0;
@@ -1074,17 +1105,50 @@ xrdp_sec_sign(struct xrdp_sec *self, char *out, int out_len,
}
/*****************************************************************************/
+/* Generate a MAC hash (5.2.3.1), using a combination of SHA1 and MD5 */
+static void APP_CC
+xrdp_sec_fips_sign(struct xrdp_sec *self, char *out, int out_len,
+ char *data, int data_len)
+{
+ char buf[20];
+ char use_count_le[4];
+
+ use_count_le[0] = (self->encrypt_use_count >> 0) & 0xFF;
+ use_count_le[1] = (self->encrypt_use_count >> 8) & 0xFF;
+ use_count_le[2] = (self->encrypt_use_count >> 16) & 0xFF;
+ use_count_le[3] = (self->encrypt_use_count >> 24) & 0xFF;
+ ssl_hmac_sha1_init(self->sign_fips_info, self->fips_sign_key, 20);
+ ssl_hmac_transform(self->sign_fips_info, data, data_len);
+ ssl_hmac_transform(self->sign_fips_info, use_count_le, 4);
+ ssl_hmac_complete(self->sign_fips_info, buf, 20);
+ g_memcpy(out, buf, out_len);
+}
+
+/*****************************************************************************/
/* returns error */
int APP_CC
xrdp_sec_send(struct xrdp_sec *self, struct stream *s, int chan)
{
int datalen;
+ int pad;
+ LLOGLN(10, ("xrdp_sec_send:"));
DEBUG((" in xrdp_sec_send"));
s_pop_layer(s, sec_hdr);
if (self->crypt_level == CRYPT_LEVEL_FIPS)
{
+ LLOGLN(10, ("xrdp_sec_send: fips"));
+ out_uint32_le(s, SEC_ENCRYPT);
+ datalen = (int)((s->end - s->p) - 12);
+ out_uint16_le(s, 16); /* crypto header size */
+ out_uint8(s, 1); /* fips version */
+ pad = (8 - (datalen % 8)) & 7;
+ g_memset(s->end, 0, pad);
+ s->end += pad;
+ out_uint8(s, pad); /* fips pad */
+ xrdp_sec_fips_sign(self, s->p, 8, s->p + 8, datalen);
+ xrdp_sec_fips_encrypt(self, s->p + 8, datalen + pad);
}
else if (self->crypt_level > CRYPT_LEVEL_LOW)
{
@@ -1303,7 +1367,7 @@ xrdp_sec_process_mcs_data_CS_SECURITY(struct xrdp_sec *self, struct stream* s)
found = 1;
}
}
- if ((found == 0) &&
+ if ((found == 0) &&
(self->crypt_method & CRYPT_METHOD_40BIT) &&
(self->crypt_level == CRYPT_LEVEL_CLIENT_COMPATIBLE))
{
@@ -1316,7 +1380,7 @@ xrdp_sec_process_mcs_data_CS_SECURITY(struct xrdp_sec *self, struct stream* s)
found = 1;
}
}
- if ((found == 0) &&
+ if ((found == 0) &&
(self->crypt_method & CRYPT_METHOD_40BIT) &&
(self->crypt_level == CRYPT_LEVEL_LOW))
{
@@ -1521,7 +1585,7 @@ xrdp_sec_process_mcs_data(struct xrdp_sec *self)
s->p = hold_p + size;
}
-
+
if (self->rdp_layer->client_info.max_bpp > 0)
{
if (self->rdp_layer->client_info.bpp >
@@ -1722,8 +1786,8 @@ xrdp_sec_incoming(struct xrdp_sec *self)
char *value = NULL;
char key_file[256];
+ LLOGLN(10, ("xrdp_sec_incoming:"));
g_memset(key_file, 0, sizeof(char) * 256);
-
DEBUG((" in xrdp_sec_incoming"));
g_random(self->server_random, 32);
items = list_create();
@@ -1786,6 +1850,7 @@ xrdp_sec_incoming(struct xrdp_sec *self)
{
return 1;
}
+ LLOGLN(10, ("xrdp_sec_incoming: out"));
return 0;
}