2 * FreeRDP: A Remote Desktop Protocol Client
5 * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
20 #include "redirection.h"
24 #ifdef WITH_DEBUG_LICENSE
25 static const char* const LICENSE_MESSAGE_STRINGS[] =
32 "", "", "", "", "", "",
33 "", "", "", "", "", "",
36 "New License Request",
38 "Platform Challenge Response",
39 "", "", "", "", "", "", "", "", "",
43 static const char* const error_codes[] =
46 "ERR_INVALID_SERVER_CERTIFICATE",
51 "ERR_NO_LICENSE_SERVER",
52 "STATUS_VALID_CLIENT",
56 "ERR_INVALID_PRODUCT_ID",
57 "ERR_INVALID_MESSAGE_LENGTH"
60 static const char* const state_transitions[] =
65 "ST_RESET_PHASE_TO_START",
66 "ST_RESEND_LAST_MESSAGE"
71 * Read a licensing preamble.\n
74 * @param bMsgType license message type
75 * @param flags message flags
76 * @param wMsgSize message size
79 void license_read_preamble(STREAM* s, uint8* bMsgType, uint8* flags, uint16* wMsgSize)
81 /* preamble (4 bytes) */
82 stream_read_uint8(s, *bMsgType); /* bMsgType (1 byte) */
83 stream_read_uint8(s, *flags); /* flags (1 byte) */
84 stream_read_uint16(s, *wMsgSize); /* wMsgSize (2 bytes) */
88 * Write a licensing preamble.\n
91 * @param bMsgType license message type
92 * @param flags message flags
93 * @param wMsgSize message size
96 void license_write_preamble(STREAM* s, uint8 bMsgType, uint8 flags, uint16 wMsgSize)
98 /* preamble (4 bytes) */
99 stream_write_uint8(s, bMsgType); /* bMsgType (1 byte) */
100 stream_write_uint8(s, flags); /* flags (1 byte) */
101 stream_write_uint16(s, wMsgSize); /* wMsgSize (2 bytes) */
105 * Initialize a license packet stream.\n
106 * @param license license module
110 STREAM* license_send_stream_init(rdpLicense* license)
113 s = transport_send_stream_init(license->rdp->transport, 4096);
114 stream_seek(s, LICENSE_PACKET_HEADER_MAX_LENGTH);
119 * Send an RDP licensing packet.\n
121 * @param license license module
125 boolean license_send(rdpLicense* license, STREAM* s, uint8 type)
132 DEBUG_LICENSE("Sending %s Packet", LICENSE_MESSAGE_STRINGS[type & 0x1F]);
134 length = stream_get_length(s);
135 stream_set_pos(s, 0);
137 sec_flags = SEC_LICENSE_PKT;
138 wMsgSize = length - LICENSE_PACKET_HEADER_MAX_LENGTH + 4;
140 * Using EXTENDED_ERROR_MSG_SUPPORTED here would cause mstsc to crash when
141 * running in server mode! This flag seems to be incorrectly documented.
143 flags = PREAMBLE_VERSION_3_0;
145 rdp_write_header(license->rdp, s, length, MCS_GLOBAL_CHANNEL_ID);
146 rdp_write_security_header(s, sec_flags);
147 license_write_preamble(s, type, flags, wMsgSize);
149 #ifdef WITH_DEBUG_LICENSE
150 printf("Sending %s Packet, length %d\n", LICENSE_MESSAGE_STRINGS[type & 0x1F], wMsgSize);
151 freerdp_hexdump(s->p - 4, wMsgSize);
154 stream_set_pos(s, length);
155 if (transport_write(license->rdp->transport, s) < 0)
162 * Receive an RDP licensing packet.\n
164 * @param license license module
168 boolean license_recv(rdpLicense* license, STREAM* s)
177 if (!rdp_read_header(license->rdp, s, &length, &channelId))
179 printf("Incorrect RDP header.\n");
183 rdp_read_security_header(s, &sec_flags);
184 if (!(sec_flags & SEC_LICENSE_PKT))
186 stream_rewind(s, RDP_SECURITY_HEADER_LENGTH);
187 if (rdp_recv_out_of_sequence_pdu(license->rdp, s) != true)
189 printf("Unexpected license packet.\n");
195 license_read_preamble(s, &bMsgType, &flags, &wMsgSize); /* preamble (4 bytes) */
197 DEBUG_LICENSE("Receiving %s Packet", LICENSE_MESSAGE_STRINGS[bMsgType & 0x1F]);
201 case LICENSE_REQUEST:
202 license_read_license_request_packet(license, s);
203 license_send_new_license_request_packet(license);
206 case PLATFORM_CHALLENGE:
207 license_read_platform_challenge_packet(license, s);
208 license_send_platform_challenge_response_packet(license);
212 license_read_new_license_packet(license, s);
215 case UPGRADE_LICENSE:
216 license_read_upgrade_license_packet(license, s);
220 license_read_error_alert_packet(license, s);
224 printf("invalid bMsgType:%d\n", bMsgType);
231 void license_generate_randoms(rdpLicense* license)
234 crypto_nonce(license->client_random, CLIENT_RANDOM_LENGTH); /* ClientRandom */
235 crypto_nonce(license->premaster_secret, PREMASTER_SECRET_LENGTH); /* PremasterSecret */
237 memset(license->client_random, 0, CLIENT_RANDOM_LENGTH); /* ClientRandom */
238 memset(license->premaster_secret, 0, PREMASTER_SECRET_LENGTH); /* PremasterSecret */
243 * Generate License Cryptographic Keys.
244 * @param license license module
247 void license_generate_keys(rdpLicense* license)
249 security_master_secret(license->premaster_secret, license->client_random,
250 license->server_random, license->master_secret); /* MasterSecret */
252 security_session_key_blob(license->master_secret, license->client_random,
253 license->server_random, license->session_key_blob); /* SessionKeyBlob */
255 security_mac_salt_key(license->session_key_blob, license->client_random,
256 license->server_random, license->mac_salt_key); /* MacSaltKey */
258 security_licensing_encryption_key(license->session_key_blob, license->client_random,
259 license->server_random, license->licensing_encryption_key); /* LicensingEncryptionKey */
261 #ifdef WITH_DEBUG_LICENSE
262 printf("ClientRandom:\n");
263 freerdp_hexdump(license->client_random, CLIENT_RANDOM_LENGTH);
265 printf("ServerRandom:\n");
266 freerdp_hexdump(license->server_random, SERVER_RANDOM_LENGTH);
268 printf("PremasterSecret:\n");
269 freerdp_hexdump(license->premaster_secret, PREMASTER_SECRET_LENGTH);
271 printf("MasterSecret:\n");
272 freerdp_hexdump(license->master_secret, MASTER_SECRET_LENGTH);
274 printf("SessionKeyBlob:\n");
275 freerdp_hexdump(license->session_key_blob, SESSION_KEY_BLOB_LENGTH);
277 printf("MacSaltKey:\n");
278 freerdp_hexdump(license->mac_salt_key, MAC_SALT_KEY_LENGTH);
280 printf("LicensingEncryptionKey:\n");
281 freerdp_hexdump(license->licensing_encryption_key, LICENSING_ENCRYPTION_KEY_LENGTH);
286 * Generate Unique Hardware Identifier (CLIENT_HARDWARE_ID).\n
287 * @param license license module
290 void license_generate_hwid(rdpLicense* license)
295 memset(license->hwid, 0, HWID_LENGTH);
296 mac_address = license->rdp->transport->tcp->mac_address;
298 md5 = crypto_md5_init();
299 crypto_md5_update(md5, mac_address, 6);
300 crypto_md5_final(md5, &license->hwid[HWID_PLATFORM_ID_LENGTH]);
303 void license_encrypt_premaster_secret(rdpLicense* license)
305 uint8* encrypted_premaster_secret;
310 rdpCertificate *certificate;
312 if (license->server_certificate->length)
313 certificate = license->certificate;
315 certificate = license->rdp->settings->server_cert;
317 exponent = certificate->cert_info.exponent;
318 modulus = certificate->cert_info.modulus.data;
319 key_length = certificate->cert_info.modulus.length;
321 #ifdef WITH_DEBUG_LICENSE
322 printf("modulus (%d bits):\n", key_length * 8);
323 freerdp_hexdump(modulus, key_length);
325 printf("exponent:\n");
326 freerdp_hexdump(exponent, 4);
329 encrypted_premaster_secret = (uint8*) xmalloc(MODULUS_MAX_SIZE);
330 memset(encrypted_premaster_secret, 0, MODULUS_MAX_SIZE);
332 crypto_rsa_public_encrypt(license->premaster_secret, PREMASTER_SECRET_LENGTH,
333 key_length, modulus, exponent, encrypted_premaster_secret);
335 license->encrypted_premaster_secret->type = BB_RANDOM_BLOB;
336 license->encrypted_premaster_secret->length = PREMASTER_SECRET_LENGTH;
337 license->encrypted_premaster_secret->data = encrypted_premaster_secret;
339 encrypted_premaster_secret = (uint8*) xmalloc(MODULUS_MAX_SIZE);
340 memset(encrypted_premaster_secret, 0, MODULUS_MAX_SIZE);
342 license->encrypted_premaster_secret->type = BB_RANDOM_BLOB;
343 license->encrypted_premaster_secret->length = PREMASTER_SECRET_LENGTH;
344 license->encrypted_premaster_secret->data = encrypted_premaster_secret;
348 void license_decrypt_platform_challenge(rdpLicense* license)
352 license->platform_challenge->data =
353 (uint8*) xmalloc(license->encrypted_platform_challenge->length);
354 license->platform_challenge->length =
355 license->encrypted_platform_challenge->length;
357 rc4 = crypto_rc4_init(license->licensing_encryption_key, LICENSING_ENCRYPTION_KEY_LENGTH);
359 crypto_rc4(rc4, license->encrypted_platform_challenge->length,
360 license->encrypted_platform_challenge->data,
361 license->platform_challenge->data);
363 #ifdef WITH_DEBUG_LICENSE
364 printf("encrypted_platform challenge:\n");
365 freerdp_hexdump(license->encrypted_platform_challenge->data,
366 license->encrypted_platform_challenge->length);
368 printf("platform challenge:\n");
369 freerdp_hexdump(license->platform_challenge->data, license->platform_challenge->length);
372 crypto_rc4_free(rc4);
376 * Read Product Information (PRODUCT_INFO).\n
379 * @param productInfo product information
382 void license_read_product_info(STREAM* s, PRODUCT_INFO* productInfo)
384 stream_read_uint32(s, productInfo->dwVersion); /* dwVersion (4 bytes) */
386 stream_read_uint32(s, productInfo->cbCompanyName); /* cbCompanyName (4 bytes) */
388 productInfo->pbCompanyName = (uint8*) xmalloc(productInfo->cbCompanyName);
389 stream_read(s, productInfo->pbCompanyName, productInfo->cbCompanyName);
391 stream_read_uint32(s, productInfo->cbProductId); /* cbProductId (4 bytes) */
393 productInfo->pbProductId = (uint8*) xmalloc(productInfo->cbProductId);
394 stream_read(s, productInfo->pbProductId, productInfo->cbProductId);
398 * Allocate New Product Information (PRODUCT_INFO).\n
400 * @return new product information
403 PRODUCT_INFO* license_new_product_info()
405 PRODUCT_INFO* productInfo;
407 productInfo = (PRODUCT_INFO*) xmalloc(sizeof(PRODUCT_INFO));
409 productInfo->dwVersion = 0;
410 productInfo->cbCompanyName = 0;
411 productInfo->pbCompanyName = NULL;
412 productInfo->cbProductId = 0;
413 productInfo->pbProductId = NULL;
419 * Free Product Information (PRODUCT_INFO).\n
421 * @param productInfo product information
424 void license_free_product_info(PRODUCT_INFO* productInfo)
426 if (productInfo->pbCompanyName != NULL)
427 xfree(productInfo->pbCompanyName);
429 if (productInfo->pbProductId != NULL)
430 xfree(productInfo->pbProductId);
436 * Read License Binary Blob (LICENSE_BINARY_BLOB).\n
439 * @param blob license binary blob
442 void license_read_binary_blob(STREAM* s, LICENSE_BLOB* blob)
446 stream_read_uint16(s, wBlobType); /* wBlobType (2 bytes) */
447 stream_read_uint16(s, blob->length); /* wBlobLen (2 bytes) */
450 * Server can choose to not send data by setting len to 0.
451 * If so, it may not bother to set the type, so shortcut the warning
453 if (blob->type != BB_ANY_BLOB && blob->length == 0)
456 if (blob->type != wBlobType && blob->type != BB_ANY_BLOB)
458 printf("license binary blob type (%x) does not match expected type (%x).\n", wBlobType, blob->type);
461 blob->type = wBlobType;
462 blob->data = (uint8*) xmalloc(blob->length);
464 stream_read(s, blob->data, blob->length); /* blobData */
468 * Write License Binary Blob (LICENSE_BINARY_BLOB).\n
471 * @param blob license binary blob
474 void license_write_binary_blob(STREAM* s, LICENSE_BLOB* blob)
476 stream_write_uint16(s, blob->type); /* wBlobType (2 bytes) */
477 stream_write_uint16(s, blob->length); /* wBlobLen (2 bytes) */
479 if (blob->length > 0)
480 stream_write(s, blob->data, blob->length); /* blobData */
483 void license_write_padded_binary_blob(STREAM* s, LICENSE_BLOB* blob)
487 pad_len = 72 % blob->length;
488 stream_write_uint16(s, blob->type); /* wBlobType (2 bytes) */
489 stream_write_uint16(s, blob->length + pad_len); /* wBlobLen (2 bytes) */
491 if (blob->length > 0)
492 stream_write(s, blob->data, blob->length); /* blobData */
494 stream_write_zero(s, pad_len);
498 * Allocate New License Binary Blob (LICENSE_BINARY_BLOB).\n
500 * @return new license binary blob
503 LICENSE_BLOB* license_new_binary_blob(uint16 type)
507 blob = (LICENSE_BLOB*) xmalloc(sizeof(LICENSE_BLOB));
516 * Free License Binary Blob (LICENSE_BINARY_BLOB).\n
518 * @param blob license binary blob
521 void license_free_binary_blob(LICENSE_BLOB* blob)
523 if (blob->data != NULL)
530 * Read License Scope List (SCOPE_LIST).\n
533 * @param scopeList scope list
536 void license_read_scope_list(STREAM* s, SCOPE_LIST* scopeList)
541 stream_read_uint32(s, scopeCount); /* ScopeCount (4 bytes) */
543 scopeList->count = scopeCount;
544 scopeList->array = (LICENSE_BLOB*) xmalloc(sizeof(LICENSE_BLOB) * scopeCount);
547 for (i = 0; i < scopeCount; i++)
549 scopeList->array[i].type = BB_SCOPE_BLOB;
550 license_read_binary_blob(s, &scopeList->array[i]);
555 * Allocate New License Scope List (SCOPE_LIST).\n
557 * @return new scope list
560 SCOPE_LIST* license_new_scope_list()
562 SCOPE_LIST* scopeList;
564 scopeList = (SCOPE_LIST*) xmalloc(sizeof(SCOPE_LIST));
565 scopeList->count = 0;
566 scopeList->array = NULL;
572 * Free License Scope List (SCOPE_LIST).\n
574 * @param scopeList scope list
577 void license_free_scope_list(SCOPE_LIST* scopeList)
581 for (i = 0; i < scopeList->count; i++)
583 license_free_binary_blob(&scopeList->array[i]);
590 * Read a LICENSE_REQUEST packet.\n
592 * @param license license module
596 void license_read_license_request_packet(rdpLicense* license, STREAM* s)
598 /* ServerRandom (32 bytes) */
599 stream_read(s, license->server_random, 32);
602 license_read_product_info(s, license->product_info);
604 /* KeyExchangeList */
605 license_read_binary_blob(s, license->key_exchange_list);
607 /* ServerCertificate */
608 license_read_binary_blob(s, license->server_certificate);
611 license_read_scope_list(s, license->scope_list);
613 /* Parse Server Certificate */
614 certificate_read_server_certificate(license->certificate,
615 license->server_certificate->data, license->server_certificate->length);
617 license_generate_keys(license);
618 license_generate_hwid(license);
619 license_encrypt_premaster_secret(license);
623 * Read a PLATFORM_CHALLENGE packet.\n
625 * @param license license module
629 void license_read_platform_challenge_packet(rdpLicense* license, STREAM* s)
631 DEBUG_LICENSE("Receiving Platform Challenge Packet");
633 stream_seek(s, 4); /* ConnectFlags, Reserved (4 bytes) */
635 /* EncryptedPlatformChallenge */
636 license->encrypted_platform_challenge->type = BB_ANY_BLOB;
637 license_read_binary_blob(s, license->encrypted_platform_challenge);
638 license->encrypted_platform_challenge->type = BB_ENCRYPTED_DATA_BLOB;
640 /* MACData (16 bytes) */
643 license_decrypt_platform_challenge(license);
647 * Read a NEW_LICENSE packet.\n
649 * @param license license module
653 void license_read_new_license_packet(rdpLicense* license, STREAM* s)
655 DEBUG_LICENSE("Receiving New License Packet");
656 license->state = LICENSE_STATE_COMPLETED;
660 * Read an UPGRADE_LICENSE packet.\n
662 * @param license license module
666 void license_read_upgrade_license_packet(rdpLicense* license, STREAM* s)
668 DEBUG_LICENSE("Receiving Upgrade License Packet");
669 license->state = LICENSE_STATE_COMPLETED;
673 * Read an ERROR_ALERT packet.\n
675 * @param license license module
679 void license_read_error_alert_packet(rdpLicense* license, STREAM* s)
682 uint32 dwStateTransition;
684 stream_read_uint32(s, dwErrorCode); /* dwErrorCode (4 bytes) */
685 stream_read_uint32(s, dwStateTransition); /* dwStateTransition (4 bytes) */
686 license_read_binary_blob(s, license->error_info); /* bbErrorInfo */
688 #ifdef WITH_DEBUG_LICENSE
689 printf("dwErrorCode: %s, dwStateTransition: %s\n",
690 error_codes[dwErrorCode], state_transitions[dwStateTransition]);
693 if (dwErrorCode == STATUS_VALID_CLIENT)
695 license->state = LICENSE_STATE_COMPLETED;
699 switch (dwStateTransition)
702 license->state = LICENSE_STATE_ABORTED;
705 case ST_NO_TRANSITION:
706 license->state = LICENSE_STATE_COMPLETED;
709 case ST_RESET_PHASE_TO_START:
710 license->state = LICENSE_STATE_AWAIT;
713 case ST_RESEND_LAST_MESSAGE:
722 * Write Platform ID.\n
724 * @param license license module
728 void license_write_platform_id(rdpLicense* license, STREAM* s)
730 stream_write_uint8(s, 0); /* Client Operating System Version */
731 stream_write_uint8(s, 0); /* Independent Software Vendor (ISV) */
732 stream_write_uint16(s, 0); /* Client Software Build */
736 * Write a NEW_LICENSE_REQUEST packet.\n
738 * @param license license module
742 void license_write_new_license_request_packet(rdpLicense* license, STREAM* s)
744 stream_write_uint32(s, KEY_EXCHANGE_ALG_RSA); /* PreferredKeyExchangeAlg (4 bytes) */
745 license_write_platform_id(license, s); /* PlatformId (4 bytes) */
746 stream_write(s, license->client_random, 32); /* ClientRandom (32 bytes) */
747 license_write_padded_binary_blob(s, license->encrypted_premaster_secret); /* EncryptedPremasterSecret */
748 license_write_binary_blob(s, license->client_user_name); /* ClientUserName */
749 license_write_binary_blob(s, license->client_machine_name); /* ClientMachineName */
753 * Send a NEW_LICENSE_REQUEST packet.\n
755 * @param license license module
758 void license_send_new_license_request_packet(rdpLicense* license)
763 s = license_send_stream_init(license);
765 if (license->rdp->settings->username != NULL)
766 username = license->rdp->settings->username;
768 username = "username";
770 license->client_user_name->data = (uint8*) username;
771 license->client_user_name->length = strlen(username) + 1;
773 license->client_machine_name->data = (uint8*) license->rdp->settings->client_hostname;
774 license->client_machine_name->length = strlen(license->rdp->settings->client_hostname) + 1;
776 license_write_new_license_request_packet(license, s);
778 license_send(license, s, NEW_LICENSE_REQUEST);
780 license->client_user_name->data = NULL;
781 license->client_user_name->length = 0;
783 license->client_machine_name->data = NULL;
784 license->client_machine_name->length = 0;
788 * Write Client Challenge Response Packet.\n
790 * @param license license module
792 * @param mac_data signature
795 void license_write_platform_challenge_response_packet(rdpLicense* license, STREAM* s, uint8* mac_data)
797 /* EncryptedPlatformChallengeResponse */
798 license_write_binary_blob(s, license->encrypted_platform_challenge);
801 license_write_binary_blob(s, license->encrypted_hwid);
804 stream_write(s, mac_data, 16);
808 * Send Client Challenge Response Packet.\n
810 * @param license license module
813 void license_send_platform_challenge_response_packet(rdpLicense* license)
821 s = license_send_stream_init(license);
822 DEBUG_LICENSE("Sending Platform Challenge Response Packet");
824 license->encrypted_platform_challenge->type = BB_DATA_BLOB;
825 length = license->platform_challenge->length + HWID_LENGTH;
826 buffer = (uint8*) xmalloc(length);
827 memcpy(buffer, license->platform_challenge->data, license->platform_challenge->length);
828 memcpy(&buffer[license->platform_challenge->length], license->hwid, HWID_LENGTH);
829 security_mac_data(license->mac_salt_key, buffer, length, mac_data);
832 buffer = (uint8*) xmalloc(HWID_LENGTH);
833 rc4 = crypto_rc4_init(license->licensing_encryption_key, LICENSING_ENCRYPTION_KEY_LENGTH);
834 crypto_rc4(rc4, HWID_LENGTH, license->hwid, buffer);
835 crypto_rc4_free(rc4);
837 #ifdef WITH_DEBUG_LICENSE
838 printf("Licensing Encryption Key:\n");
839 freerdp_hexdump(license->licensing_encryption_key, 16);
841 printf("HardwareID:\n");
842 freerdp_hexdump(license->hwid, 20);
844 printf("Encrypted HardwareID:\n");
845 freerdp_hexdump(buffer, 20);
848 license->encrypted_hwid->type = BB_DATA_BLOB;
849 license->encrypted_hwid->data = buffer;
850 license->encrypted_hwid->length = HWID_LENGTH;
852 license_write_platform_challenge_response_packet(license, s, mac_data);
854 license_send(license, s, PLATFORM_CHALLENGE_RESPONSE);
858 * Send Server License Error - Valid Client Packet.\n
860 * @param license license module
863 boolean license_send_valid_client_error_packet(rdpLicense* license)
867 s = license_send_stream_init(license);
869 stream_write_uint32(s, STATUS_VALID_CLIENT); /* dwErrorCode */
870 stream_write_uint32(s, ST_NO_TRANSITION); /* dwStateTransition */
872 license_write_binary_blob(s, license->error_info);
874 license_send(license, s, ERROR_ALERT);
880 * Instantiate new license module.
881 * @param rdp RDP module
882 * @return new license module
885 rdpLicense* license_new(rdpRdp* rdp)
889 license = (rdpLicense*) xzalloc(sizeof(rdpLicense));
894 license->state = LICENSE_STATE_AWAIT;
895 //license->certificate = certificate_new(rdp);
896 license->certificate = certificate_new();
897 license->product_info = license_new_product_info();
898 license->error_info = license_new_binary_blob(BB_ERROR_BLOB);
899 license->key_exchange_list = license_new_binary_blob(BB_KEY_EXCHG_ALG_BLOB);
900 license->server_certificate = license_new_binary_blob(BB_CERTIFICATE_BLOB);
901 license->client_user_name = license_new_binary_blob(BB_CLIENT_USER_NAME_BLOB);
902 license->client_machine_name = license_new_binary_blob(BB_CLIENT_MACHINE_NAME_BLOB);
903 license->platform_challenge = license_new_binary_blob(BB_ANY_BLOB);
904 license->encrypted_platform_challenge = license_new_binary_blob(BB_ANY_BLOB);
905 license->encrypted_premaster_secret = license_new_binary_blob(BB_ANY_BLOB);
906 license->encrypted_hwid = license_new_binary_blob(BB_ENCRYPTED_DATA_BLOB);
907 license->scope_list = license_new_scope_list();
908 license_generate_randoms(license);
915 * Free license module.
916 * @param license license module to be freed
919 void license_free(rdpLicense* license)
923 certificate_free(license->certificate);
924 license_free_product_info(license->product_info);
925 license_free_binary_blob(license->error_info);
926 license_free_binary_blob(license->key_exchange_list);
927 license_free_binary_blob(license->server_certificate);
928 license_free_binary_blob(license->client_user_name);
929 license_free_binary_blob(license->client_machine_name);
930 license_free_binary_blob(license->platform_challenge);
931 license_free_binary_blob(license->encrypted_platform_challenge);
932 license_free_binary_blob(license->encrypted_premaster_secret);
933 license_free_binary_blob(license->encrypted_hwid);
934 license_free_scope_list(license->scope_list);