void rdp_write_client_auto_reconnect_cookie(wStream* s, rdpSettings* settings) { CryptoHmac hmac; BYTE nullRandom[32]; BYTE cryptSecurityVerifier[16]; ARC_CS_PRIVATE_PACKET* autoReconnectCookie; autoReconnectCookie = settings->ClientAutoReconnectCookie; /* SecurityVerifier = HMAC(AutoReconnectRandom, ClientRandom) */ hmac = crypto_hmac_new(); ZeroMemory(nullRandom, sizeof(nullRandom)); crypto_hmac_md5_init(hmac, autoReconnectCookie->securityVerifier, 16); if (settings->ClientRandomLength > 0) crypto_hmac_update(hmac, settings->ClientRandom, settings->ClientRandomLength); else crypto_hmac_update(hmac, nullRandom, sizeof(nullRandom)); crypto_hmac_final(hmac, cryptSecurityVerifier, 16); crypto_hmac_free(hmac); Stream_Write_UINT32(s, autoReconnectCookie->cbLen); /* cbLen (4 bytes) */ Stream_Write_UINT32(s, autoReconnectCookie->version); /* version (4 bytes) */ Stream_Write_UINT32(s, autoReconnectCookie->logonId); /* LogonId (4 bytes) */ Stream_Write(s, cryptSecurityVerifier, 16); /* SecurityVerifier */ }
void crypto_hmac(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen, struct scatterlist *sg, unsigned int nsg, u8 *out) { crypto_hmac_init(tfm, key, keylen); crypto_hmac_update(tfm, sg, nsg); crypto_hmac_final(tfm, key, keylen, out); }
BOOL rdp_compute_client_auto_reconnect_cookie(rdpRdp* rdp) { CryptoHmac hmac; BYTE ClientRandom[32]; BYTE AutoReconnectRandom[32]; ARC_SC_PRIVATE_PACKET* serverCookie; ARC_CS_PRIVATE_PACKET* clientCookie; rdpSettings* settings = rdp->settings; serverCookie = settings->ServerAutoReconnectCookie; clientCookie = settings->ClientAutoReconnectCookie; clientCookie->cbLen = 28; clientCookie->version = serverCookie->version; clientCookie->logonId = serverCookie->logonId; ZeroMemory(clientCookie->securityVerifier, 16); ZeroMemory(AutoReconnectRandom, sizeof(AutoReconnectRandom)); CopyMemory(AutoReconnectRandom, serverCookie->arcRandomBits, 16); ZeroMemory(ClientRandom, sizeof(ClientRandom)); if (settings->SelectedProtocol == PROTOCOL_RDP) CopyMemory(ClientRandom, settings->ClientRandom, settings->ClientRandomLength); hmac = crypto_hmac_new(); if (!hmac) return FALSE; /* SecurityVerifier = HMAC_MD5(AutoReconnectRandom, ClientRandom) */ if (!crypto_hmac_md5_init(hmac, AutoReconnectRandom, 16)) return FALSE; crypto_hmac_update(hmac, ClientRandom, 32); crypto_hmac_final(hmac, clientCookie->securityVerifier, 16); crypto_hmac_free(hmac); return TRUE; }
void rdp_write_extended_info_packet(wStream* s, rdpSettings* settings) { int clientAddressFamily; WCHAR* clientAddress = NULL; int cbClientAddress; WCHAR* clientDir = NULL; int cbClientDir; int cbAutoReconnectLen; clientAddressFamily = settings->IPv6Enabled ? ADDRESS_FAMILY_INET6 : ADDRESS_FAMILY_INET; cbClientAddress = ConvertToUnicode(CP_UTF8, 0, settings->ClientAddress, -1, &clientAddress, 0) * 2; cbClientDir = ConvertToUnicode(CP_UTF8, 0, settings->ClientDir, -1, &clientDir, 0) * 2; cbAutoReconnectLen = (int) settings->ServerAutoReconnectCookie->cbLen; Stream_Write_UINT16(s, clientAddressFamily); /* clientAddressFamily */ Stream_Write_UINT16(s, cbClientAddress + 2); /* cbClientAddress */ if (cbClientAddress > 0) Stream_Write(s, clientAddress, cbClientAddress); /* clientAddress */ Stream_Write_UINT16(s, 0); Stream_Write_UINT16(s, cbClientDir + 2); /* cbClientDir */ if (cbClientDir > 0) Stream_Write(s, clientDir, cbClientDir); /* clientDir */ Stream_Write_UINT16(s, 0); rdp_write_client_time_zone(s, settings); /* clientTimeZone */ Stream_Write_UINT32(s, 0); /* clientSessionId, should be set to 0 */ freerdp_performance_flags_make(settings); Stream_Write_UINT32(s, settings->PerformanceFlags); /* performanceFlags */ Stream_Write_UINT16(s, cbAutoReconnectLen); /* cbAutoReconnectLen */ if (cbAutoReconnectLen > 0) { CryptoHmac hmac; ARC_SC_PRIVATE_PACKET* serverCookie; ARC_CS_PRIVATE_PACKET* clientCookie; WLog_DBG(TAG, "Sending auto reconnect"); serverCookie = settings->ServerAutoReconnectCookie; clientCookie = settings->ClientAutoReconnectCookie; clientCookie->cbLen = serverCookie->cbLen; clientCookie->version = serverCookie->version; clientCookie->logonId = serverCookie->logonId; hmac = crypto_hmac_new(); if (!hmac) { WLog_ERR(TAG, "unable to allocate hmac"); goto out_free; } crypto_hmac_md5_init(hmac, serverCookie->arcRandomBits, 16); if (settings->SelectedProtocol == PROTOCOL_RDP) { crypto_hmac_update(hmac, (BYTE*) (settings->ClientRandom), 32); } else { /* Anthony Tong's version had 16 zeroes here; I'm not sure why. * I do know that 16 did not reconnect correctly vs Win2008RDVH, * and 32 did. */ const BYTE zeros[32] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }; crypto_hmac_update(hmac, zeros, 32); } crypto_hmac_final(hmac, clientCookie->securityVerifier, 16); rdp_write_client_auto_reconnect_cookie(s, settings); /* autoReconnectCookie */ /* mark as used */ settings->ServerAutoReconnectCookie->cbLen = 0; crypto_hmac_free(hmac); } /* reserved1 (2 bytes) */ /* reserved2 (2 bytes) */ out_free: free(clientAddress); free(clientDir); }