void ntlm_rc4k(BYTE* key, int length, BYTE* plaintext, BYTE* ciphertext) { WINPR_RC4_CTX rc4; winpr_RC4_Init(&rc4, (void*) key, 16); winpr_RC4_Update(&rc4, length, (void*) plaintext, (void*) ciphertext); winpr_RC4_Final(&rc4); }
void ntlm_init_rc4_seal_states(NTLM_CONTEXT* context) { if (context->server) { context->SendSigningKey = context->ServerSigningKey; context->RecvSigningKey = context->ClientSigningKey; context->SendSealingKey = context->ClientSealingKey; context->RecvSealingKey = context->ServerSealingKey; winpr_RC4_Init(&context->SendRc4Seal, context->ServerSealingKey, 16); winpr_RC4_Init(&context->RecvRc4Seal, context->ClientSealingKey, 16); } else { context->SendSigningKey = context->ClientSigningKey; context->RecvSigningKey = context->ServerSigningKey; context->SendSealingKey = context->ServerSealingKey; context->RecvSealingKey = context->ClientSealingKey; winpr_RC4_Init(&context->SendRc4Seal, context->ClientSealingKey, 16); winpr_RC4_Init(&context->RecvRc4Seal, context->ServerSealingKey, 16); } }
BOOL rdp_server_establish_keys(rdpRdp* rdp, wStream* s) { BYTE* client_random = NULL; BYTE* crypt_client_random = NULL; UINT32 rand_len, key_len; UINT16 channel_id, length, sec_flags; BYTE* mod; BYTE* priv_exp; BOOL ret = FALSE; if (!rdp->settings->UseRdpSecurityLayer) { /* No RDP Security. */ return TRUE; } if (!rdp_read_header(rdp, s, &length, &channel_id)) { WLog_ERR(TAG, "invalid RDP header"); return FALSE; } if (!rdp_read_security_header(s, &sec_flags)) { WLog_ERR(TAG, "invalid security header"); return FALSE; } if ((sec_flags & SEC_EXCHANGE_PKT) == 0) { WLog_ERR(TAG, "missing SEC_EXCHANGE_PKT in security header"); return FALSE; } rdp->do_crypt_license = (sec_flags & SEC_LICENSE_ENCRYPT_SC) != 0 ? TRUE : FALSE; if (Stream_GetRemainingLength(s) < 4) return FALSE; Stream_Read_UINT32(s, rand_len); /* rand_len already includes 8 bytes of padding */ if (Stream_GetRemainingLength(s) < rand_len) return FALSE; key_len = rdp->settings->RdpServerRsaKey->ModulusLength; client_random = malloc(key_len); if (!client_random) return FALSE; if (rand_len != key_len + 8) { WLog_ERR(TAG, "invalid encrypted client random length"); goto end2; } crypt_client_random = calloc(1, rand_len); if (!crypt_client_random) goto end2; Stream_Read(s, crypt_client_random, rand_len); mod = rdp->settings->RdpServerRsaKey->Modulus; priv_exp = rdp->settings->RdpServerRsaKey->PrivateExponent; crypto_rsa_private_decrypt(crypt_client_random, rand_len - 8, key_len, mod, priv_exp, client_random); /* now calculate encrypt / decrypt and update keys */ if (!security_establish_keys(client_random, rdp)) { goto end; } rdp->do_crypt = TRUE; if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS) { rdp->fips_encrypt = crypto_des3_encrypt_init(rdp->fips_encrypt_key, fips_ivec); if (!rdp->fips_encrypt) { WLog_ERR(TAG, "unable to allocate des3 encrypt key"); goto end; } rdp->fips_decrypt = crypto_des3_decrypt_init(rdp->fips_decrypt_key, fips_ivec); if (!rdp->fips_decrypt) { WLog_ERR(TAG, "unable to allocate des3 decrypt key"); goto end; } rdp->fips_hmac = calloc(1, sizeof(WINPR_HMAC_CTX)); if (!rdp->fips_hmac) { WLog_ERR(TAG, "unable to allocate fips hmac"); goto end; } ret = TRUE; goto end; } winpr_RC4_Init(rdp->rc4_decrypt_key, rdp->decrypt_key, rdp->rc4_key_len); winpr_RC4_Init(rdp->rc4_encrypt_key, rdp->encrypt_key, rdp->rc4_key_len); ret = TRUE; end: free(crypt_client_random); end2: free(client_random); return ret; }
static BOOL rdp_client_establish_keys(rdpRdp* rdp) { BYTE* mod; BYTE* exp; wStream* s; UINT32 length; UINT32 key_len; int status = 0; BOOL ret = FALSE; rdpSettings* settings; BYTE* crypt_client_random = NULL; settings = rdp->settings; if (!settings->UseRdpSecurityLayer) { /* no RDP encryption */ return TRUE; } /* encrypt client random */ free(settings->ClientRandom); settings->ClientRandomLength = CLIENT_RANDOM_LENGTH; settings->ClientRandom = malloc(settings->ClientRandomLength); if (!settings->ClientRandom) return FALSE; crypto_nonce(settings->ClientRandom, settings->ClientRandomLength); key_len = settings->RdpServerCertificate->cert_info.ModulusLength; mod = settings->RdpServerCertificate->cert_info.Modulus; exp = settings->RdpServerCertificate->cert_info.exponent; /* * client random must be (bitlen / 8) + 8 - see [MS-RDPBCGR] 5.3.4.1 * for details */ crypt_client_random = calloc(1, key_len + 8); if (!crypt_client_random) return FALSE; crypto_rsa_public_encrypt(settings->ClientRandom, settings->ClientRandomLength, key_len, mod, exp, crypt_client_random); /* send crypt client random to server */ length = RDP_PACKET_HEADER_MAX_LENGTH + RDP_SECURITY_HEADER_LENGTH + 4 + key_len + 8; s = Stream_New(NULL, length); if (!s) { WLog_ERR(TAG, "Stream_New failed!"); goto end; } rdp_write_header(rdp, s, length, MCS_GLOBAL_CHANNEL_ID); rdp_write_security_header(s, SEC_EXCHANGE_PKT | SEC_LICENSE_ENCRYPT_SC); length = key_len + 8; Stream_Write_UINT32(s, length); Stream_Write(s, crypt_client_random, length); Stream_SealLength(s); status = transport_write(rdp->mcs->transport, s); Stream_Free(s, TRUE); if (status < 0) goto end; rdp->do_crypt_license = TRUE; /* now calculate encrypt / decrypt and update keys */ if (!security_establish_keys(settings->ClientRandom, rdp)) goto end; rdp->do_crypt = TRUE; if (settings->SaltedChecksum) rdp->do_secure_checksum = TRUE; if (settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS) { rdp->fips_encrypt = crypto_des3_encrypt_init(rdp->fips_encrypt_key, fips_ivec); if (!rdp->fips_encrypt) { WLog_ERR(TAG, "unable to allocate des3 encrypt key"); goto end; } rdp->fips_decrypt = crypto_des3_decrypt_init(rdp->fips_decrypt_key, fips_ivec); if (!rdp->fips_decrypt) { WLog_ERR(TAG, "unable to allocate des3 decrypt key"); goto end; } rdp->fips_hmac = calloc(1, sizeof(WINPR_HMAC_CTX)); if (!rdp->fips_hmac) { WLog_ERR(TAG, "unable to allocate fips hmac"); goto end; } ret = TRUE; goto end; } winpr_RC4_Init(rdp->rc4_decrypt_key, rdp->decrypt_key, rdp->rc4_key_len); winpr_RC4_Init(rdp->rc4_encrypt_key, rdp->encrypt_key, rdp->rc4_key_len); ret = TRUE; end: free(crypt_client_random); return ret; }