Blame libfreerdp/core/license.c

Packit Service fa4841
/**
Packit Service fa4841
 * FreeRDP: A Remote Desktop Protocol Implementation
Packit Service fa4841
 * RDP Licensing
Packit Service fa4841
 *
Packit Service fa4841
 * Copyright 2011-2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit Service fa4841
 * Copyright 2014 Norbert Federa <norbert.federa@thincast.com>
Packit Service fa4841
 * Copyright 2018 David Fort <contact@hardening-consulting.com>
Packit Service fa4841
 *
Packit Service fa4841
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit Service fa4841
 * you may not use this file except in compliance with the License.
Packit Service fa4841
 * You may obtain a copy of the License at
Packit Service fa4841
 *
Packit Service fa4841
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit Service fa4841
 *
Packit Service fa4841
 * Unless required by applicable law or agreed to in writing, software
Packit Service fa4841
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit Service fa4841
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit Service fa4841
 * See the License for the specific language governing permissions and
Packit Service fa4841
 * limitations under the License.
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
#ifdef HAVE_CONFIG_H
Packit Service fa4841
#include "config.h"
Packit Service fa4841
#endif
Packit Service fa4841
Packit Service fa4841
#include <winpr/crt.h>
Packit Service fa4841
#include <winpr/crypto.h>
Packit Service fa4841
#include <winpr/shell.h>
Packit Service fa4841
#include <winpr/path.h>
Packit Service fa4841
Packit Service fa4841
#include <freerdp/log.h>
Packit Service fa4841
Packit Service fa4841
#include "redirection.h"
Packit Service fa4841
#include "certificate.h"
Packit Service fa4841
Packit Service fa4841
#include "license.h"
Packit Service fa4841
Packit Service fa4841
#define TAG FREERDP_TAG("core.license")
Packit Service fa4841
Packit Service fa4841
#if 0
Packit Service fa4841
#define LICENSE_NULL_CLIENT_RANDOM 1
Packit Service fa4841
#define LICENSE_NULL_PREMASTER_SECRET 1
Packit Service fa4841
#endif
Packit Service fa4841
Packit Service fa4841
static wStream* license_send_stream_init(rdpLicense* license);
Packit Service fa4841
Packit Service fa4841
static void license_generate_randoms(rdpLicense* license);
Packit Service fa4841
static BOOL license_generate_keys(rdpLicense* license);
Packit Service fa4841
static BOOL license_generate_hwid(rdpLicense* license);
Packit Service fa4841
static BOOL license_encrypt_premaster_secret(rdpLicense* license);
Packit Service fa4841
Packit Service fa4841
static LICENSE_PRODUCT_INFO* license_new_product_info(void);
Packit Service fa4841
static void license_free_product_info(LICENSE_PRODUCT_INFO* productInfo);
Packit Service fa4841
static BOOL license_read_product_info(wStream* s, LICENSE_PRODUCT_INFO* productInfo);
Packit Service fa4841
Packit Service fa4841
static LICENSE_BLOB* license_new_binary_blob(UINT16 type);
Packit Service fa4841
static void license_free_binary_blob(LICENSE_BLOB* blob);
Packit Service fa4841
static BOOL license_read_binary_blob(wStream* s, LICENSE_BLOB* blob);
Packit Service fa4841
static BOOL license_write_binary_blob(wStream* s, const LICENSE_BLOB* blob);
Packit Service fa4841
Packit Service fa4841
static SCOPE_LIST* license_new_scope_list(void);
Packit Service fa4841
static void license_free_scope_list(SCOPE_LIST* scopeList);
Packit Service fa4841
static BOOL license_read_scope_list(wStream* s, SCOPE_LIST* scopeList);
Packit Service fa4841
Packit Service fa4841
static BOOL license_read_license_request_packet(rdpLicense* license, wStream* s);
Packit Service fa4841
static BOOL license_read_platform_challenge_packet(rdpLicense* license, wStream* s);
Packit Service fa4841
static BOOL license_read_new_or_upgrade_license_packet(rdpLicense* license, wStream* s);
Packit Service fa4841
static BOOL license_read_error_alert_packet(rdpLicense* license, wStream* s);
Packit Service fa4841
Packit Service fa4841
static BOOL license_write_new_license_request_packet(rdpLicense* license, wStream* s);
Packit Service fa4841
static BOOL license_answer_license_request(rdpLicense* license);
Packit Service fa4841
Packit Service fa4841
static BOOL license_write_platform_challenge_response_packet(rdpLicense* license, wStream* s,
Packit Service fa4841
                                                             const BYTE* mac_data);
Packit Service fa4841
static BOOL license_send_platform_challenge_response_packet(rdpLicense* license);
Packit Service fa4841
static BOOL license_send_client_info(rdpLicense* license, const LICENSE_BLOB* calBlob,
Packit Service fa4841
                                     BYTE* signature);
Packit Service fa4841
Packit Service fa4841
#define PLATFORMID (CLIENT_OS_ID_WINNT_POST_52 | CLIENT_IMAGE_ID_MICROSOFT)
Packit Service fa4841
Packit Service fa4841
#ifdef WITH_DEBUG_LICENSE
Packit Service fa4841
Packit Service fa4841
static const char* const LICENSE_MESSAGE_STRINGS[] = { "",
Packit Service fa4841
	                                                   "License Request",
Packit Service fa4841
	                                                   "Platform Challenge",
Packit Service fa4841
	                                                   "New License",
Packit Service fa4841
	                                                   "Upgrade License",
Packit Service fa4841
	                                                   "",
Packit Service fa4841
	                                                   "",
Packit Service fa4841
	                                                   "",
Packit Service fa4841
	                                                   "",
Packit Service fa4841
	                                                   "",
Packit Service fa4841
	                                                   "",
Packit Service fa4841
	                                                   "",
Packit Service fa4841
	                                                   "",
Packit Service fa4841
	                                                   "",
Packit Service fa4841
	                                                   "",
Packit Service fa4841
	                                                   "",
Packit Service fa4841
	                                                   "",
Packit Service fa4841
	                                                   "",
Packit Service fa4841
	                                                   "License Info",
Packit Service fa4841
	                                                   "New License Request",
Packit Service fa4841
	                                                   "",
Packit Service fa4841
	                                                   "Platform Challenge Response",
Packit Service fa4841
	                                                   "",
Packit Service fa4841
	                                                   "",
Packit Service fa4841
	                                                   "",
Packit Service fa4841
	                                                   "",
Packit Service fa4841
	                                                   "",
Packit Service fa4841
	                                                   "",
Packit Service fa4841
	                                                   "",
Packit Service fa4841
	                                                   "",
Packit Service fa4841
	                                                   "",
Packit Service fa4841
	                                                   "Error Alert" };
Packit Service fa4841
Packit Service fa4841
static const char* const error_codes[] = { "ERR_UNKNOWN",
Packit Service fa4841
	                                       "ERR_INVALID_SERVER_CERTIFICATE",
Packit Service fa4841
	                                       "ERR_NO_LICENSE",
Packit Service fa4841
	                                       "ERR_INVALID_MAC",
Packit Service fa4841
	                                       "ERR_INVALID_SCOPE",
Packit Service fa4841
	                                       "ERR_UNKNOWN",
Packit Service fa4841
	                                       "ERR_NO_LICENSE_SERVER",
Packit Service fa4841
	                                       "STATUS_VALID_CLIENT",
Packit Service fa4841
	                                       "ERR_INVALID_CLIENT",
Packit Service fa4841
	                                       "ERR_UNKNOWN",
Packit Service fa4841
	                                       "ERR_UNKNOWN",
Packit Service fa4841
	                                       "ERR_INVALID_PRODUCT_ID",
Packit Service fa4841
	                                       "ERR_INVALID_MESSAGE_LENGTH" };
Packit Service fa4841
Packit Service fa4841
static const char* const state_transitions[] = { "ST_UNKNOWN", "ST_TOTAL_ABORT", "ST_NO_TRANSITION",
Packit Service fa4841
	                                             "ST_RESET_PHASE_TO_START",
Packit Service fa4841
	                                             "ST_RESEND_LAST_MESSAGE" };
Packit Service fa4841
Packit Service fa4841
static void license_print_product_info(const LICENSE_PRODUCT_INFO* productInfo)
Packit Service fa4841
{
Packit Service fa4841
	char* CompanyName = NULL;
Packit Service fa4841
	char* ProductId = NULL;
Packit Service fa4841
	ConvertFromUnicode(CP_UTF8, 0, (WCHAR*)productInfo->pbCompanyName,
Packit Service fa4841
	                   productInfo->cbCompanyName / 2, &CompanyName, 0, NULL, NULL);
Packit Service fa4841
	ConvertFromUnicode(CP_UTF8, 0, (WCHAR*)productInfo->pbProductId, productInfo->cbProductId / 2,
Packit Service fa4841
	                   &ProductId, 0, NULL, NULL);
Packit Service fa4841
	WLog_INFO(TAG, "ProductInfo:");
Packit Service fa4841
	WLog_INFO(TAG, "\tdwVersion: 0x%08" PRIX32 "", productInfo->dwVersion);
Packit Service fa4841
	WLog_INFO(TAG, "\tCompanyName: %s", CompanyName);
Packit Service fa4841
	WLog_INFO(TAG, "\tProductId: %s", ProductId);
Packit Service fa4841
	free(CompanyName);
Packit Service fa4841
	free(ProductId);
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static void license_print_scope_list(const SCOPE_LIST* scopeList)
Packit Service fa4841
{
Packit Service fa4841
	UINT32 index;
Packit Service fa4841
	const LICENSE_BLOB* scope;
Packit Service fa4841
	WLog_INFO(TAG, "ScopeList (%" PRIu32 "):", scopeList->count);
Packit Service fa4841
Packit Service fa4841
	for (index = 0; index < scopeList->count; index++)
Packit Service fa4841
	{
Packit Service fa4841
		scope = &scopeList->array[index];
Packit Service fa4841
		WLog_INFO(TAG, "\t%s", (const char*)scope->data);
Packit Service fa4841
	}
Packit Service fa4841
}
Packit Service fa4841
#endif
Packit Service fa4841
Packit Service fa4841
static const char licenseStore[] = "licenses";
Packit Service fa4841
Packit Service fa4841
static BOOL computeCalHash(const char* hostname, char* hashStr)
Packit Service fa4841
{
Packit Service fa4841
	WINPR_DIGEST_CTX* sha1 = NULL;
Packit Service fa4841
	BOOL ret = FALSE;
Packit Service fa4841
	BYTE hash[20];
Packit Service fa4841
	size_t i;
Packit Service fa4841
Packit Service fa4841
	if (!(sha1 = winpr_Digest_New()))
Packit Service fa4841
		goto out;
Packit Service fa4841
	if (!winpr_Digest_Init(sha1, WINPR_MD_SHA1))
Packit Service fa4841
		goto out;
Packit Service fa4841
	if (!winpr_Digest_Update(sha1, (const BYTE*)hostname, strlen(hostname)))
Packit Service fa4841
		goto out;
Packit Service fa4841
	if (!winpr_Digest_Final(sha1, hash, sizeof(hash)))
Packit Service fa4841
		goto out;
Packit Service fa4841
Packit Service fa4841
	for (i = 0; i < sizeof(hash); i++, hashStr += 2)
Packit Service fa4841
		sprintf_s(hashStr, 3, "%.2x", hash[i]);
Packit Service fa4841
Packit Service fa4841
	ret = TRUE;
Packit Service fa4841
out:
Packit Service fa4841
	winpr_Digest_Free(sha1);
Packit Service fa4841
	return ret;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static BOOL saveCal(rdpSettings* settings, const BYTE* data, int length, char* hostname)
Packit Service fa4841
{
Packit Service fa4841
	char hash[41];
Packit Service fa4841
	FILE* fp;
Packit Service fa4841
	char* licenseStorePath = NULL;
Packit Service fa4841
	char filename[MAX_PATH], filenameNew[MAX_PATH];
Packit Service fa4841
	char *filepath = NULL, *filepathNew = NULL;
Packit Service fa4841
	size_t written;
Packit Service fa4841
	BOOL ret = FALSE;
Packit Service fa4841
Packit Service fa4841
	if (!PathFileExistsA(settings->ConfigPath))
Packit Service fa4841
	{
Packit Service fa4841
		if (!PathMakePathA(settings->ConfigPath, 0))
Packit Service fa4841
		{
Packit Service fa4841
			WLog_ERR(TAG, "error creating directory '%s'", settings->ConfigPath);
Packit Service fa4841
			goto out;
Packit Service fa4841
		}
Packit Service fa4841
		WLog_INFO(TAG, "creating directory %s", settings->ConfigPath);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (!(licenseStorePath = GetCombinedPath(settings->ConfigPath, licenseStore)))
Packit Service fa4841
		goto out;
Packit Service fa4841
Packit Service fa4841
	if (!PathFileExistsA(licenseStorePath))
Packit Service fa4841
	{
Packit Service fa4841
		if (!PathMakePathA(licenseStorePath, 0))
Packit Service fa4841
		{
Packit Service fa4841
			WLog_ERR(TAG, "error creating directory '%s'", licenseStorePath);
Packit Service fa4841
			goto out;
Packit Service fa4841
		}
Packit Service fa4841
		WLog_INFO(TAG, "creating directory %s", licenseStorePath);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (!computeCalHash(hostname, hash))
Packit Service fa4841
		goto out;
Packit Service fa4841
	sprintf_s(filename, sizeof(filename) - 1, "%s.cal", hash);
Packit Service fa4841
	sprintf_s(filenameNew, sizeof(filenameNew) - 1, "%s.cal.new", hash);
Packit Service fa4841
Packit Service fa4841
	if (!(filepath = GetCombinedPath(licenseStorePath, filename)))
Packit Service fa4841
		goto out;
Packit Service fa4841
Packit Service fa4841
	if (!(filepathNew = GetCombinedPath(licenseStorePath, filenameNew)))
Packit Service fa4841
		goto out;
Packit Service fa4841
Packit Service fa4841
	fp = fopen(filepathNew, "wb");
Packit Service fa4841
	if (!fp)
Packit Service fa4841
		goto out;
Packit Service fa4841
Packit Service fa4841
	written = fwrite(data, length, 1, fp);
Packit Service fa4841
	fclose(fp);
Packit Service fa4841
Packit Service fa4841
	if (written != 1)
Packit Service fa4841
	{
Packit Service fa4841
		DeleteFile(filepathNew);
Packit Service fa4841
		goto out;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	ret = MoveFileEx(filepathNew, filepath, MOVEFILE_REPLACE_EXISTING);
Packit Service fa4841
Packit Service fa4841
out:
Packit Service fa4841
	free(filepathNew);
Packit Service fa4841
	free(filepath);
Packit Service fa4841
	free(licenseStorePath);
Packit Service fa4841
	return ret;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static BYTE* loadCalFile(rdpSettings* settings, const char* hostname, int* dataLen)
Packit Service fa4841
{
Packit Service fa4841
	char *licenseStorePath = NULL, *calPath = NULL;
Packit Service fa4841
	char calFilename[MAX_PATH];
Packit Service fa4841
	char hash[41];
Packit Service fa4841
	int length, status;
Packit Service fa4841
	FILE* fp;
Packit Service fa4841
	BYTE* ret = NULL;
Packit Service fa4841
Packit Service fa4841
	if (!computeCalHash(hostname, hash))
Packit Service fa4841
	{
Packit Service fa4841
		WLog_ERR(TAG, "loadCalFile: unable to compute hostname hash");
Packit Service fa4841
		return NULL;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	sprintf_s(calFilename, sizeof(calFilename) - 1, "%s.cal", hash);
Packit Service fa4841
Packit Service fa4841
	if (!(licenseStorePath = GetCombinedPath(settings->ConfigPath, licenseStore)))
Packit Service fa4841
		return NULL;
Packit Service fa4841
Packit Service fa4841
	if (!(calPath = GetCombinedPath(licenseStorePath, calFilename)))
Packit Service fa4841
		goto error_path;
Packit Service fa4841
Packit Service fa4841
	fp = fopen(calPath, "rb");
Packit Service fa4841
	if (!fp)
Packit Service fa4841
		goto error_open;
Packit Service fa4841
Packit Service fa4841
	_fseeki64(fp, 0, SEEK_END);
Packit Service fa4841
	length = _ftelli64(fp);
Packit Service fa4841
	_fseeki64(fp, 0, SEEK_SET);
Packit Service fa4841
Packit Service fa4841
	ret = (BYTE*)malloc(length);
Packit Service fa4841
	if (!ret)
Packit Service fa4841
		goto error_malloc;
Packit Service fa4841
Packit Service fa4841
	status = fread(ret, length, 1, fp);
Packit Service fa4841
	if (status <= 0)
Packit Service fa4841
		goto error_read;
Packit Service fa4841
Packit Service fa4841
	*dataLen = length;
Packit Service fa4841
Packit Service fa4841
	fclose(fp);
Packit Service fa4841
	free(calPath);
Packit Service fa4841
	free(licenseStorePath);
Packit Service fa4841
	return ret;
Packit Service fa4841
Packit Service fa4841
error_read:
Packit Service fa4841
	free(ret);
Packit Service fa4841
error_malloc:
Packit Service fa4841
	fclose(fp);
Packit Service fa4841
error_open:
Packit Service fa4841
	free(calPath);
Packit Service fa4841
error_path:
Packit Service fa4841
	free(licenseStorePath);
Packit Service fa4841
	return NULL;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Read a licensing preamble.\n
Packit Service fa4841
 * @msdn{cc240480}
Packit Service fa4841
 * @param s stream
Packit Service fa4841
 * @param bMsgType license message type
Packit Service fa4841
 * @param flags message flags
Packit Service fa4841
 * @param wMsgSize message size
Packit Service fa4841
 * @return if the operation completed successfully
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
static BOOL license_read_preamble(wStream* s, BYTE* bMsgType, BYTE* flags, UINT16* wMsgSize)
Packit Service fa4841
{
Packit Service fa4841
	/* preamble (4 bytes) */
