/// <summary> /// Construct and send CLIENT_LICENSE_INFO /// Meanwhile, generate the two licensing keys: licensing encryption key and MAC salt key. /// </summary> public void SendClientLicenseInformation(KeyExchangeAlg preferredKeyExchangeAlg, uint platformId, byte[] licenseInfo, CLIENT_HARDWARE_ID clientHardwareID) { CLIENT_LICENSE_INFO info = new CLIENT_LICENSE_INFO(); info.PreferredKeyExchangeAlg = preferredKeyExchangeAlg; info.PlatformId = platformId; info.LicenseInfo.blobData = licenseInfo; info.LicenseInfo.wBlobLen = (ushort)licenseInfo.Length; info.LicenseInfo.wBlobType = wBlobType_Values.BB_DATA_BLOB; var random = new Random(); clientRandom = new byte[32]; random.NextBytes(clientRandom); info.ClientRandom = clientRandom; preMasterSecret = new byte[48]; random.NextBytes(preMasterSecret); EncryptionAlgorithm.GenerateLicensingKeys(preMasterSecret, clientRandom, serverRandom, out macSaltKey, out licensingEncryptionKey); if (macSaltKey == null) { throw new Exception("The generated MAC-salt-key should not be NULL!"); } if (licensingEncryptionKey == null) { throw new Exception("The generated LicensingEncryptionKey should not be NULL!"); } info.EncryptedPreMasterSecret.blobData = RdpbcgrUtility.GenerateEncryptedRandom(preMasterSecret, publicExponent, modulus); info.EncryptedPreMasterSecret.wBlobLen = (ushort)info.EncryptedPreMasterSecret.blobData.Length; info.EncryptedPreMasterSecret.wBlobType = wBlobType_Values.BB_RANDOM_BLOB; CLIENT_HARDWARE_ID hardwareID = new CLIENT_HARDWARE_ID(); hardwareID = clientHardwareID; info.EncryptedHWID.wBlobType = wBlobType_Values.BB_ENCRYPTED_DATA_BLOB; var hardwareIDBytes = TypeMarshal.ToBytes <CLIENT_HARDWARE_ID>(hardwareID); info.EncryptedHWID.blobData = RC4(hardwareIDBytes); info.EncryptedHWID.wBlobLen = (ushort)info.EncryptedHWID.blobData.Length; // MACData (16 bytes): An array of 16 bytes containing an MD5 digest (Message Authentication Code (MAC)) // that is generated over the unencrypted Client Hardware Identification structure. info.MACData = EncryptionAlgorithm.GenerateNonFIPSDataSignature(macSaltKey, hardwareIDBytes, 16 * 8); // n is 16 * 8 bits. TS_LICENSE_PDU pdu = ConstructLicensePDU(bMsgType_Values.LICENSE_INFO, new LicensingMessage { ClientLicenseInfo = info }); rdpbcgrClient.SendBytes(pdu.ToBytes()); }
/// <summary> /// Construct and send CLIENT_PLATFORM_CHALLENGE_RESPONSE with encrypted Platform Challeng Response /// </summary> public void SendClientPlatformChallengeResponse(CLIENT_HARDWARE_ID clientHardwareID) { CLIENT_PLATFORM_CHALLENGE_RESPONSE response = new CLIENT_PLATFORM_CHALLENGE_RESPONSE(); PLATFORM_CHALLENGE_RESPONSE_DATA challengeData = new PLATFORM_CHALLENGE_RESPONSE_DATA(); challengeData.pbChallenge = platformChallenge; challengeData.cbChallenge = (ushort)platformChallenge.Length; challengeData.wClientType = 0x0100; challengeData.wVersion = 0x0100; challengeData.wLicenseDetailLevel = 0x0003; response.EncryptedPlatformChallengResponse.wBlobType = wBlobType_Values.BB_ENCRYPTED_DATA_BLOB; var challengeDataBytes = TypeMarshal.ToBytes <PLATFORM_CHALLENGE_RESPONSE_DATA>(challengeData); response.EncryptedPlatformChallengResponse.blobData = RC4(challengeDataBytes); response.EncryptedPlatformChallengResponse.wBlobLen = (ushort)response.EncryptedPlatformChallengResponse.blobData.Length; CLIENT_HARDWARE_ID hardwareID = new CLIENT_HARDWARE_ID(); hardwareID = clientHardwareID; response.EncryptedHWID.wBlobType = wBlobType_Values.BB_ENCRYPTED_DATA_BLOB; var hardwareIDBytes = TypeMarshal.ToBytes <CLIENT_HARDWARE_ID>(hardwareID); response.EncryptedHWID.blobData = RC4(hardwareIDBytes); response.EncryptedHWID.wBlobLen = (ushort)response.EncryptedHWID.blobData.Length; // MACData (16 bytes): An array of 16 bytes containing an MD5 digest (MAC) generated over the Platform Challenge Response Data and decrypted Client Hardware Identification. var data = challengeDataBytes.Concat(hardwareIDBytes).ToArray(); response.MACData = EncryptionAlgorithm.GenerateNonFIPSDataSignature(macSaltKey, data, 16 * 8); // n is 16 * 8 bits. TS_LICENSE_PDU pdu = ConstructLicensePDU(bMsgType_Values.PLATFORM_CHALLENGE_RESPONSE, new LicensingMessage { ClientPlatformChallengeResponse = response }); rdpbcgrClient.SendBytes(pdu.ToBytes()); }
/// <summary> /// Verify if the MACData received from server is valid or not. /// </summary> /// <param name="receivedMAC">The MACData received from Server</param> /// <param name="decryptedData">The decrypted data from Server, which is protected by MACData</param> /// <returns>If the received MAC is valid or not</returns> public bool VerifyServerMAC(byte[] receivedMAC, byte[] decryptedData) { var calculatedMAC = EncryptionAlgorithm.GenerateNonFIPSDataSignature(macSaltKey, decryptedData, 16 * 8); return(Enumerable.SequenceEqual(receivedMAC, calculatedMAC)); }