libxrdp: work on fips

This commit is contained in:
Jay Sorg 2014-02-23 20:45:59 -08:00
parent 25ad4d8a36
commit 950ef882f4
3 changed files with 148 additions and 79 deletions

View File

@ -121,6 +121,7 @@ struct xrdp_sec
char fips_sign_key[20];
void* encrypt_fips_info;
void* decrypt_fips_info;
void* sign_fips_info;
};
/* channel */

View File

@ -305,7 +305,10 @@ xrdp_rdp_recv(struct xrdp_rdp *self, struct stream *s, int *code)
}
else
{
g_writeln("Wrong channel Id to be handled by xrdp_channel_process %d", chan);
if (chan != 1)
{
g_writeln("Wrong channel Id to be handled by xrdp_channel_process %d", chan);
}
}
s->next_packet = 0;

View File

@ -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 */
@ -373,52 +374,57 @@ xrdp_sec_update(char *key, char *update_key, int key_len)
return 0;
}
/*****************************************************************************/
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;
@ -1073,18 +1104,51 @@ xrdp_sec_sign(struct xrdp_sec *self, char *out, int out_len,
ssl_md5_info_delete(md5_info);
}
/*****************************************************************************/
/* 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;
}