Packit Service fa4841
	if (Stream_GetRemainingLength(s) < 4)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	Stream_Read_UINT8(s, *bMsgType);  /* bMsgType (1 byte) */
Packit Service fa4841
	Stream_Read_UINT8(s, *flags);     /* flags (1 byte) */
Packit Service fa4841
	Stream_Read_UINT16(s, *wMsgSize); /* wMsgSize (2 bytes) */
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Write a licensing preamble.\n
Packit Service fa4841
 * @msdn{cc240480}
Packit Service fa4841
 * @param s stream
Packit Service fa4841
 * @param bMsgType license message type
Packit Service fa4841
 * @param flags message flags
Packit Service fa4841
 * @param wMsgSize message size
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
static BOOL license_write_preamble(wStream* s, BYTE bMsgType, BYTE flags, UINT16 wMsgSize)
Packit Service fa4841
{
Packit Service fa4841
	if (!Stream_EnsureRemainingCapacity(s, 4))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	/* preamble (4 bytes) */
Packit Service fa4841
	Stream_Write_UINT8(s, bMsgType);  /* bMsgType (1 byte) */
Packit Service fa4841
	Stream_Write_UINT8(s, flags);     /* flags (1 byte) */
Packit Service fa4841
	Stream_Write_UINT16(s, wMsgSize); /* wMsgSize (2 bytes) */
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Initialize a license packet stream.\n
Packit Service fa4841
 * @param license license module
Packit Service fa4841
 * @return stream
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
wStream* license_send_stream_init(rdpLicense* license)
Packit Service fa4841
{
Packit Service fa4841
	wStream* s;
Packit Service fa4841
	BOOL do_crypt = license->rdp->do_crypt;
Packit Service fa4841
Packit Service fa4841
	license->rdp->sec_flags = SEC_LICENSE_PKT;
Packit Service fa4841
Packit Service fa4841
	/**
Packit Service fa4841
	 * Encryption of licensing packets is optional even if the rdp security
Packit Service fa4841
	 * layer is used. If the peer has not indicated that it is capable of
Packit Service fa4841
	 * processing encrypted licensing packets (rdp->do_crypt_license) we turn
Packit Service fa4841
	 * off encryption (via rdp->do_crypt) before initializing the rdp stream
Packit Service fa4841
	 * and reenable it afterwards.
Packit Service fa4841
	 */
Packit Service fa4841
Packit Service fa4841
	if (do_crypt)
Packit Service fa4841
	{
Packit Service fa4841
		license->rdp->sec_flags |= SEC_LICENSE_ENCRYPT_CS;
Packit Service fa4841
		license->rdp->do_crypt = license->rdp->do_crypt_license;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	s = rdp_send_stream_init(license->rdp);
Packit Service fa4841
	if (!s)
Packit Service fa4841
		return NULL;
Packit Service fa4841
Packit Service fa4841
	license->rdp->do_crypt = do_crypt;
Packit Service fa4841
	license->PacketHeaderLength = Stream_GetPosition(s);
Packit Service fa4841
	if (!Stream_SafeSeek(s, LICENSE_PREAMBLE_LENGTH))
Packit Service fa4841
		goto fail;
Packit Service fa4841
	return s;
Packit Service fa4841
Packit Service fa4841
fail:
Packit Service fa4841
	Stream_Release(s);
Packit Service fa4841
	return NULL;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Send an RDP licensing packet.\n
Packit Service fa4841
 * @msdn{cc240479}
Packit Service fa4841
 * @param license license module
Packit Service fa4841
 * @param s stream
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
static BOOL license_send(rdpLicense* license, wStream* s, BYTE type)
Packit Service fa4841
{
Packit Service fa4841
	size_t length;
Packit Service fa4841
	BYTE flags;
Packit Service fa4841
	UINT16 wMsgSize;
Packit Service fa4841
	rdpRdp* rdp = license->rdp;
Packit Service fa4841
	BOOL ret;
Packit Service fa4841
Packit Service fa4841
	DEBUG_LICENSE("Sending %s Packet", LICENSE_MESSAGE_STRINGS[type & 0x1F]);
Packit Service fa4841
	length = Stream_GetPosition(s);
Packit Service fa4841
	wMsgSize = length - license->PacketHeaderLength;
Packit Service fa4841
	Stream_SetPosition(s, license->PacketHeaderLength);
Packit Service fa4841
	flags = PREAMBLE_VERSION_3_0;
Packit Service fa4841
Packit Service fa4841
	/**
Packit Service fa4841
	 * Using EXTENDED_ERROR_MSG_SUPPORTED here would cause mstsc to crash when
Packit Service fa4841
	 * running in server mode! This flag seems to be incorrectly documented.
Packit Service fa4841
	 */
Packit Service fa4841
Packit Service fa4841
	if (!rdp->settings->ServerMode)
Packit Service fa4841
		flags |= EXTENDED_ERROR_MSG_SUPPORTED;
Packit Service fa4841
Packit Service fa4841
	if (!license_write_preamble(s, type, flags, wMsgSize))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
#ifdef WITH_DEBUG_LICENSE
Packit Service fa4841
	WLog_DBG(TAG, "Sending %s Packet, length %" PRIu16 "", LICENSE_MESSAGE_STRINGS[type & 0x1F],
Packit Service fa4841
	         wMsgSize);
Packit Service fa4841
	winpr_HexDump(TAG, WLOG_DEBUG, Stream_Pointer(s) - LICENSE_PREAMBLE_LENGTH, wMsgSize);
Packit Service fa4841
#endif
Packit Service fa4841
	Stream_SetPosition(s, length);
Packit Service fa4841
	ret = rdp_send(rdp, s, MCS_GLOBAL_CHANNEL_ID);
Packit Service fa4841
	rdp->sec_flags = 0;
Packit Service fa4841
	return ret;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Receive an RDP licensing packet.\n
Packit Service fa4841
 * @msdn{cc240479}
Packit Service fa4841
 * @param license license module
Packit Service fa4841
 * @param s stream
Packit Service fa4841
 * @return if the operation completed successfully
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
int license_recv(rdpLicense* license, wStream* s)
Packit Service fa4841
{
Packit Service fa4841
	BYTE flags;
Packit Service fa4841
	BYTE bMsgType;
Packit Service fa4841
	UINT16 wMsgSize;
Packit Service fa4841
	UINT16 length;
Packit Service fa4841
	UINT16 channelId;
Packit Service fa4841
	UINT16 securityFlags = 0;
Packit Service fa4841
Packit Service fa4841
	if (!rdp_read_header(license->rdp, s, &length, &channelId))
Packit Service fa4841
	{
Packit Service fa4841
		WLog_ERR(TAG, "Incorrect RDP header.");
Packit Service fa4841
		return -1;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (!rdp_read_security_header(s, &securityFlags, &length))
Packit Service fa4841
		return -1;
Packit Service fa4841
Packit Service fa4841
	if (securityFlags & SEC_ENCRYPT)
Packit Service fa4841
	{
Packit Service fa4841
		if (!rdp_decrypt(license->rdp, s, &length, securityFlags))
Packit Service fa4841
		{
Packit Service fa4841
			WLog_ERR(TAG, "rdp_decrypt failed");
Packit Service fa4841
			return -1;
Packit Service fa4841
		}
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (!(securityFlags & SEC_LICENSE_PKT))
Packit Service fa4841
	{
Packit Service fa4841
		int status;
Packit Service fa4841
Packit Service fa4841
		if (!(securityFlags & SEC_ENCRYPT))
Packit Service fa4841
			Stream_Rewind(s, RDP_SECURITY_HEADER_LENGTH);
Packit Service fa4841
Packit Service fa4841
		status = rdp_recv_out_of_sequence_pdu(license->rdp, s);
Packit Service fa4841
		if (status < 0)
Packit Service fa4841
		{
Packit Service fa4841
			WLog_ERR(TAG, "unexpected license packet.");
Packit Service fa4841
			return status;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		return 0;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (!license_read_preamble(s, &bMsgType, &flags, &wMsgSize)) /* preamble (4 bytes) */
Packit Service fa4841
		return -1;
Packit Service fa4841
Packit Service fa4841
	DEBUG_LICENSE("Receiving %s Packet", LICENSE_MESSAGE_STRINGS[bMsgType & 0x1F]);
Packit Service fa4841
Packit Service fa4841
	switch (bMsgType)
Packit Service fa4841
	{
Packit Service fa4841
		case LICENSE_REQUEST:
Packit Service fa4841
			if (!license_read_license_request_packet(license, s))
Packit Service fa4841
				return -1;
Packit Service fa4841
Packit Service fa4841
			if (!license_answer_license_request(license))
Packit Service fa4841
				return -1;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case PLATFORM_CHALLENGE:
Packit Service fa4841
			if (!license_read_platform_challenge_packet(license, s))
Packit Service fa4841
				return -1;
Packit Service fa4841
Packit Service fa4841
			if (!license_send_platform_challenge_response_packet(license))
Packit Service fa4841
				return -1;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case NEW_LICENSE:
Packit Service fa4841
		case UPGRADE_LICENSE:
Packit Service fa4841
			if (!license_read_new_or_upgrade_license_packet(license, s))
Packit Service fa4841
				return -1;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case ERROR_ALERT:
Packit Service fa4841
			if (!license_read_error_alert_packet(license, s))
Packit Service fa4841
				return -1;
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		default:
Packit Service fa4841
			WLog_ERR(TAG, "invalid bMsgType:%" PRIu8 "", bMsgType);
Packit Service fa4841
			return -1;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (!tpkt_ensure_stream_consumed(s, length))
Packit Service fa4841
		return -1;
Packit Service fa4841
	return 0;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
void license_generate_randoms(rdpLicense* license)
Packit Service fa4841
{
Packit Service fa4841
#ifdef LICENSE_NULL_CLIENT_RANDOM
Packit Service fa4841
	ZeroMemory(license->ClientRandom, CLIENT_RANDOM_LENGTH); /* ClientRandom */
Packit Service fa4841
#else
Packit Service fa4841
	winpr_RAND(license->ClientRandom, CLIENT_RANDOM_LENGTH);       /* ClientRandom */
Packit Service fa4841
#endif
Packit Service fa4841
Packit Service fa4841
#ifdef LICENSE_NULL_PREMASTER_SECRET
Packit Service fa4841
	ZeroMemory(license->PremasterSecret, PREMASTER_SECRET_LENGTH); /* PremasterSecret */
Packit Service fa4841
#else
Packit Service fa4841
	winpr_RAND(license->PremasterSecret, PREMASTER_SECRET_LENGTH); /* PremasterSecret */
Packit Service fa4841
#endif
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Generate License Cryptographic Keys.
Packit Service fa4841
 * @param license license module
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
static BOOL license_generate_keys(rdpLicense* license)
Packit Service fa4841
{
Packit Service fa4841
	BOOL ret;
Packit Service fa4841
Packit Service fa4841
	if (
Packit Service fa4841
	    /* MasterSecret */
Packit Service fa4841
	    !security_master_secret(license->PremasterSecret, license->ClientRandom,
Packit Service fa4841
	                            license->ServerRandom, license->MasterSecret) ||
Packit Service fa4841
	    /* SessionKeyBlob */
Packit Service fa4841
	    !security_session_key_blob(license->MasterSecret, license->ClientRandom,
Packit Service fa4841
	                               license->ServerRandom, license->SessionKeyBlob))
Packit Service fa4841
	{
Packit Service fa4841
		return FALSE;
Packit Service fa4841
	}
Packit Service fa4841
	security_mac_salt_key(license->SessionKeyBlob, license->ClientRandom, license->ServerRandom,
Packit Service fa4841
	                      license->MacSaltKey); /* MacSaltKey */
Packit Service fa4841
	ret = security_licensing_encryption_key(
Packit Service fa4841
	    license->SessionKeyBlob, license->ClientRandom, license->ServerRandom,
Packit Service fa4841
	    license->LicensingEncryptionKey); /* LicensingEncryptionKey */
Packit Service fa4841
#ifdef WITH_DEBUG_LICENSE
Packit Service fa4841
	WLog_DBG(TAG, "ClientRandom:");
Packit Service fa4841
	winpr_HexDump(TAG, WLOG_DEBUG, license->ClientRandom, CLIENT_RANDOM_LENGTH);
Packit Service fa4841
	WLog_DBG(TAG, "ServerRandom:");
Packit Service fa4841
	winpr_HexDump(TAG, WLOG_DEBUG, license->ServerRandom, SERVER_RANDOM_LENGTH);
Packit Service fa4841
	WLog_DBG(TAG, "PremasterSecret:");
Packit Service fa4841
	winpr_HexDump(TAG, WLOG_DEBUG, license->PremasterSecret, PREMASTER_SECRET_LENGTH);
Packit Service fa4841
	WLog_DBG(TAG, "MasterSecret:");
Packit Service fa4841
	winpr_HexDump(TAG, WLOG_DEBUG, license->MasterSecret, MASTER_SECRET_LENGTH);
Packit Service fa4841
	WLog_DBG(TAG, "SessionKeyBlob:");
Packit Service fa4841
	winpr_HexDump(TAG, WLOG_DEBUG, license->SessionKeyBlob, SESSION_KEY_BLOB_LENGTH);
Packit Service fa4841
	WLog_DBG(TAG, "MacSaltKey:");
Packit Service fa4841
	winpr_HexDump(TAG, WLOG_DEBUG, license->MacSaltKey, MAC_SALT_KEY_LENGTH);
Packit Service fa4841
	WLog_DBG(TAG, "LicensingEncryptionKey:");
Packit Service fa4841
	winpr_HexDump(TAG, WLOG_DEBUG, license->LicensingEncryptionKey,
Packit Service fa4841
	              LICENSING_ENCRYPTION_KEY_LENGTH);
Packit Service fa4841
#endif
Packit Service fa4841
	return ret;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Generate Unique Hardware Identifier (CLIENT_HARDWARE_ID).\n
Packit Service fa4841
 * @param license license module
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
BOOL license_generate_hwid(rdpLicense* license)
Packit Service fa4841
{
Packit Service fa4841
	const BYTE* hashTarget;
Packit Service fa4841
	size_t targetLen;
Packit Service fa4841
	BYTE macAddress[6];
Packit Service fa4841
Packit Service fa4841
	ZeroMemory(license->HardwareId, HWID_LENGTH);
Packit Service fa4841
Packit Service fa4841
	if (license->rdp->settings->OldLicenseBehaviour)
Packit Service fa4841
	{
Packit Service fa4841
		ZeroMemory(macAddress, sizeof(macAddress));
Packit Service fa4841
		hashTarget = macAddress;
Packit Service fa4841
		targetLen = sizeof(macAddress);
Packit Service fa4841
	}
Packit Service fa4841
	else
Packit Service fa4841
	{
Packit Service fa4841
		wStream s;
Packit Service fa4841
		const char* hostname = license->rdp->settings->ClientHostname;
Packit Service fa4841
		Stream_StaticInit(&s, license->HardwareId, 4);
Packit Service fa4841
		Stream_Write_UINT32(&s, PLATFORMID);
Packit Service fa4841
		Stream_Free(&s, TRUE);
Packit Service fa4841
Packit Service fa4841
		hashTarget = (const BYTE*)hostname;
Packit Service fa4841
		targetLen = strlen(hostname);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	/* Allow FIPS override for use of MD5 here, really this does not have to be MD5 as we are just
Packit Service fa4841
	 * taking a MD5 hash of the 6 bytes of 0's(macAddress) */
Packit Service fa4841
	/* and filling in the Data1-Data4 fields of the CLIENT_HARDWARE_ID structure(from MS-RDPELE
Packit Service fa4841
	 * section 2.2.2.3.1). This is for RDP licensing packets */
Packit Service fa4841
	/* which will already be encrypted under FIPS, so the use of MD5 here is not for sensitive data
Packit Service fa4841
	 * protection. */
Packit Service fa4841
	return winpr_Digest_Allow_FIPS(WINPR_MD_MD5, hashTarget, targetLen,
Packit Service fa4841
	                               &license->HardwareId[HWID_PLATFORM_ID_LENGTH],
Packit Service fa4841
	                               WINPR_MD5_DIGEST_LENGTH);
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static BOOL license_get_server_rsa_public_key(rdpLicense* license)
Packit Service fa4841
{
Packit Service fa4841
	BYTE* Exponent;
Packit Service fa4841
	BYTE* Modulus;
Packit Service fa4841
	int ModulusLength;
Packit Service fa4841
	rdpSettings* settings = license->rdp->settings;
Packit Service fa4841
Packit Service fa4841
	if (license->ServerCertificate->length < 1)
Packit Service fa4841
	{
Packit Service fa4841
		if (!certificate_read_server_certificate(license->certificate, settings->ServerCertificate,
Packit Service fa4841
		                                         settings->ServerCertificateLength))
Packit Service fa4841
			return FALSE;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	Exponent = license->certificate->cert_info.exponent;
Packit Service fa4841
	Modulus = license->certificate->cert_info.Modulus;
Packit Service fa4841
	ModulusLength = license->certificate->cert_info.ModulusLength;
Packit Service fa4841
	CopyMemory(license->Exponent, Exponent, 4);
Packit Service fa4841
	license->ModulusLength = ModulusLength;
Packit Service fa4841
	license->Modulus = (BYTE*)malloc(ModulusLength);
Packit Service fa4841
	if (!license->Modulus)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
	CopyMemory(license->Modulus, Modulus, ModulusLength);
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
BOOL license_encrypt_premaster_secret(rdpLicense* license)
Packit Service fa4841
{
Packit Service fa4841
	BYTE* EncryptedPremasterSecret;
Packit Service fa4841
Packit Service fa4841
	if (!license_get_server_rsa_public_key(license))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
#ifdef WITH_DEBUG_LICENSE
Packit Service fa4841
	WLog_DBG(TAG, "Modulus (%" PRIu32 " bits):", license->ModulusLength * 8);
Packit Service fa4841
	winpr_HexDump(TAG, WLOG_DEBUG, license->Modulus, license->ModulusLength);
Packit Service fa4841
	WLog_DBG(TAG, "Exponent:");
Packit Service fa4841
	winpr_HexDump(TAG, WLOG_DEBUG, license->Exponent, 4);
Packit Service fa4841
#endif
Packit Service fa4841
Packit Service fa4841
	EncryptedPremasterSecret = (BYTE*)calloc(1, license->ModulusLength);
Packit Service fa4841
	if (!EncryptedPremasterSecret)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	license->EncryptedPremasterSecret->type = BB_RANDOM_BLOB;
Packit Service fa4841
	license->EncryptedPremasterSecret->length = PREMASTER_SECRET_LENGTH;
Packit Service fa4841
#ifndef LICENSE_NULL_PREMASTER_SECRET
Packit Service fa4841
	license->EncryptedPremasterSecret->length = crypto_rsa_public_encrypt(
Packit Service fa4841
	    license->PremasterSecret, PREMASTER_SECRET_LENGTH, license->ModulusLength, license->Modulus,
Packit Service fa4841
	    license->Exponent, EncryptedPremasterSecret);
Packit Service fa4841
#endif
Packit Service fa4841
	license->EncryptedPremasterSecret->data = EncryptedPremasterSecret;
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static BOOL license_rc4_with_licenseKey(const rdpLicense* license, const BYTE* input, size_t len,
Packit Service fa4841
                                        LICENSE_BLOB* target)
Packit Service fa4841
{
Packit Service fa4841
	WINPR_RC4_CTX* rc4;
Packit Service fa4841
	BYTE* buffer = NULL;
Packit Service fa4841
Packit Service fa4841
	rc4 =
Packit Service fa4841
	    winpr_RC4_New_Allow_FIPS(license->LicensingEncryptionKey, LICENSING_ENCRYPTION_KEY_LENGTH);
Packit Service fa4841
	if (!rc4)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	buffer = (BYTE*)realloc(target->data, len);
Packit Service fa4841
	if (!buffer)
Packit Service fa4841
		goto error_buffer;
Packit Service fa4841
Packit Service fa4841
	target->data = buffer;
Packit Service fa4841
	target->length = len;
Packit Service fa4841
Packit Service fa4841
	if (!winpr_RC4_Update(rc4, len, input, buffer))
Packit Service fa4841
		goto error_buffer;
Packit Service fa4841
Packit Service fa4841
	winpr_RC4_Free(rc4);
Packit Service fa4841
	return TRUE;
Packit Service fa4841
Packit Service fa4841
error_buffer:
Packit Service fa4841
	winpr_RC4_Free(rc4);
Packit Service fa4841
	return FALSE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Encrypt the input using the license key and MAC the input for a signature
Packit Service fa4841
 *
Packit Service fa4841
 * @param license rdpLicense to get keys and salt from
Packit Service fa4841
 * @param input the input data to encrypt and MAC
Packit Service fa4841
 * @param len size of input
Packit Service fa4841
 * @param target a target LICENSE_BLOB where the encrypted input will be stored
Packit Service fa4841
 * @param mac the signature buffer (16 bytes)
Packit Service fa4841
 * @return if the operation completed successfully
Packit Service fa4841
 */
Packit Service fa4841
static BOOL license_encrypt_and_MAC(rdpLicense* license, const BYTE* input, size_t len,
Packit Service fa4841
                                    LICENSE_BLOB* target, BYTE* mac)
Packit Service fa4841
{
Packit Service fa4841
	return license_rc4_with_licenseKey(license, input, len, target) &&
Packit Service fa4841
	       security_mac_data(license->MacSaltKey, input, len, mac);
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Decrypt the input using the license key and check the MAC
Packit Service fa4841
 *
Packit Service fa4841
 * @param license rdpLicense to get keys and salt from
Packit Service fa4841
 * @param input the input data to decrypt and MAC
Packit Service fa4841
 * @param len size of input
Packit Service fa4841
 * @param target a target LICENSE_BLOB where the decrypted input will be stored
Packit Service fa4841
 * @param mac the signature buffer (16 bytes)
Packit Service fa4841
 * @return if the operation completed successfully
Packit Service fa4841
 */
Packit Service fa4841
static BOOL license_decrypt_and_check_MAC(rdpLicense* license, const BYTE* input, size_t len,
Packit Service fa4841
                                          LICENSE_BLOB* target, const BYTE* packetMac)
Packit Service fa4841
{
Packit Service fa4841
	BYTE macData[16];
Packit Service fa4841
Packit Service fa4841
	return license_rc4_with_licenseKey(license, input, len, target) &&
Packit Service fa4841
	       security_mac_data(license->MacSaltKey, target->data, len, macData) &&
Packit Service fa4841
	       (memcmp(packetMac, macData, sizeof(macData)) == 0);
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Read Product Information (PRODUCT_INFO).\n
Packit Service fa4841
 * @msdn{cc241915}
Packit Service fa4841
 * @param s stream
Packit Service fa4841
 * @param productInfo product information
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
BOOL license_read_product_info(wStream* s, LICENSE_PRODUCT_INFO* productInfo)
Packit Service fa4841
{
Packit Service fa4841
	if (Stream_GetRemainingLength(s) < 8)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	Stream_Read_UINT32(s, productInfo->dwVersion);     /* dwVersion (4 bytes) */
Packit Service fa4841
	Stream_Read_UINT32(s, productInfo->cbCompanyName); /* cbCompanyName (4 bytes) */
Packit Service fa4841
Packit Service fa4841
	/* Name must be >0, but there is no upper limit defined, use UINT32_MAX */
Packit Service fa4841
	if ((productInfo->cbCompanyName < 2) || (productInfo->cbCompanyName % 2 != 0))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	if (Stream_GetRemainingLength(s) < productInfo->cbCompanyName)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	productInfo->pbProductId = NULL;
Packit Service fa4841
	productInfo->pbCompanyName = (BYTE*)malloc(productInfo->cbCompanyName);
Packit Service fa4841
	if (!productInfo->pbCompanyName)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
	Stream_Read(s, productInfo->pbCompanyName, productInfo->cbCompanyName);
Packit Service fa4841
Packit Service fa4841
	if (Stream_GetRemainingLength(s) < 4)
Packit Service fa4841
		goto out_fail;
Packit Service fa4841
Packit Service fa4841
	Stream_Read_UINT32(s, productInfo->cbProductId); /* cbProductId (4 bytes) */
Packit Service fa4841
Packit Service fa4841
	if ((productInfo->cbProductId < 2) || (productInfo->cbProductId % 2 != 0))
Packit Service fa4841
		goto out_fail;
Packit Service fa4841
Packit Service fa4841
	if (Stream_GetRemainingLength(s) < productInfo->cbProductId)
Packit Service fa4841
		goto out_fail;
Packit Service fa4841
Packit Service fa4841
	productInfo->pbProductId = (BYTE*)malloc(productInfo->cbProductId);
Packit Service fa4841
	if (!productInfo->pbProductId)
Packit Service fa4841
		goto out_fail;
Packit Service fa4841
	Stream_Read(s, productInfo->pbProductId, productInfo->cbProductId);
Packit Service fa4841
	return TRUE;
Packit Service fa4841
Packit Service fa4841
out_fail:
Packit Service fa4841
	free(productInfo->pbCompanyName);
Packit Service fa4841
	free(productInfo->pbProductId);
Packit Service fa4841
	productInfo->pbCompanyName = NULL;
Packit Service fa4841
	productInfo->pbProductId = NULL;
Packit Service fa4841
	return FALSE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Allocate New Product Information (LICENSE_PRODUCT_INFO).\n
Packit Service fa4841
 * @msdn{cc241915}
Packit Service fa4841
 * @return new product information
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
LICENSE_PRODUCT_INFO* license_new_product_info()
Packit Service fa4841
{
Packit Service fa4841
	LICENSE_PRODUCT_INFO* productInfo;
Packit Service fa4841
	productInfo = (LICENSE_PRODUCT_INFO*)malloc(sizeof(LICENSE_PRODUCT_INFO));
Packit Service fa4841
	if (!productInfo)
Packit Service fa4841
		return NULL;
Packit Service fa4841
	productInfo->dwVersion = 0;
Packit Service fa4841
	productInfo->cbCompanyName = 0;
Packit Service fa4841
	productInfo->pbCompanyName = NULL;
Packit Service fa4841
	productInfo->cbProductId = 0;
Packit Service fa4841
	productInfo->pbProductId = NULL;
Packit Service fa4841
	return productInfo;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Free Product Information (LICENSE_PRODUCT_INFO).\n
Packit Service fa4841
 * @msdn{cc241915}
Packit Service fa4841
 * @param productInfo product information
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
void license_free_product_info(LICENSE_PRODUCT_INFO* productInfo)
Packit Service fa4841
{
Packit Service fa4841
	if (productInfo)
Packit Service fa4841
	{
Packit Service fa4841
		free(productInfo->pbCompanyName);
Packit Service fa4841
		free(productInfo->pbProductId);
Packit Service fa4841
		free(productInfo);
Packit Service fa4841
	}
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Read License Binary Blob (LICENSE_BINARY_BLOB).\n
Packit Service fa4841
 * @msdn{cc240481}
Packit Service fa4841
 * @param s stream
Packit Service fa4841
 * @param blob license binary blob
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
BOOL license_read_binary_blob(wStream* s, LICENSE_BLOB* blob)
Packit Service fa4841
{
Packit Service fa4841
	UINT16 wBlobType;
Packit Service fa4841
Packit Service fa4841
	if (Stream_GetRemainingLength(s) < 4)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	Stream_Read_UINT16(s, wBlobType);    /* wBlobType (2 bytes) */
Packit Service fa4841
	Stream_Read_UINT16(s, blob->length); /* wBlobLen (2 bytes) */
Packit Service fa4841
Packit Service fa4841
	if (Stream_GetRemainingLength(s) < blob->length)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	/*
Packit Service fa4841
	 * Server can choose to not send data by setting length to 0.
Packit Service fa4841
	 * If so, it may not bother to set the type, so shortcut the warning
Packit Service fa4841
	 */
Packit Service fa4841
	if ((blob->type != BB_ANY_BLOB) && (blob->length == 0))
Packit Service fa4841
		return TRUE;
Packit Service fa4841
Packit Service fa4841
	if ((blob->type != wBlobType) && (blob->type != BB_ANY_BLOB))
Packit Service fa4841
	{
Packit Service fa4841
		WLog_ERR(TAG,
Packit Service fa4841
		         "license binary blob type (0x%" PRIx16 ") does not match expected type (0x%" PRIx16
Packit Service fa4841
		         ").",
Packit Service fa4841
		         wBlobType, blob->type);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	blob->type = wBlobType;
Packit Service fa4841
	blob->data = (BYTE*)malloc(blob->length);
Packit Service fa4841
	if (!blob->data)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
	Stream_Read(s, blob->data, blob->length); /* blobData */
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Write License Binary Blob (LICENSE_BINARY_BLOB).\n
Packit Service fa4841
 * @msdn{cc240481}
Packit Service fa4841
 * @param s stream
Packit Service fa4841
 * @param blob license binary blob
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
BOOL license_write_binary_blob(wStream* s, const LICENSE_BLOB* blob)
Packit Service fa4841
{
Packit Service fa4841
	if (!Stream_EnsureRemainingCapacity(s, blob->length + 4))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	Stream_Write_UINT16(s, blob->type);   /* wBlobType (2 bytes) */
Packit Service fa4841
	Stream_Write_UINT16(s, blob->length); /* wBlobLen (2 bytes) */
Packit Service fa4841
Packit Service fa4841
	if (blob->length > 0)
Packit Service fa4841
		Stream_Write(s, blob->data, blob->length); /* blobData */
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static BOOL license_write_encrypted_premaster_secret_blob(wStream* s, const LICENSE_BLOB* blob,
Packit Service fa4841
                                                          UINT32 ModulusLength)
Packit Service fa4841
{
Packit Service fa4841
	UINT32 length;
Packit Service fa4841
	length = ModulusLength + 8;
Packit Service fa4841
Packit Service fa4841
	if (blob->length > ModulusLength)
Packit Service fa4841
	{
Packit Service fa4841
		WLog_ERR(TAG, "license_write_encrypted_premaster_secret_blob: invalid blob");
Packit Service fa4841
		return FALSE;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (!Stream_EnsureRemainingCapacity(s, length + 4))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
	Stream_Write_UINT16(s, blob->type); /* wBlobType (2 bytes) */
Packit Service fa4841
	Stream_Write_UINT16(s, length);     /* wBlobLen (2 bytes) */
Packit Service fa4841
Packit Service fa4841
	if (blob->length > 0)
Packit Service fa4841
		Stream_Write(s, blob->data, blob->length); /* blobData */
Packit Service fa4841
Packit Service fa4841
	Stream_Zero(s, length - blob->length);
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Allocate New License Binary Blob (LICENSE_BINARY_BLOB).\n
Packit Service fa4841
 * @msdn{cc240481}
Packit Service fa4841
 * @return new license binary blob
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
LICENSE_BLOB* license_new_binary_blob(UINT16 type)
Packit Service fa4841
{
Packit Service fa4841
	LICENSE_BLOB* blob;
Packit Service fa4841
	blob = (LICENSE_BLOB*)calloc(1, sizeof(LICENSE_BLOB));
Packit Service fa4841
	if (blob)
Packit Service fa4841
		blob->type = type;
Packit Service fa4841
	return blob;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Free License Binary Blob (LICENSE_BINARY_BLOB).\n
Packit Service fa4841
 * @msdn{cc240481}
Packit Service fa4841
 * @param blob license binary blob
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
void license_free_binary_blob(LICENSE_BLOB* blob)
Packit Service fa4841
{
Packit Service fa4841
	if (blob)
Packit Service fa4841
	{
Packit Service fa4841
		free(blob->data);
Packit Service fa4841
		free(blob);
Packit Service fa4841
	}
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Read License Scope List (SCOPE_LIST).\n
Packit Service fa4841
 * @msdn{cc241916}
Packit Service fa4841
 * @param s stream
Packit Service fa4841
 * @param scopeList scope list
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
BOOL license_read_scope_list(wStream* s, SCOPE_LIST* scopeList)
Packit Service fa4841
{
Packit Service fa4841
	UINT32 i;
Packit Service fa4841
	UINT32 scopeCount;
Packit Service fa4841
Packit Service fa4841
	if (Stream_GetRemainingLength(s) < 4)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	Stream_Read_UINT32(s, scopeCount); /* ScopeCount (4 bytes) */
Packit Service fa4841
Packit Service fa4841
	if (scopeCount > Stream_GetRemainingLength(s) / 4) /* every blob is at least 4 bytes */
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	scopeList->count = scopeCount;
Packit Service fa4841
	scopeList->array = (LICENSE_BLOB*)calloc(scopeCount, sizeof(LICENSE_BLOB));
Packit Service fa4841
	if (!scopeList->array)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	/* ScopeArray */
Packit Service fa4841
	for (i = 0; i < scopeCount; i++)
Packit Service fa4841
	{
Packit Service fa4841
		scopeList->array[i].type = BB_SCOPE_BLOB;
Packit Service fa4841
Packit Service fa4841
		if (!license_read_binary_blob(s, &scopeList->array[i]))
Packit Service fa4841
			return FALSE;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Allocate New License Scope List (SCOPE_LIST).\n
Packit Service fa4841
 * @msdn{cc241916}
Packit Service fa4841
 * @return new scope list
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
SCOPE_LIST* license_new_scope_list()
Packit Service fa4841
{
Packit Service fa4841
	return (SCOPE_LIST*)calloc(1, sizeof(SCOPE_LIST));
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Free License Scope List (SCOPE_LIST).\n
Packit Service fa4841
 * @msdn{cc241916}
Packit Service fa4841
 * @param scopeList scope list
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
void license_free_scope_list(SCOPE_LIST* scopeList)
Packit Service fa4841
{
Packit Service fa4841
	UINT32 i;
Packit Service fa4841
Packit Service fa4841
	if (!scopeList)
Packit Service fa4841
		return;
Packit Service fa4841
Packit Service fa4841
	/*
Packit Service fa4841
	 * We must NOT call license_free_binary_blob() on each scopelist->array[i] element,
Packit Service fa4841
	 * because scopelist->array was allocated at once, by a single call to malloc. The elements
Packit Service fa4841
	 * it contains cannot be deallocated separately then.
Packit Service fa4841
	 * To make things clean, we must deallocate each scopelist->array[].data,
Packit Service fa4841
	 * and finish by deallocating scopelist->array with a single call to free().
Packit Service fa4841
	 */
Packit Service fa4841
	for (i = 0; i < scopeList->count; i++)
Packit Service fa4841
	{
Packit Service fa4841
		free(scopeList->array[i].data);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	free(scopeList->array);
Packit Service fa4841
	free(scopeList);
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
BOOL license_send_client_info(rdpLicense* license, const LICENSE_BLOB* calBlob, BYTE* signature)
Packit Service fa4841
{
Packit Service fa4841
	wStream* s;
Packit Service fa4841
Packit Service fa4841
	/* Client License Information: */
Packit Service fa4841
	UINT32 PlatformId = PLATFORMID;
Packit Service fa4841
	UINT32 PreferredKeyExchangeAlg = KEY_EXCHANGE_ALG_RSA;
Packit Service fa4841
Packit Service fa4841
	s = license_send_stream_init(license);
Packit Service fa4841
	if (!s)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	Stream_Write_UINT32(s, PreferredKeyExchangeAlg); /* PreferredKeyExchangeAlg (4 bytes) */
Packit Service fa4841
	Stream_Write_UINT32(s, PlatformId);              /* PlatformId (4 bytes) */
Packit Service fa4841
Packit Service fa4841
	/* ClientRandom (32 bytes) */
Packit Service fa4841
	Stream_Write(s, license->ClientRandom, CLIENT_RANDOM_LENGTH);
Packit Service fa4841
Packit Service fa4841
	/* Licensing Binary Blob with EncryptedPreMasterSecret: */
Packit Service fa4841
	if (!license_write_encrypted_premaster_secret_blob(s, license->EncryptedPremasterSecret,
Packit Service fa4841
	                                                   license->ModulusLength))
Packit Service fa4841
		goto error;
Packit Service fa4841
Packit Service fa4841
	/* Licensing Binary Blob with LicenseInfo: */
Packit Service fa4841
	if (!license_write_binary_blob(s, calBlob))
Packit Service fa4841
		goto error;
Packit Service fa4841
Packit Service fa4841
	/* Licensing Binary Blob with EncryptedHWID */
Packit Service fa4841
	if (!license_write_binary_blob(s, license->EncryptedHardwareId))
Packit Service fa4841
		goto error;
Packit Service fa4841
Packit Service fa4841
	/* MACData */
Packit Service fa4841
	Stream_Write(s, signature, LICENSING_ENCRYPTION_KEY_LENGTH);
Packit Service fa4841
Packit Service fa4841
	return license_send(license, s, LICENSE_INFO);
Packit Service fa4841
Packit Service fa4841
error:
Packit Service fa4841
	Stream_Release(s);
Packit Service fa4841
	return FALSE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Read a LICENSE_REQUEST packet.\n
Packit Service fa4841
 * @msdn{cc241914}
Packit Service fa4841
 * @param license license module
Packit Service fa4841
 * @param s stream
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
BOOL license_read_license_request_packet(rdpLicense* license, wStream* s)
Packit Service fa4841
{
Packit Service fa4841
	/* ServerRandom (32 bytes) */
Packit Service fa4841
	if (Stream_GetRemainingLength(s) < 32)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	Stream_Read(s, license->ServerRandom, 32);
Packit Service fa4841
Packit Service fa4841
	/* ProductInfo */
Packit Service fa4841
	if (!license_read_product_info(s, license->ProductInfo))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	/* KeyExchangeList */
Packit Service fa4841
	if (!license_read_binary_blob(s, license->KeyExchangeList))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	/* ServerCertificate */
Packit Service fa4841
	if (!license_read_binary_blob(s, license->ServerCertificate))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	/* ScopeList */
Packit Service fa4841
	if (!license_read_scope_list(s, license->ScopeList))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	/* Parse Server Certificate */
Packit Service fa4841
	if (!certificate_read_server_certificate(license->certificate, license->ServerCertificate->data,
Packit Service fa4841
	                                         license->ServerCertificate->length))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	if (!license_generate_keys(license) || !license_generate_hwid(license) ||
Packit Service fa4841
	    !license_encrypt_premaster_secret(license))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
#ifdef WITH_DEBUG_LICENSE
Packit Service fa4841
	WLog_DBG(TAG, "ServerRandom:");
Packit Service fa4841
	winpr_HexDump(TAG, WLOG_DEBUG, license->ServerRandom, 32);
Packit Service fa4841
	license_print_product_info(license->ProductInfo);
Packit Service fa4841
	license_print_scope_list(license->ScopeList);
Packit Service fa4841
#endif
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/*
Packit Service fa4841
 * Read a PLATFORM_CHALLENGE packet.\n
Packit Service fa4841
 * @msdn{cc241921}
Packit Service fa4841
 * @param license license module
Packit Service fa4841
 * @param s stream
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
BOOL license_read_platform_challenge_packet(rdpLicense* license, wStream* s)
Packit Service fa4841
{
Packit Service fa4841
	BYTE macData[16];
Packit Service fa4841
	UINT32 ConnectFlags = 0;
Packit Service fa4841
Packit Service fa4841
	DEBUG_LICENSE("Receiving Platform Challenge Packet");
Packit Service fa4841
Packit Service fa4841
	if (Stream_GetRemainingLength(s) < 4)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	Stream_Read_UINT32(s, ConnectFlags); /* ConnectFlags, Reserved (4 bytes) */
Packit Service fa4841
Packit Service fa4841
	/* EncryptedPlatformChallenge */
Packit Service fa4841
	license->EncryptedPlatformChallenge->type = BB_ANY_BLOB;
Packit Service fa4841
	if (!license_read_binary_blob(s, license->EncryptedPlatformChallenge))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
	license->EncryptedPlatformChallenge->type = BB_ENCRYPTED_DATA_BLOB;
Packit Service fa4841
Packit Service fa4841
	/* MACData (16 bytes) */
Packit Service fa4841
	if (Stream_GetRemainingLength(s) < 16)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	Stream_Read(s, macData, 16);
Packit Service fa4841
	if (!license_decrypt_and_check_MAC(license, license->EncryptedPlatformChallenge->data,
Packit Service fa4841
	                                   license->EncryptedPlatformChallenge->length,
Packit Service fa4841
	                                   license->PlatformChallenge, macData))
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
#ifdef WITH_DEBUG_LICENSE
Packit Service fa4841
	WLog_DBG(TAG, "ConnectFlags: 0x%08" PRIX32 "", ConnectFlags);
Packit Service fa4841
	WLog_DBG(TAG, "EncryptedPlatformChallenge:");
Packit Service fa4841
	winpr_HexDump(TAG, WLOG_DEBUG, license->EncryptedPlatformChallenge->data,
Packit Service fa4841
	              license->EncryptedPlatformChallenge->length);
Packit Service fa4841
	WLog_DBG(TAG, "PlatformChallenge:");
Packit Service fa4841
	winpr_HexDump(TAG, WLOG_DEBUG, license->PlatformChallenge->data,
Packit Service fa4841
	              license->PlatformChallenge->length);
Packit Service fa4841
	WLog_DBG(TAG, "MacData:");
Packit Service fa4841
	winpr_HexDump(TAG, WLOG_DEBUG, macData, 16);
Packit Service fa4841
#endif
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static BOOL license_read_encrypted_blob(const rdpLicense* license, wStream* s, LICENSE_BLOB* target)
Packit Service fa4841
{
Packit Service fa4841
	UINT16 wBlobType, wBlobLen;
Packit Service fa4841
	BYTE* encryptedData;
Packit Service fa4841
Packit Service fa4841
	if (Stream_GetRemainingLength(s) < 4)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	Stream_Read_UINT16(s, wBlobType);
Packit Service fa4841
	if (wBlobType != BB_ENCRYPTED_DATA_BLOB)
Packit Service fa4841
	{
Packit Service fa4841
		WLog_DBG(
Packit Service fa4841
		    TAG,
Packit Service fa4841
		    "expecting BB_ENCRYPTED_DATA_BLOB blob, probably a windows 2003 server, continuing...");
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	Stream_Read_UINT16(s, wBlobLen);
Packit Service fa4841
Packit Service fa4841
	if (Stream_GetRemainingLength(s) < wBlobLen)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	encryptedData = Stream_Pointer(s);
Packit Service fa4841
	Stream_Seek(s, wBlobLen);
Packit Service fa4841
	return license_rc4_with_licenseKey(license, encryptedData, wBlobLen, target);
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Read a NEW_LICENSE packet.\n
Packit Service fa4841
 * @msdn{cc241926}
Packit Service fa4841
 * @param license license module
Packit Service fa4841
 * @param s stream
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
BOOL license_read_new_or_upgrade_license_packet(rdpLicense* license, wStream* s)
Packit Service fa4841
{
Packit Service fa4841
	UINT32 os_major;
Packit Service fa4841
	UINT32 os_minor;
Packit Service fa4841
	UINT32 cbScope, cbCompanyName, cbProductId, cbLicenseInfo;
Packit Service fa4841
	wStream* licenseStream = NULL;
Packit Service fa4841
	BOOL ret = FALSE;
Packit Service fa4841
	BYTE computedMac[16];
Packit Service fa4841
	LICENSE_BLOB* calBlob;
Packit Service fa4841
Packit Service fa4841
	DEBUG_LICENSE("Receiving Server New/Upgrade License Packet");
Packit Service fa4841
Packit Service fa4841
	calBlob = license_new_binary_blob(BB_DATA_BLOB);
Packit Service fa4841
	if (!calBlob)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	/* EncryptedLicenseInfo */
Packit Service fa4841
	if (!license_read_encrypted_blob(license, s, calBlob))
Packit Service fa4841
		goto out_free_blob;
Packit Service fa4841
Packit Service fa4841
	/* compute MAC and check it */
Packit Service fa4841
	if (Stream_GetRemainingLength(s) < 16)
Packit Service fa4841
		goto out_free_blob;
Packit Service fa4841
Packit Service fa4841
	if (!security_mac_data(license->MacSaltKey, calBlob->data, calBlob->length, computedMac))
Packit Service fa4841
		goto out_free_blob;
Packit Service fa4841
Packit Service fa4841
	if (memcmp(computedMac, Stream_Pointer(s), sizeof(computedMac)) != 0)
Packit Service fa4841
	{
Packit Service fa4841
		WLog_ERR(TAG, "new or upgrade license MAC mismatch");
Packit Service fa4841
		goto out_free_blob;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (!Stream_SafeSeek(s, 16))
Packit Service fa4841
		goto out_free_blob;
Packit Service fa4841
Packit Service fa4841
	licenseStream = Stream_New(calBlob->data, calBlob->length);
Packit Service fa4841
	if (!licenseStream)
Packit Service fa4841
		goto out_free_blob;
Packit Service fa4841
Packit Service fa4841
	if (Stream_GetRemainingLength(licenseStream) < 8)
Packit Service fa4841
		goto out_free_stream;
Packit Service fa4841
Packit Service fa4841
	Stream_Read_UINT16(licenseStream, os_minor);
Packit Service fa4841
	Stream_Read_UINT16(licenseStream, os_major);
Packit Service fa4841
Packit Service fa4841
	/* Scope */
Packit Service fa4841
	Stream_Read_UINT32(licenseStream, cbScope);
Packit Service fa4841
	if (Stream_GetRemainingLength(licenseStream) < cbScope)
Packit Service fa4841
		goto out_free_stream;
Packit Service fa4841
#ifdef WITH_DEBUG_LICENSE
Packit Service fa4841
	WLog_DBG(TAG, "Scope:");
Packit Service fa4841
	winpr_HexDump(TAG, WLOG_DEBUG, Stream_Pointer(licenseStream), cbScope);
Packit Service fa4841
#endif
Packit Service fa4841
	Stream_Seek(licenseStream, cbScope);
Packit Service fa4841
Packit Service fa4841
	/* CompanyName */
Packit Service fa4841
	if (Stream_GetRemainingLength(licenseStream) < 4)
Packit Service fa4841
		goto out_free_stream;
Packit Service fa4841
	Stream_Read_UINT32(licenseStream, cbCompanyName);
Packit Service fa4841
	if (Stream_GetRemainingLength(licenseStream) < cbCompanyName)
Packit Service fa4841
		goto out_free_stream;
Packit Service fa4841
#ifdef WITH_DEBUG_LICENSE
Packit Service fa4841
	WLog_DBG(TAG, "Company name:");
Packit Service fa4841
	winpr_HexDump(TAG, WLOG_DEBUG, Stream_Pointer(licenseStream), cbCompanyName);
Packit Service fa4841
#endif
Packit Service fa4841
	Stream_Seek(licenseStream, cbCompanyName);
Packit Service fa4841
Packit Service fa4841
	/* productId */
Packit Service fa4841
	if (Stream_GetRemainingLength(licenseStream) < 4)
Packit Service fa4841
		goto out_free_stream;
Packit Service fa4841
	Stream_Read_UINT32(licenseStream, cbProductId);
Packit Service fa4841
	if (Stream_GetRemainingLength(licenseStream) < cbProductId)
Packit Service fa4841
		goto out_free_stream;
Packit Service fa4841
#ifdef WITH_DEBUG_LICENSE
Packit Service fa4841
	WLog_DBG(TAG, "Product id:");
Packit Service fa4841
	winpr_HexDump(TAG, WLOG_DEBUG, Stream_Pointer(licenseStream), cbProductId);
Packit Service fa4841
#endif
Packit Service fa4841
	Stream_Seek(licenseStream, cbProductId);
Packit Service fa4841
Packit Service fa4841
	/* licenseInfo */
Packit Service fa4841
	if (Stream_GetRemainingLength(licenseStream) < 4)
Packit Service fa4841
		goto out_free_stream;
Packit Service fa4841
	Stream_Read_UINT32(licenseStream, cbLicenseInfo);
Packit Service fa4841
	if (Stream_GetRemainingLength(licenseStream) < cbLicenseInfo)
Packit Service fa4841
		goto out_free_stream;
Packit Service fa4841
Packit Service fa4841
	license->state = LICENSE_STATE_COMPLETED;
Packit Service fa4841
Packit Service fa4841
	ret = TRUE;
Packit Service fa4841
	if (!license->rdp->settings->OldLicenseBehaviour)
Packit Service fa4841
		ret = saveCal(license->rdp->settings, Stream_Pointer(licenseStream), cbLicenseInfo,
Packit Service fa4841
		              license->rdp->settings->ClientHostname);
Packit Service fa4841
Packit Service fa4841
out_free_stream:
Packit Service fa4841
	Stream_Free(licenseStream, FALSE);
Packit Service fa4841
out_free_blob:
Packit Service fa4841
	license_free_binary_blob(calBlob);
Packit Service fa4841
	return ret;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Read an ERROR_ALERT packet.\n
Packit Service fa4841
 * @msdn{cc240482}
Packit Service fa4841
 * @param license license module
Packit Service fa4841
 * @param s stream
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
BOOL license_read_error_alert_packet(rdpLicense* license, wStream* s)
Packit Service fa4841
{
Packit Service fa4841
	UINT32 dwErrorCode;
Packit Service fa4841
	UINT32 dwStateTransition;
Packit Service fa4841
Packit Service fa4841
	if (Stream_GetRemainingLength(s) < 8)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	Stream_Read_UINT32(s, dwErrorCode);       /* dwErrorCode (4 bytes) */
Packit Service fa4841
	Stream_Read_UINT32(s, dwStateTransition); /* dwStateTransition (4 bytes) */
Packit Service fa4841
Packit Service fa4841
	if (!license_read_binary_blob(s, license->ErrorInfo)) /* bbErrorInfo */
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
#ifdef WITH_DEBUG_LICENSE
Packit Service fa4841
	WLog_DBG(TAG, "dwErrorCode: %s, dwStateTransition: %s", error_codes[dwErrorCode],
Packit Service fa4841
	         state_transitions[dwStateTransition]);
Packit Service fa4841
#endif
Packit Service fa4841
Packit Service fa4841
	if (dwErrorCode == STATUS_VALID_CLIENT)
Packit Service fa4841
	{
Packit Service fa4841
		license->state = LICENSE_STATE_COMPLETED;
Packit Service fa4841
		return TRUE;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	switch (dwStateTransition)
Packit Service fa4841
	{
Packit Service fa4841
		case ST_TOTAL_ABORT:
Packit Service fa4841
			license->state = LICENSE_STATE_ABORTED;
Packit Service fa4841
			break;
Packit Service fa4841
		case ST_NO_TRANSITION:
Packit Service fa4841
			license->state = LICENSE_STATE_COMPLETED;
Packit Service fa4841
			break;
Packit Service fa4841
		case ST_RESET_PHASE_TO_START:
Packit Service fa4841
			license->state = LICENSE_STATE_AWAIT;
Packit Service fa4841
			break;
Packit Service fa4841
		case ST_RESEND_LAST_MESSAGE:
Packit Service fa4841
			break;
Packit Service fa4841
		default:
Packit Service fa4841
			break;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Write a NEW_LICENSE_REQUEST packet.\n
Packit Service fa4841
 * @msdn{cc241918}
Packit Service fa4841
 * @param license license module
Packit Service fa4841
 * @param s stream
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
BOOL license_write_new_license_request_packet(rdpLicense* license, wStream* s)
Packit Service fa4841
{
Packit Service fa4841
	UINT32 PlatformId = PLATFORMID;
Packit Service fa4841
	UINT32 PreferredKeyExchangeAlg = KEY_EXCHANGE_ALG_RSA;
Packit Service fa4841
Packit Service fa4841
	Stream_Write_UINT32(s, PreferredKeyExchangeAlg); /* PreferredKeyExchangeAlg (4 bytes) */
Packit Service fa4841
	Stream_Write_UINT32(s, PlatformId);              /* PlatformId (4 bytes) */
Packit Service fa4841
	Stream_Write(s, license->ClientRandom, 32);      /* ClientRandom (32 bytes) */
Packit Service fa4841
Packit Service fa4841
	if (/* EncryptedPremasterSecret */
Packit Service fa4841
	    !license_write_encrypted_premaster_secret_blob(s, license->EncryptedPremasterSecret,
Packit Service fa4841
	                                                   license->ModulusLength) ||
Packit Service fa4841
	    /* ClientUserName */
Packit Service fa4841
	    !license_write_binary_blob(s, license->ClientUserName) ||
Packit Service fa4841
	    /* ClientMachineName */
Packit Service fa4841
	    !license_write_binary_blob(s, license->ClientMachineName))
Packit Service fa4841
	{
Packit Service fa4841
		return FALSE;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
#ifdef WITH_DEBUG_LICENSE
Packit Service fa4841
	WLog_DBG(TAG, "PreferredKeyExchangeAlg: 0x%08" PRIX32 "", PreferredKeyExchangeAlg);
Packit Service fa4841
	WLog_DBG(TAG, "ClientRandom:");
Packit Service fa4841
	winpr_HexDump(TAG, WLOG_DEBUG, license->ClientRandom, 32);
Packit Service fa4841
	WLog_DBG(TAG, "EncryptedPremasterSecret");
Packit Service fa4841
	winpr_HexDump(TAG, WLOG_DEBUG, license->EncryptedPremasterSecret->data,
Packit Service fa4841
	              license->EncryptedPremasterSecret->length);
Packit Service fa4841
	WLog_DBG(TAG, "ClientUserName (%" PRIu16 "): %s", license->ClientUserName->length,
Packit Service fa4841
	         (char*)license->ClientUserName->data);
Packit Service fa4841
	WLog_DBG(TAG, "ClientMachineName (%" PRIu16 "): %s", license->ClientMachineName->length,
Packit Service fa4841
	         (char*)license->ClientMachineName->data);
Packit Service fa4841
#endif
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Send a NEW_LICENSE_REQUEST packet.\n
Packit Service fa4841
 * @msdn{cc241918}
Packit Service fa4841
 * @param license license module
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
BOOL license_answer_license_request(rdpLicense* license)
Packit Service fa4841
{
Packit Service fa4841
	wStream* s;
Packit Service fa4841
	BYTE* license_data = NULL;
Packit Service fa4841
	int license_size = 0;
Packit Service fa4841
	BOOL status;
Packit Service fa4841
	char* username;
Packit Service fa4841
Packit Service fa4841
	if (!license->rdp->settings->OldLicenseBehaviour)
Packit Service fa4841
		license_data = loadCalFile(license->rdp->settings, license->rdp->settings->ClientHostname,
Packit Service fa4841
		                           &license_size);
Packit Service fa4841
Packit Service fa4841
	if (license_data)
Packit Service fa4841
	{
Packit Service fa4841
		LICENSE_BLOB* calBlob = NULL;
Packit Service fa4841
		BYTE signature[LICENSING_ENCRYPTION_KEY_LENGTH];
Packit Service fa4841
Packit Service fa4841
		DEBUG_LICENSE("Sending Saved License Packet");
Packit Service fa4841
Packit Service fa4841
		license->EncryptedHardwareId->type = BB_ENCRYPTED_DATA_BLOB;
Packit Service fa4841
		if (!license_encrypt_and_MAC(license, license->HardwareId, HWID_LENGTH,
Packit Service fa4841
		                             license->EncryptedHardwareId, signature))
Packit Service fa4841
		{
Packit Service fa4841
			free(license_data);
Packit Service fa4841
			return FALSE;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		calBlob = license_new_binary_blob(BB_DATA_BLOB);
Packit Service fa4841
		if (!calBlob)
Packit Service fa4841
		{
Packit Service fa4841
			free(license_data);
Packit Service fa4841
			return FALSE;
Packit Service fa4841
		}
Packit Service fa4841
		calBlob->data = license_data;
Packit Service fa4841
		calBlob->length = license_size;
Packit Service fa4841
Packit Service fa4841
		status = license_send_client_info(license, calBlob, signature);
Packit Service fa4841
		license_free_binary_blob(calBlob);
Packit Service fa4841
Packit Service fa4841
		return status;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	DEBUG_LICENSE("Sending New License Packet");
Packit Service fa4841
Packit Service fa4841
	s = license_send_stream_init(license);
Packit Service fa4841
	if (!s)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
	if (license->rdp->settings->Username != NULL)
Packit Service fa4841
		username = license->rdp->settings->Username;
Packit Service fa4841
	else
Packit Service fa4841
		username = "username";
Packit Service fa4841
Packit Service fa4841
	license->ClientUserName->data = (BYTE*)username;
Packit Service fa4841
	license->ClientUserName->length = strlen(username) + 1;
Packit Service fa4841
	license->ClientMachineName->data = (BYTE*)license->rdp->settings->ClientHostname;
Packit Service fa4841
	license->ClientMachineName->length = strlen(license->rdp->settings->ClientHostname) + 1;
Packit Service fa4841
Packit Service fa4841
	status = license_write_new_license_request_packet(license, s);
Packit Service fa4841
Packit Service fa4841
	license->ClientUserName->data = NULL;
Packit Service fa4841
	license->ClientUserName->length = 0;
Packit Service fa4841
	license->ClientMachineName->data = NULL;
Packit Service fa4841
	license->ClientMachineName->length = 0;
Packit Service fa4841
Packit Service fa4841
	if (!status)
Packit Service fa4841
	{
Packit Service fa4841
		Stream_Release(s);
Packit Service fa4841
		return FALSE;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	return license_send(license, s, NEW_LICENSE_REQUEST);
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Write Client Challenge Response Packet.\n
Packit Service fa4841
 * @msdn{cc241922}
Packit Service fa4841
 * @param license license module
Packit Service fa4841
 * @param s stream
Packit Service fa4841
 * @param mac_data signature
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
BOOL license_write_platform_challenge_response_packet(rdpLicense* license, wStream* s,
Packit Service fa4841
                                                      const BYTE* macData)
Packit Service fa4841
{
Packit Service fa4841
	if (!license_write_binary_blob(
Packit Service fa4841
	        s,
Packit Service fa4841
	        license->EncryptedPlatformChallengeResponse) || /* EncryptedPlatformChallengeResponse */
Packit Service fa4841
	    !license_write_binary_blob(s, license->EncryptedHardwareId) || /* EncryptedHWID */
Packit Service fa4841
	    !Stream_EnsureRemainingCapacity(s, 16))
Packit Service fa4841
	{
Packit Service fa4841
		return FALSE;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	Stream_Write(s, macData, 16); /* MACData */
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Send Client Challenge Response Packet.\n
Packit Service fa4841
 * @msdn{cc241922}
Packit Service fa4841
 * @param license license module
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
BOOL license_send_platform_challenge_response_packet(rdpLicense* license)
Packit Service fa4841
{
Packit Service fa4841
	wStream* s;
Packit Service fa4841
	wStream* challengeRespData;
Packit Service fa4841
	int length;
Packit Service fa4841
	BYTE* buffer;
Packit Service fa4841
	BYTE mac_data[16];
Packit Service fa4841
	BOOL status;
Packit Service fa4841
Packit Service fa4841
	DEBUG_LICENSE("Sending Platform Challenge Response Packet");
Packit Service fa4841
	s = license_send_stream_init(license);
Packit Service fa4841
	license->EncryptedPlatformChallenge->type = BB_DATA_BLOB;
Packit Service fa4841
Packit Service fa4841
	/* prepare the PLATFORM_CHALLENGE_RESPONSE_DATA */
Packit Service fa4841
	challengeRespData = Stream_New(NULL, 8 + license->PlatformChallenge->length);
Packit Service fa4841
	if (!challengeRespData)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
	Stream_Write_UINT16(challengeRespData, 0x0100);                        /* wVersion */
Packit Service fa4841
	Stream_Write_UINT16(challengeRespData, OTHER_PLATFORM_CHALLENGE_TYPE); /* wClientType */
Packit Service fa4841
	Stream_Write_UINT16(challengeRespData, LICENSE_DETAIL_DETAIL);         /* wLicenseDetailLevel */
Packit Service fa4841
	Stream_Write_UINT16(challengeRespData, license->PlatformChallenge->length); /* cbChallenge */
Packit Service fa4841
	Stream_Write(challengeRespData, license->PlatformChallenge->data,
Packit Service fa4841
	             license->PlatformChallenge->length); /* pbChallenge */
Packit Service fa4841
	Stream_SealLength(challengeRespData);
Packit Service fa4841
Packit Service fa4841
	/* compute MAC of PLATFORM_CHALLENGE_RESPONSE_DATA + HWID */
Packit Service fa4841
	length = Stream_Length(challengeRespData) + HWID_LENGTH;
Packit Service fa4841
	buffer = (BYTE*)malloc(length);
Packit Service fa4841
	if (!buffer)
Packit Service fa4841
	{
Packit Service fa4841
		Stream_Free(challengeRespData, TRUE);
Packit Service fa4841
		return FALSE;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	CopyMemory(buffer, Stream_Buffer(challengeRespData), Stream_Length(challengeRespData));
Packit Service fa4841
	CopyMemory(&buffer[Stream_Length(challengeRespData)], license->HardwareId, HWID_LENGTH);
Packit Service fa4841
	status = security_mac_data(license->MacSaltKey, buffer, length, mac_data);
Packit Service fa4841
	free(buffer);
Packit Service fa4841
Packit Service fa4841
	if (!status)
Packit Service fa4841
	{
Packit Service fa4841
		Stream_Free(challengeRespData, TRUE);
Packit Service fa4841
		return FALSE;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	license->EncryptedHardwareId->type = BB_ENCRYPTED_DATA_BLOB;
Packit Service fa4841
	if (!license_rc4_with_licenseKey(license, license->HardwareId, HWID_LENGTH,
Packit Service fa4841
	                                 license->EncryptedHardwareId))
Packit Service fa4841
	{
Packit Service fa4841
		Stream_Free(challengeRespData, TRUE);
Packit Service fa4841
		return FALSE;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	status = license_rc4_with_licenseKey(license, Stream_Buffer(challengeRespData),
Packit Service fa4841
	                                     Stream_Length(challengeRespData),
Packit Service fa4841
	                                     license->EncryptedPlatformChallengeResponse);
Packit Service fa4841
	Stream_Free(challengeRespData, TRUE);
Packit Service fa4841
	if (!status)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
#ifdef WITH_DEBUG_LICENSE
Packit Service fa4841
	WLog_DBG(TAG, "LicensingEncryptionKey:");
Packit Service fa4841
	winpr_HexDump(TAG, WLOG_DEBUG, license->LicensingEncryptionKey, 16);
Packit Service fa4841
	WLog_DBG(TAG, "HardwareId:");
Packit Service fa4841
	winpr_HexDump(TAG, WLOG_DEBUG, license->HardwareId, HWID_LENGTH);
Packit Service fa4841
	WLog_DBG(TAG, "EncryptedHardwareId:");
Packit Service fa4841
	winpr_HexDump(TAG, WLOG_DEBUG, license->EncryptedHardwareId->data, HWID_LENGTH);
Packit Service fa4841
#endif
Packit Service fa4841
	if (license_write_platform_challenge_response_packet(license, s, mac_data))
Packit Service fa4841
		return license_send(license, s, PLATFORM_CHALLENGE_RESPONSE);
Packit Service fa4841
Packit Service fa4841
	Stream_Release(s);
Packit Service fa4841
	return FALSE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Send Server License Error - Valid Client Packet.\n
Packit Service fa4841
 * @msdn{cc241922}
Packit Service fa4841
 * @param license license module
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
BOOL license_send_valid_client_error_packet(rdpRdp* rdp)
Packit Service fa4841
{
Packit Service fa4841
	rdpLicense* license = rdp->license;
Packit Service fa4841
	wStream* s = license_send_stream_init(license);
Packit Service fa4841
	if (!s)
Packit Service fa4841
		return FALSE;
Packit Service fa4841
Packit Service fa4841
	DEBUG_LICENSE("Sending Error Alert Packet");
Packit Service fa4841
	Stream_Write_UINT32(s, STATUS_VALID_CLIENT); /* dwErrorCode */
Packit Service fa4841
	Stream_Write_UINT32(s, ST_NO_TRANSITION);    /* dwStateTransition */
Packit Service fa4841
Packit Service fa4841
	if (license_write_binary_blob(s, license->ErrorInfo))
Packit Service fa4841
		return license_send(license, s, ERROR_ALERT);
Packit Service fa4841
Packit Service fa4841
	Stream_Release(s);
Packit Service fa4841
	return FALSE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Instantiate new license module.
Packit Service fa4841
 * @param rdp RDP module
Packit Service fa4841
 * @return new license module
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
rdpLicense* license_new(rdpRdp* rdp)
Packit Service fa4841
{
Packit Service fa4841
	rdpLicense* license;
Packit Service fa4841
	license = (rdpLicense*)calloc(1, sizeof(rdpLicense));
Packit Service fa4841
	if (!license)
Packit Service fa4841
		return NULL;
Packit Service fa4841
Packit Service fa4841
	license->rdp = rdp;
Packit Service fa4841
	license->state = LICENSE_STATE_AWAIT;
Packit Service fa4841
	if (!(license->certificate = certificate_new()))
Packit Service fa4841
		goto out_error;
Packit Service fa4841
	if (!(license->ProductInfo = license_new_product_info()))
Packit Service fa4841
		goto out_error;
Packit Service fa4841
	if (!(license->ErrorInfo = license_new_binary_blob(BB_ERROR_BLOB)))
Packit Service fa4841
		goto out_error;
Packit Service fa4841
	if (!(license->KeyExchangeList = license_new_binary_blob(BB_KEY_EXCHG_ALG_BLOB)))
Packit Service fa4841
		goto out_error;
Packit Service fa4841
	if (!(license->ServerCertificate = license_new_binary_blob(BB_CERTIFICATE_BLOB)))
Packit Service fa4841
		goto out_error;
Packit Service fa4841
	if (!(license->ClientUserName = license_new_binary_blob(BB_CLIENT_USER_NAME_BLOB)))
Packit Service fa4841
		goto out_error;
Packit Service fa4841
	if (!(license->ClientMachineName = license_new_binary_blob(BB_CLIENT_MACHINE_NAME_BLOB)))
Packit Service fa4841
		goto out_error;
Packit Service fa4841
	if (!(license->PlatformChallenge = license_new_binary_blob(BB_ANY_BLOB)))
Packit Service fa4841
		goto out_error;
Packit Service fa4841
	if (!(license->EncryptedPlatformChallenge = license_new_binary_blob(BB_ANY_BLOB)))
Packit Service fa4841
		goto out_error;
Packit Service fa4841
	if (!(license->EncryptedPlatformChallengeResponse =
Packit Service fa4841
	          license_new_binary_blob(BB_ENCRYPTED_DATA_BLOB)))
Packit Service fa4841
		goto out_error;
Packit Service fa4841
	if (!(license->EncryptedPremasterSecret = license_new_binary_blob(BB_ANY_BLOB)))
Packit Service fa4841
		goto out_error;
Packit Service fa4841
	if (!(license->EncryptedHardwareId = license_new_binary_blob(BB_ENCRYPTED_DATA_BLOB)))
Packit Service fa4841
		goto out_error;
Packit Service fa4841
	if (!(license->ScopeList = license_new_scope_list()))
Packit Service fa4841
		goto out_error;
Packit Service fa4841
Packit Service fa4841
	license_generate_randoms(license);
Packit Service fa4841
Packit Service fa4841
	return license;
Packit Service fa4841
Packit Service fa4841
out_error:
Packit Service fa4841
	license_free(license);
Packit Service fa4841
	return NULL;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Free license module.
Packit Service fa4841
 * @param license license module to be freed
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
void license_free(rdpLicense* license)
Packit Service fa4841
{
Packit Service fa4841
	if (license)
Packit Service fa4841
	{
Packit Service fa4841
		free(license->Modulus);
Packit Service fa4841
		certificate_free(license->certificate);
Packit Service fa4841
		license_free_product_info(license->ProductInfo);
Packit Service fa4841
		license_free_binary_blob(license->ErrorInfo);
Packit Service fa4841
		license_free_binary_blob(license->KeyExchangeList);
Packit Service fa4841
		license_free_binary_blob(license->ServerCertificate);
Packit Service fa4841
		license_free_binary_blob(license->ClientUserName);
Packit Service fa4841
		license_free_binary_blob(license->ClientMachineName);
Packit Service fa4841
		license_free_binary_blob(license->PlatformChallenge);
Packit Service fa4841
		license_free_binary_blob(license->EncryptedPlatformChallenge);
Packit Service fa4841
		license_free_binary_blob(license->EncryptedPlatformChallengeResponse);
Packit Service fa4841
		license_free_binary_blob(license->EncryptedPremasterSecret);
Packit Service fa4841
		license_free_binary_blob(license->EncryptedHardwareId);
Packit Service fa4841
		license_free_scope_list(license->ScopeList);
Packit Service fa4841
		free(license);
Packit Service fa4841
	}
Packit Service fa4841
}