FreeRDP
license.c
1 /*
2  * FreeRDP: A Remote Desktop Protocol Implementation
3  * RDP Licensing
4  *
5  * Copyright 2011-2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6  * Copyright 2014 Norbert Federa <norbert.federa@thincast.com>
7  * Copyright 2018 David Fort <contact@hardening-consulting.com>
8  * Copyright 2022,2023 Armin Novak <armin.novak@thincast.com>
9  * Copyright 2022,2023 Thincast Technologies GmbH
10  *
11  * Licensed under the Apache License, Version 2.0 (the "License");
12  * you may not use this file except in compliance with the License.
13  * You may obtain a copy of the License at
14  *
15  * http://www.apache.org/licenses/LICENSE-2.0
16  *
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  */
23 
24 #include <freerdp/config.h>
25 
26 #include "settings.h"
27 
28 #include <freerdp/license.h>
29 
30 #include <winpr/crt.h>
31 #include <winpr/assert.h>
32 #include <winpr/crypto.h>
33 #include <winpr/shell.h>
34 #include <winpr/path.h>
35 #include <winpr/file.h>
36 
37 #include <freerdp/log.h>
38 
39 #include <freerdp/crypto/certificate.h>
40 
41 #include "license.h"
42 
43 #include "../crypto/crypto.h"
44 #include "../crypto/certificate.h"
45 
46 #define TAG FREERDP_TAG("core.license")
47 
48 #if 0
49 #define LICENSE_NULL_CLIENT_RANDOM 1
50 #define LICENSE_NULL_PREMASTER_SECRET 1
51 #endif
52 
53 #define PLATFORM_CHALLENGE_RESPONSE_VERSION 0x0100
54 
56 enum LicenseRequestType
57 {
58  LICENSE_REQUEST = 0x01,
59  PLATFORM_CHALLENGE = 0x02,
60  NEW_LICENSE = 0x03,
61  UPGRADE_LICENSE = 0x04,
62  LICENSE_INFO = 0x12,
63  NEW_LICENSE_REQUEST = 0x13,
64  PLATFORM_CHALLENGE_RESPONSE = 0x15,
65  ERROR_ALERT = 0xFF
66 };
67 
68 // #define LICENSE_PKT_CS_MASK \
69 // (LICENSE_INFO | NEW_LICENSE_REQUEST | PLATFORM_CHALLENGE_RESPONSE | ERROR_ALERT)
70 //#define LICENSE_PKT_SC_MASK \
71 // (LICENSE_REQUEST | PLATFORM_CHALLENGE | NEW_LICENSE | UPGRADE_LICENSE | ERROR_ALERT)
72 //#define LICENSE_PKT_MASK (LICENSE_PKT_CS_MASK | LICENSE_PKT_SC_MASK)
73 
74 #define LICENSE_PREAMBLE_LENGTH 4
75 
76 /* Cryptographic Lengths */
77 
78 #define SERVER_RANDOM_LENGTH 32
79 #define MASTER_SECRET_LENGTH 48
80 #define PREMASTER_SECRET_LENGTH 48
81 #define SESSION_KEY_BLOB_LENGTH 48
82 #define MAC_SALT_KEY_LENGTH 16
83 #define LICENSING_ENCRYPTION_KEY_LENGTH 16
84 #define HWID_PLATFORM_ID_LENGTH 4
85 // #define HWID_UNIQUE_DATA_LENGTH 16
86 #define HWID_LENGTH 20
87 // #define LICENSING_PADDING_SIZE 8
88 
89 /* Preamble Flags */
90 
91 // #define PREAMBLE_VERSION_2_0 0x02
92 #define PREAMBLE_VERSION_3_0 0x03
93 // #define LicenseProtocolVersionMask 0x0F
94 #define EXTENDED_ERROR_MSG_SUPPORTED 0x80
95 
97 enum
98 {
99  BB_ANY_BLOB = 0x0000,
100  BB_DATA_BLOB = 0x0001,
101  BB_RANDOM_BLOB = 0x0002,
102  BB_CERTIFICATE_BLOB = 0x0003,
103  BB_ERROR_BLOB = 0x0004,
104  BB_ENCRYPTED_DATA_BLOB = 0x0009,
105  BB_KEY_EXCHG_ALG_BLOB = 0x000D,
106  BB_SCOPE_BLOB = 0x000E,
107  BB_CLIENT_USER_NAME_BLOB = 0x000F,
108  BB_CLIENT_MACHINE_NAME_BLOB = 0x0010
109 };
110 
111 /* License Key Exchange Algorithms */
112 
113 #define KEY_EXCHANGE_ALG_RSA 0x00000001
114 
117 enum
118 {
119  ERR_INVALID_SERVER_CERTIFICATE = 0x00000001,
120  ERR_NO_LICENSE = 0x00000002,
121  ERR_INVALID_MAC = 0x00000003,
122  ERR_INVALID_SCOPE = 0x00000004,
123  ERR_NO_LICENSE_SERVER = 0x00000006,
124  STATUS_VALID_CLIENT = 0x00000007,
125  ERR_INVALID_CLIENT = 0x00000008,
126  ERR_INVALID_PRODUCT_ID = 0x0000000B,
127  ERR_INVALID_MESSAGE_LENGTH = 0x0000000C
128 };
129 
132 enum
133 {
134  ST_TOTAL_ABORT = 0x00000001,
135  ST_NO_TRANSITION = 0x00000002,
136  ST_RESET_PHASE_TO_START = 0x00000003,
137  ST_RESEND_LAST_MESSAGE = 0x00000004
138 };
139 
142 enum
143 {
144  WIN32_PLATFORM_CHALLENGE_TYPE = 0x0100,
145  WIN16_PLATFORM_CHALLENGE_TYPE = 0x0200,
146  WINCE_PLATFORM_CHALLENGE_TYPE = 0x0300,
147  OTHER_PLATFORM_CHALLENGE_TYPE = 0xFF00
148 };
149 
152 enum
153 {
154  LICENSE_DETAIL_SIMPLE = 0x0001,
155  LICENSE_DETAIL_MODERATE = 0x0002,
156  LICENSE_DETAIL_DETAIL = 0x0003
157 };
158 
159 /*
160  * PlatformId:
161  *
162  * The most significant byte of the PlatformId field contains the operating system version of the
163  * client. The second most significant byte of the PlatformId field identifies the ISV that provided
164  * the client image. The remaining two bytes in the PlatformId field are used by the ISV to identify
165  * the build number of the operating system.
166  *
167  * 0x04010000:
168  *
169  * CLIENT_OS_ID_WINNT_POST_52 (0x04000000)
170  * CLIENT_IMAGE_ID_MICROSOFT (0x00010000)
171  */
172 enum
173 {
174  CLIENT_OS_ID_WINNT_351 = 0x01000000,
175  CLIENT_OS_ID_WINNT_40 = 0x02000000,
176  CLIENT_OS_ID_WINNT_50 = 0x03000000,
177  CLIENT_OS_ID_WINNT_POST_52 = 0x04000000,
178 
179  CLIENT_IMAGE_ID_MICROSOFT = 0x00010000,
180  CLIENT_IMAGE_ID_CITRIX = 0x00020000,
181 };
182 
183 struct rdp_license
184 {
185  LICENSE_STATE state;
186  LICENSE_TYPE type;
187  rdpRdp* rdp;
188  rdpCertificate* certificate;
189  BYTE HardwareId[HWID_LENGTH];
190  BYTE ClientRandom[CLIENT_RANDOM_LENGTH];
191  BYTE ServerRandom[SERVER_RANDOM_LENGTH];
192  BYTE MasterSecret[MASTER_SECRET_LENGTH];
193  BYTE PremasterSecret[PREMASTER_SECRET_LENGTH];
194  BYTE SessionKeyBlob[SESSION_KEY_BLOB_LENGTH];
195  BYTE MacSaltKey[MAC_SALT_KEY_LENGTH];
196  BYTE LicensingEncryptionKey[LICENSING_ENCRYPTION_KEY_LENGTH];
197  LICENSE_PRODUCT_INFO* ProductInfo;
198  LICENSE_BLOB* ErrorInfo;
199  LICENSE_BLOB* LicenseInfo; /* Client -> Server */
200  LICENSE_BLOB* KeyExchangeList;
201  LICENSE_BLOB* ServerCertificate;
202  LICENSE_BLOB* ClientUserName;
203  LICENSE_BLOB* ClientMachineName;
204  LICENSE_BLOB* PlatformChallenge;
205  LICENSE_BLOB* EncryptedPremasterSecret;
206  LICENSE_BLOB* EncryptedPlatformChallenge;
207  LICENSE_BLOB* EncryptedPlatformChallengeResponse;
208  LICENSE_BLOB* EncryptedHardwareId;
209  LICENSE_BLOB* EncryptedLicenseInfo;
210  BYTE MACData[LICENSING_ENCRYPTION_KEY_LENGTH];
211  SCOPE_LIST* ScopeList;
212  UINT32 PacketHeaderLength;
213  UINT32 PreferredKeyExchangeAlg;
214  UINT32 PlatformId;
215  UINT16 ClientType;
216  UINT16 LicenseDetailLevel;
217  BOOL update;
218 };
219 
220 static BOOL license_send_error_alert(rdpLicense* license, UINT32 dwErrorCode,
221  UINT32 dwStateTransition, const LICENSE_BLOB* info);
222 static BOOL license_set_state(rdpLicense* license, LICENSE_STATE state);
223 static const char* license_get_state_string(LICENSE_STATE state);
224 
225 static const char* license_preferred_key_exchange_alg_string(UINT32 alg, char* buffer, size_t size)
226 {
227  const char* name = NULL;
228 
229  switch (alg)
230  {
231  case KEY_EXCHANGE_ALG_RSA:
232  name = "KEY_EXCHANGE_ALG_RSA";
233  break;
234  default:
235  name = "KEY_EXCHANGE_ALG_UNKNOWN";
236  break;
237  }
238 
239  (void)_snprintf(buffer, size, "%s [0x%08" PRIx32 "]", name, alg);
240  return buffer;
241 }
242 
243 static const char* license_request_type_string(UINT32 type)
244 {
245  switch (type)
246  {
247  case LICENSE_REQUEST:
248  return "LICENSE_REQUEST";
249  case PLATFORM_CHALLENGE:
250  return "PLATFORM_CHALLENGE";
251  case NEW_LICENSE:
252  return "NEW_LICENSE";
253  case UPGRADE_LICENSE:
254  return "UPGRADE_LICENSE";
255  case LICENSE_INFO:
256  return "LICENSE_INFO";
257  case NEW_LICENSE_REQUEST:
258  return "NEW_LICENSE_REQUEST";
259  case PLATFORM_CHALLENGE_RESPONSE:
260  return "PLATFORM_CHALLENGE_RESPONSE";
261  case ERROR_ALERT:
262  return "ERROR_ALERT";
263  default:
264  return "LICENSE_REQUEST_TYPE_UNKNOWN";
265  }
266 }
267 
268 static const char* licencse_blob_type_string(UINT16 type)
269 {
270  switch (type)
271  {
272  case BB_ANY_BLOB:
273  return "BB_ANY_BLOB";
274  case BB_DATA_BLOB:
275  return "BB_DATA_BLOB";
276  case BB_RANDOM_BLOB:
277  return "BB_RANDOM_BLOB";
278  case BB_CERTIFICATE_BLOB:
279  return "BB_CERTIFICATE_BLOB";
280  case BB_ERROR_BLOB:
281  return "BB_ERROR_BLOB";
282  case BB_ENCRYPTED_DATA_BLOB:
283  return "BB_ENCRYPTED_DATA_BLOB";
284  case BB_KEY_EXCHG_ALG_BLOB:
285  return "BB_KEY_EXCHG_ALG_BLOB";
286  case BB_SCOPE_BLOB:
287  return "BB_SCOPE_BLOB";
288  case BB_CLIENT_USER_NAME_BLOB:
289  return "BB_CLIENT_USER_NAME_BLOB";
290  case BB_CLIENT_MACHINE_NAME_BLOB:
291  return "BB_CLIENT_MACHINE_NAME_BLOB";
292  default:
293  return "BB_UNKNOWN";
294  }
295 }
296 static wStream* license_send_stream_init(rdpLicense* license);
297 
298 static void license_generate_randoms(rdpLicense* license);
299 static BOOL license_generate_keys(rdpLicense* license);
300 static BOOL license_generate_hwid(rdpLicense* license);
301 static BOOL license_encrypt_premaster_secret(rdpLicense* license);
302 
303 static LICENSE_PRODUCT_INFO* license_new_product_info(void);
304 static void license_free_product_info(LICENSE_PRODUCT_INFO* productInfo);
305 static BOOL license_read_product_info(wStream* s, LICENSE_PRODUCT_INFO* productInfo);
306 
307 static LICENSE_BLOB* license_new_binary_blob(UINT16 type);
308 static void license_free_binary_blob(LICENSE_BLOB* blob);
309 static BOOL license_read_binary_blob_data(LICENSE_BLOB* blob, UINT16 type, const void* data,
310  size_t length);
311 static BOOL license_read_binary_blob(wStream* s, LICENSE_BLOB* blob);
312 static BOOL license_write_binary_blob(wStream* s, const LICENSE_BLOB* blob);
313 
314 static SCOPE_LIST* license_new_scope_list(void);
315 static BOOL license_scope_list_resize(SCOPE_LIST* scopeList, UINT32 count);
316 static void license_free_scope_list(SCOPE_LIST* scopeList);
317 static BOOL license_read_scope_list(wStream* s, SCOPE_LIST* scopeList);
318 static BOOL license_write_scope_list(wStream* s, const SCOPE_LIST* scopeList);
319 
320 static BOOL license_read_license_request_packet(rdpLicense* license, wStream* s);
321 static BOOL license_write_license_request_packet(const rdpLicense* license, wStream* s);
322 
323 static BOOL license_read_platform_challenge_packet(rdpLicense* license, wStream* s);
324 static BOOL license_send_platform_challenge_packet(rdpLicense* license);
325 static BOOL license_read_new_or_upgrade_license_packet(rdpLicense* license, wStream* s);
326 static BOOL license_read_error_alert_packet(rdpLicense* license, wStream* s);
327 
328 static BOOL license_write_new_license_request_packet(const rdpLicense* license, wStream* s);
329 static BOOL license_read_new_license_request_packet(rdpLicense* license, wStream* s);
330 static BOOL license_answer_license_request(rdpLicense* license);
331 
332 static BOOL license_send_platform_challenge_response(rdpLicense* license);
333 static BOOL license_read_platform_challenge_response(rdpLicense* license, wStream* s);
334 
335 static BOOL license_read_client_platform_challenge_response(rdpLicense* license, wStream* s);
336 static BOOL license_write_client_platform_challenge_response(rdpLicense* license, wStream* s);
337 
338 static BOOL license_read_server_upgrade_license(rdpLicense* license, wStream* s);
339 static BOOL license_write_server_upgrade_license(const rdpLicense* license, wStream* s);
340 
341 static BOOL license_send_license_info(rdpLicense* license, const LICENSE_BLOB* calBlob,
342  const BYTE* signature, size_t signature_length);
343 static BOOL license_read_license_info(rdpLicense* license, wStream* s);
344 static state_run_t license_client_recv(rdpLicense* license, wStream* s);
345 static state_run_t license_server_recv(rdpLicense* license, wStream* s);
346 
347 #define PLATFORMID (CLIENT_OS_ID_WINNT_POST_52 | CLIENT_IMAGE_ID_MICROSOFT)
348 
349 #ifdef WITH_DEBUG_LICENSE
350 
351 static const char* error_codes[] = { "ERR_UNKNOWN",
352  "ERR_INVALID_SERVER_CERTIFICATE",
353  "ERR_NO_LICENSE",
354  "ERR_INVALID_MAC",
355  "ERR_INVALID_SCOPE",
356  "ERR_UNKNOWN",
357  "ERR_NO_LICENSE_SERVER",
358  "STATUS_VALID_CLIENT",
359  "ERR_INVALID_CLIENT",
360  "ERR_UNKNOWN",
361  "ERR_UNKNOWN",
362  "ERR_INVALID_PRODUCT_ID",
363  "ERR_INVALID_MESSAGE_LENGTH" };
364 
365 static const char* state_transitions[] = { "ST_UNKNOWN", "ST_TOTAL_ABORT", "ST_NO_TRANSITION",
366  "ST_RESET_PHASE_TO_START", "ST_RESEND_LAST_MESSAGE" };
367 
368 static void license_print_product_info(const LICENSE_PRODUCT_INFO* productInfo)
369 {
370  char* CompanyName = NULL;
371  char* ProductId = NULL;
372 
373  WINPR_ASSERT(productInfo);
374  WINPR_ASSERT(productInfo->pbCompanyName);
375  WINPR_ASSERT(productInfo->pbProductId);
376 
377  CompanyName = ConvertWCharNToUtf8Alloc((const WCHAR*)productInfo->pbCompanyName,
378  productInfo->cbCompanyName / sizeof(WCHAR), NULL);
379  ProductId = ConvertWCharNToUtf8Alloc((const WCHAR*)productInfo->pbProductId,
380  productInfo->cbProductId / sizeof(WCHAR), NULL);
381  WLog_INFO(TAG, "ProductInfo:");
382  WLog_INFO(TAG, "\tdwVersion: 0x%08" PRIX32 "", productInfo->dwVersion);
383  WLog_INFO(TAG, "\tCompanyName: %s", CompanyName);
384  WLog_INFO(TAG, "\tProductId: %s", ProductId);
385  free(CompanyName);
386  free(ProductId);
387 }
388 
389 static void license_print_scope_list(const SCOPE_LIST* scopeList)
390 {
391  WINPR_ASSERT(scopeList);
392 
393  WLog_INFO(TAG, "ScopeList (%" PRIu32 "):", scopeList->count);
394 
395  for (UINT32 index = 0; index < scopeList->count; index++)
396  {
397  const LICENSE_BLOB* scope = NULL;
398 
399  WINPR_ASSERT(scopeList->array);
400  scope = scopeList->array[index];
401  WINPR_ASSERT(scope);
402 
403  WLog_INFO(TAG, "\t%s", (const char*)scope->data);
404  }
405 }
406 #endif
407 
408 static const char licenseStore[] = "licenses";
409 
410 static BOOL license_ensure_state(rdpLicense* license, LICENSE_STATE state, UINT32 msg)
411 {
412  const LICENSE_STATE cstate = license_get_state(license);
413 
414  WINPR_ASSERT(license);
415 
416  if (cstate != state)
417  {
418  const char* scstate = license_get_state_string(cstate);
419  const char* sstate = license_get_state_string(state);
420  const char* where = license_request_type_string(msg);
421 
422  WLog_WARN(TAG, "Received [%s], but found invalid licensing state %s, expected %s", where,
423  scstate, sstate);
424  return FALSE;
425  }
426  return TRUE;
427 }
428 
429 state_run_t license_recv(rdpLicense* license, wStream* s)
430 {
431  WINPR_ASSERT(license);
432  WINPR_ASSERT(license->rdp);
433  WINPR_ASSERT(license->rdp->settings);
434 
435  if (freerdp_settings_get_bool(license->rdp->settings, FreeRDP_ServerMode))
436  return license_server_recv(license, s);
437  else
438  return license_client_recv(license, s);
439 }
440 
441 static BOOL license_check_stream_length(wStream* s, SSIZE_T expect, const char* where)
442 {
443  const size_t remain = Stream_GetRemainingLength(s);
444 
445  WINPR_ASSERT(where);
446 
447  if (expect < 0)
448  {
449  WLog_WARN(TAG, "invalid %s, expected value %" PRIdz " invalid", where, expect);
450  return FALSE;
451  }
452  if (remain < (size_t)expect)
453  {
454  WLog_WARN(TAG, "short %s, expected %" PRIdz " bytes, got %" PRIuz, where, expect, remain);
455  return FALSE;
456  }
457  return TRUE;
458 }
459 
460 static BOOL license_check_stream_capacity(wStream* s, size_t expect, const char* where)
461 {
462  WINPR_ASSERT(where);
463 
464  if (!Stream_CheckAndLogRequiredCapacityEx(TAG, WLOG_WARN, s, expect, 1, "%s(%s:%" PRIuz ") %s",
465  __func__, __FILE__, (size_t)__LINE__, where))
466  return FALSE;
467 
468  return TRUE;
469 }
470 
471 static BOOL computeCalHash(const char* hostname, char* hashStr, size_t len)
472 {
473  WINPR_DIGEST_CTX* sha1 = NULL;
474  BOOL ret = FALSE;
475  BYTE hash[20] = { 0 };
476 
477  WINPR_ASSERT(hostname);
478  WINPR_ASSERT(hashStr);
479 
480  if (len < 2 * sizeof(hash) + 1)
481  return FALSE;
482 
483  if (!(sha1 = winpr_Digest_New()))
484  goto out;
485  if (!winpr_Digest_Init(sha1, WINPR_MD_SHA1))
486  goto out;
487  if (!winpr_Digest_Update(sha1, (const BYTE*)hostname, strlen(hostname)))
488  goto out;
489  if (!winpr_Digest_Final(sha1, hash, sizeof(hash)))
490  goto out;
491 
492  for (size_t i = 0; i < sizeof(hash); i++, hashStr += 2)
493  (void)sprintf_s(hashStr, 3, "%.2x", hash[i]);
494 
495  ret = TRUE;
496 out:
497  if (!ret)
498  WLog_ERR(TAG, "failed to generate SHA1 of hostname '%s'", hostname);
499  winpr_Digest_Free(sha1);
500  return ret;
501 }
502 
503 static BOOL saveCal(const rdpSettings* settings, const BYTE* data, size_t length,
504  const char* hostname)
505 {
506  char hash[41] = { 0 };
507  FILE* fp = NULL;
508  char* licenseStorePath = NULL;
509  char filename[MAX_PATH] = { 0 };
510  char filenameNew[MAX_PATH] = { 0 };
511  char* filepath = NULL;
512  char* filepathNew = NULL;
513 
514  size_t written = 0;
515  BOOL ret = FALSE;
516  const char* path = freerdp_settings_get_string(settings, FreeRDP_ConfigPath);
517 
518  WINPR_ASSERT(path);
519  WINPR_ASSERT(data || (length == 0));
520  WINPR_ASSERT(hostname);
521 
522  if (!winpr_PathFileExists(path))
523  {
524  if (!winpr_PathMakePath(path, 0))
525  {
526  WLog_ERR(TAG, "error creating directory '%s'", path);
527  goto out;
528  }
529  WLog_INFO(TAG, "creating directory %s", path);
530  }
531 
532  if (!(licenseStorePath = GetCombinedPath(path, licenseStore)))
533  {
534  WLog_ERR(TAG, "Failed to get license store path from '%s' + '%s'", path, licenseStore);
535  goto out;
536  }
537 
538  if (!winpr_PathFileExists(licenseStorePath))
539  {
540  if (!winpr_PathMakePath(licenseStorePath, 0))
541  {
542  WLog_ERR(TAG, "error creating directory '%s'", licenseStorePath);
543  goto out;
544  }
545  WLog_INFO(TAG, "creating directory %s", licenseStorePath);
546  }
547 
548  if (!computeCalHash(hostname, hash, sizeof(hash)))
549  goto out;
550  (void)sprintf_s(filename, sizeof(filename) - 1, "%s.cal", hash);
551  (void)sprintf_s(filenameNew, sizeof(filenameNew) - 1, "%s.cal.new", hash);
552 
553  if (!(filepath = GetCombinedPath(licenseStorePath, filename)))
554  {
555  WLog_ERR(TAG, "Failed to get license file path from '%s' + '%s'", path, filename);
556  goto out;
557  }
558 
559  if (!(filepathNew = GetCombinedPath(licenseStorePath, filenameNew)))
560  {
561  WLog_ERR(TAG, "Failed to get license new file path from '%s' + '%s'", path, filenameNew);
562  goto out;
563  }
564 
565  fp = winpr_fopen(filepathNew, "wb");
566  if (!fp)
567  {
568  WLog_ERR(TAG, "Failed to open license file '%s'", filepathNew);
569  goto out;
570  }
571 
572  written = fwrite(data, length, 1, fp);
573  (void)fclose(fp);
574 
575  if (written != 1)
576  {
577  WLog_ERR(TAG, "Failed to write to license file '%s'", filepathNew);
578  winpr_DeleteFile(filepathNew);
579  goto out;
580  }
581 
582  ret = winpr_MoveFileEx(filepathNew, filepath, MOVEFILE_REPLACE_EXISTING);
583  if (!ret)
584  WLog_ERR(TAG, "Failed to move license file '%s' to '%s'", filepathNew, filepath);
585 
586 out:
587  free(filepathNew);
588  free(filepath);
589  free(licenseStorePath);
590  return ret;
591 }
592 
593 static BYTE* loadCalFile(const rdpSettings* settings, const char* hostname, size_t* dataLen)
594 {
595  char* licenseStorePath = NULL;
596  char* calPath = NULL;
597  char calFilename[MAX_PATH] = { 0 };
598  char hash[41] = { 0 };
599  INT64 length = 0;
600  size_t status = 0;
601  FILE* fp = NULL;
602  BYTE* ret = NULL;
603 
604  WINPR_ASSERT(settings);
605  WINPR_ASSERT(hostname);
606  WINPR_ASSERT(dataLen);
607 
608  if (!computeCalHash(hostname, hash, sizeof(hash)))
609  {
610  WLog_ERR(TAG, "loadCalFile: unable to compute hostname hash");
611  return NULL;
612  }
613 
614  (void)sprintf_s(calFilename, sizeof(calFilename) - 1, "%s.cal", hash);
615 
616  if (!(licenseStorePath = GetCombinedPath(
617  freerdp_settings_get_string(settings, FreeRDP_ConfigPath), licenseStore)))
618  return NULL;
619 
620  if (!(calPath = GetCombinedPath(licenseStorePath, calFilename)))
621  goto error_path;
622 
623  fp = winpr_fopen(calPath, "rb");
624  if (!fp)
625  goto error_open;
626 
627  if (_fseeki64(fp, 0, SEEK_END) != 0)
628  goto error_malloc;
629  length = _ftelli64(fp);
630  if (_fseeki64(fp, 0, SEEK_SET) != 0)
631  goto error_malloc;
632  if (length < 0)
633  goto error_malloc;
634 
635  ret = (BYTE*)malloc((size_t)length);
636  if (!ret)
637  goto error_malloc;
638 
639  status = fread(ret, (size_t)length, 1, fp);
640  if (status == 0)
641  goto error_read;
642 
643  *dataLen = (size_t)length;
644 
645  (void)fclose(fp);
646  free(calPath);
647  free(licenseStorePath);
648  return ret;
649 
650 error_read:
651  free(ret);
652 error_malloc:
653  fclose(fp);
654 error_open:
655  free(calPath);
656 error_path:
657  free(licenseStorePath);
658  return NULL;
659 }
660 
671 static BOOL license_read_preamble(wStream* s, BYTE* bMsgType, BYTE* flags, UINT16* wMsgSize)
672 {
673  WINPR_ASSERT(bMsgType);
674  WINPR_ASSERT(flags);
675  WINPR_ASSERT(wMsgSize);
676 
677  /* preamble (4 bytes) */
678  if (!license_check_stream_length(s, 4, "license preamble"))
679  return FALSE;
680 
681  Stream_Read_UINT8(s, *bMsgType); /* bMsgType (1 byte) */
682  Stream_Read_UINT8(s, *flags); /* flags (1 byte) */
683  Stream_Read_UINT16(s, *wMsgSize); /* wMsgSize (2 bytes) */
684  return license_check_stream_length(s, *wMsgSize - 4ll, "license preamble::wMsgSize");
685 }
686 
697 static BOOL license_write_preamble(wStream* s, BYTE bMsgType, BYTE flags, UINT16 wMsgSize)
698 {
699  if (!Stream_EnsureRemainingCapacity(s, 4))
700  return FALSE;
701 
702  /* preamble (4 bytes) */
703  Stream_Write_UINT8(s, bMsgType); /* bMsgType (1 byte) */
704  Stream_Write_UINT8(s, flags); /* flags (1 byte) */
705  Stream_Write_UINT16(s, wMsgSize); /* wMsgSize (2 bytes) */
706  return TRUE;
707 }
708 
717 wStream* license_send_stream_init(rdpLicense* license)
718 {
719  WINPR_ASSERT(license);
720  WINPR_ASSERT(license->rdp);
721 
722  const BOOL do_crypt = license->rdp->do_crypt;
723 
724  license->rdp->sec_flags = SEC_LICENSE_PKT;
725 
726  /*
727  * Encryption of licensing packets is optional even if the rdp security
728  * layer is used. If the peer has not indicated that it is capable of
729  * processing encrypted licensing packets (rdp->do_crypt_license) we turn
730  * off encryption (via rdp->do_crypt) before initializing the rdp stream
731  * and re-enable it afterwards.
732  */
733 
734  if (do_crypt)
735  {
736  license->rdp->sec_flags |= SEC_LICENSE_ENCRYPT_CS;
737  license->rdp->do_crypt = license->rdp->do_crypt_license;
738  }
739 
740  wStream* s = rdp_send_stream_init(license->rdp);
741  if (!s)
742  return NULL;
743 
744  license->rdp->do_crypt = do_crypt;
745  license->PacketHeaderLength = (UINT16)Stream_GetPosition(s);
746  if (!Stream_SafeSeek(s, LICENSE_PREAMBLE_LENGTH))
747  goto fail;
748  return s;
749 
750 fail:
751  Stream_Release(s);
752  return NULL;
753 }
754 
762 static BOOL license_send(rdpLicense* license, wStream* s, BYTE type)
763 {
764  WINPR_ASSERT(license);
765  WINPR_ASSERT(license->rdp);
766 
767  rdpRdp* rdp = license->rdp;
768  WINPR_ASSERT(rdp->settings);
769 
770  DEBUG_LICENSE("Sending %s Packet", license_request_type_string(type));
771  const size_t length = Stream_GetPosition(s);
772  WINPR_ASSERT(length >= license->PacketHeaderLength);
773  WINPR_ASSERT(length <= UINT16_MAX + license->PacketHeaderLength);
774 
775  const UINT16 wMsgSize = (UINT16)(length - license->PacketHeaderLength);
776  Stream_SetPosition(s, license->PacketHeaderLength);
777  BYTE flags = PREAMBLE_VERSION_3_0;
778 
784  if (!rdp->settings->ServerMode)
785  flags |= EXTENDED_ERROR_MSG_SUPPORTED;
786 
787  if (!license_write_preamble(s, type, flags, wMsgSize))
788  {
789  Stream_Release(s);
790  return FALSE;
791  }
792 
793 #ifdef WITH_DEBUG_LICENSE
794  WLog_DBG(TAG, "Sending %s Packet, length %" PRIu16 "", license_request_type_string(type),
795  wMsgSize);
796  winpr_HexDump(TAG, WLOG_DEBUG, Stream_PointerAs(s, char) - LICENSE_PREAMBLE_LENGTH, wMsgSize);
797 #endif
798  Stream_SetPosition(s, length);
799  const BOOL ret = rdp_send(rdp, s, MCS_GLOBAL_CHANNEL_ID);
800  rdp->sec_flags = 0;
801  return ret;
802 }
803 
804 BOOL license_read_server_upgrade_license(rdpLicense* license, wStream* s)
805 {
806  WINPR_ASSERT(license);
807 
808  if (!license_read_binary_blob(s, license->EncryptedLicenseInfo))
809  return FALSE;
810  if (!license_check_stream_length(s, sizeof(license->MACData),
811  "SERVER_UPGRADE_LICENSE::MACData"))
812  return FALSE;
813  Stream_Read(s, license->MACData, sizeof(license->MACData));
814  return TRUE;
815 }
816 
817 BOOL license_write_server_upgrade_license(const rdpLicense* license, wStream* s)
818 {
819  WINPR_ASSERT(license);
820 
821  if (!license_write_binary_blob(s, license->EncryptedLicenseInfo))
822  return FALSE;
823  if (!license_check_stream_capacity(s, sizeof(license->MACData),
824  "SERVER_UPGRADE_LICENSE::MACData"))
825  return FALSE;
826  Stream_Write(s, license->MACData, sizeof(license->MACData));
827  return TRUE;
828 }
829 
830 static BOOL license_server_send_new_or_upgrade_license(rdpLicense* license, BOOL upgrade)
831 {
832  wStream* s = license_send_stream_init(license);
833  const BYTE type = upgrade ? UPGRADE_LICENSE : NEW_LICENSE;
834 
835  if (!s)
836  return FALSE;
837 
838  if (!license_write_server_upgrade_license(license, s))
839  goto fail;
840 
841  return license_send(license, s, type);
842 
843 fail:
844  Stream_Release(s);
845  return FALSE;
846 }
847 
856 state_run_t license_client_recv(rdpLicense* license, wStream* s)
857 {
858  BYTE flags = 0;
859  BYTE bMsgType = 0;
860  UINT16 wMsgSize = 0;
861  const size_t length = Stream_GetRemainingLength(s);
862 
863  WINPR_ASSERT(license);
864 
865  if (!license_read_preamble(s, &bMsgType, &flags, &wMsgSize)) /* preamble (4 bytes) */
866  return STATE_RUN_FAILED;
867 
868  DEBUG_LICENSE("Receiving %s Packet", license_request_type_string(bMsgType));
869 
870  switch (bMsgType)
871  {
872  case LICENSE_REQUEST:
873  /* Client does not require configuration, so skip this state */
874  if (license_get_state(license) == LICENSE_STATE_INITIAL)
875  license_set_state(license, LICENSE_STATE_CONFIGURED);
876 
877  if (!license_ensure_state(license, LICENSE_STATE_CONFIGURED, bMsgType))
878  return STATE_RUN_FAILED;
879 
880  if (!license_read_license_request_packet(license, s))
881  return STATE_RUN_FAILED;
882 
883  if (!license_answer_license_request(license))
884  return STATE_RUN_FAILED;
885 
886  license_set_state(license, LICENSE_STATE_NEW_REQUEST);
887  break;
888 
889  case PLATFORM_CHALLENGE:
890  if (!license_ensure_state(license, LICENSE_STATE_NEW_REQUEST, bMsgType))
891  return STATE_RUN_FAILED;
892 
893  if (!license_read_platform_challenge_packet(license, s))
894  return STATE_RUN_FAILED;
895 
896  if (!license_send_platform_challenge_response(license))
897  return STATE_RUN_FAILED;
898  license_set_state(license, LICENSE_STATE_PLATFORM_CHALLENGE_RESPONSE);
899  break;
900 
901  case NEW_LICENSE:
902  case UPGRADE_LICENSE:
903  if (!license_ensure_state(license, LICENSE_STATE_PLATFORM_CHALLENGE_RESPONSE, bMsgType))
904  return STATE_RUN_FAILED;
905  if (!license_read_new_or_upgrade_license_packet(license, s))
906  return STATE_RUN_FAILED;
907  break;
908 
909  case ERROR_ALERT:
910  if (!license_read_error_alert_packet(license, s))
911  return STATE_RUN_FAILED;
912  break;
913 
914  default:
915  WLog_ERR(TAG, "invalid bMsgType:%" PRIu8 "", bMsgType);
916  return STATE_RUN_FAILED;
917  }
918 
919  if (!tpkt_ensure_stream_consumed(s, length))
920  return STATE_RUN_FAILED;
921  return STATE_RUN_SUCCESS;
922 }
923 
924 state_run_t license_server_recv(rdpLicense* license, wStream* s)
925 {
926  state_run_t rc = STATE_RUN_FAILED;
927  BYTE flags = 0;
928  BYTE bMsgType = 0;
929  UINT16 wMsgSize = 0;
930  const size_t length = Stream_GetRemainingLength(s);
931 
932  WINPR_ASSERT(license);
933 
934  if (!license_read_preamble(s, &bMsgType, &flags, &wMsgSize)) /* preamble (4 bytes) */
935  goto fail;
936 
937  DEBUG_LICENSE("Receiving %s Packet", license_request_type_string(bMsgType));
938 
939  switch (bMsgType)
940  {
941  case NEW_LICENSE_REQUEST:
942  if (!license_ensure_state(license, LICENSE_STATE_REQUEST, bMsgType))
943  goto fail;
944  if (!license_read_new_license_request_packet(license, s))
945  goto fail;
946  // TODO: Validate if client is allowed
947  if (!license_send_error_alert(license, ERR_INVALID_MAC, ST_TOTAL_ABORT,
948  license->ErrorInfo))
949  goto fail;
950  if (!license_send_platform_challenge_packet(license))
951  goto fail;
952  license->update = FALSE;
953  if (!license_set_state(license, LICENSE_STATE_PLATFORM_CHALLENGE))
954  goto fail;
955  break;
956  case LICENSE_INFO:
957  if (!license_ensure_state(license, LICENSE_STATE_REQUEST, bMsgType))
958  goto fail;
959  if (!license_read_license_info(license, s))
960  goto fail;
961  // TODO: Validate license info
962  if (!license_send_platform_challenge_packet(license))
963  goto fail;
964  if (!license_set_state(license, LICENSE_STATE_PLATFORM_CHALLENGE))
965  goto fail;
966  license->update = TRUE;
967  break;
968 
969  case PLATFORM_CHALLENGE_RESPONSE:
970  if (!license_ensure_state(license, LICENSE_STATE_PLATFORM_CHALLENGE, bMsgType))
971  goto fail;
972  if (!license_read_client_platform_challenge_response(license, s))
973  goto fail;
974 
975  // TODO: validate challenge response
976  if (FALSE)
977  {
978  if (license_send_error_alert(license, ERR_INVALID_CLIENT, ST_TOTAL_ABORT,
979  license->ErrorInfo))
980  goto fail;
981  }
982  else
983  {
984  if (!license_server_send_new_or_upgrade_license(license, license->update))
985  goto fail;
986 
987  license->type = LICENSE_TYPE_ISSUED;
988  license_set_state(license, LICENSE_STATE_COMPLETED);
989 
990  rc = STATE_RUN_CONTINUE; /* License issued, switch state */
991  }
992  break;
993 
994  case ERROR_ALERT:
995  if (!license_read_error_alert_packet(license, s))
996  goto fail;
997  break;
998 
999  default:
1000  WLog_ERR(TAG, "invalid bMsgType:%" PRIu8 "", bMsgType);
1001  goto fail;
1002  }
1003 
1004  if (!tpkt_ensure_stream_consumed(s, length))
1005  goto fail;
1006 
1007  if (!state_run_success(rc))
1008  rc = STATE_RUN_SUCCESS;
1009 
1010 fail:
1011  if (state_run_failed(rc))
1012  {
1013  if (flags & EXTENDED_ERROR_MSG_SUPPORTED)
1014  license_send_error_alert(license, ERR_INVALID_CLIENT, ST_TOTAL_ABORT, NULL);
1015  license_set_state(license, LICENSE_STATE_ABORTED);
1016  }
1017 
1018  return rc;
1019 }
1020 
1021 void license_generate_randoms(rdpLicense* license)
1022 {
1023  WINPR_ASSERT(license);
1024 
1025 #ifdef LICENSE_NULL_CLIENT_RANDOM
1026  ZeroMemory(license->ClientRandom, sizeof(license->ClientRandom)); /* ClientRandom */
1027 #else
1028  winpr_RAND(license->ClientRandom, sizeof(license->ClientRandom)); /* ClientRandom */
1029 #endif
1030 
1031  winpr_RAND(license->ServerRandom, sizeof(license->ServerRandom)); /* ServerRandom */
1032 
1033 #ifdef LICENSE_NULL_PREMASTER_SECRET
1034  ZeroMemory(license->PremasterSecret, sizeof(license->PremasterSecret)); /* PremasterSecret */
1035 #else
1036  winpr_RAND(license->PremasterSecret, sizeof(license->PremasterSecret)); /* PremasterSecret */
1037 #endif
1038 }
1039 
1045 static BOOL license_generate_keys(rdpLicense* license)
1046 {
1047  WINPR_ASSERT(license);
1048 
1049  if (
1050  /* MasterSecret */
1051  !security_master_secret(license->PremasterSecret, sizeof(license->PremasterSecret),
1052  license->ClientRandom, sizeof(license->ClientRandom),
1053  license->ServerRandom, sizeof(license->ServerRandom),
1054  license->MasterSecret, sizeof(license->MasterSecret)) ||
1055  /* SessionKeyBlob */
1056  !security_session_key_blob(license->MasterSecret, sizeof(license->MasterSecret),
1057  license->ClientRandom, sizeof(license->ClientRandom),
1058  license->ServerRandom, sizeof(license->ServerRandom),
1059  license->SessionKeyBlob, sizeof(license->SessionKeyBlob)))
1060  {
1061  return FALSE;
1062  }
1063  security_mac_salt_key(license->SessionKeyBlob, sizeof(license->SessionKeyBlob),
1064  license->ClientRandom, sizeof(license->ClientRandom),
1065  license->ServerRandom, sizeof(license->ServerRandom), license->MacSaltKey,
1066  sizeof(license->MacSaltKey)); /* MacSaltKey */
1067  const BOOL ret = security_licensing_encryption_key(
1068  license->SessionKeyBlob, sizeof(license->SessionKeyBlob), license->ClientRandom,
1069  sizeof(license->ClientRandom), license->ServerRandom, sizeof(license->ServerRandom),
1070  license->LicensingEncryptionKey,
1071  sizeof(license->LicensingEncryptionKey)); /* LicensingEncryptionKey */
1072 
1073 #ifdef WITH_DEBUG_LICENSE
1074  WLog_DBG(TAG, "ClientRandom:");
1075  winpr_HexDump(TAG, WLOG_DEBUG, license->ClientRandom, sizeof(license->ClientRandom));
1076  WLog_DBG(TAG, "ServerRandom:");
1077  winpr_HexDump(TAG, WLOG_DEBUG, license->ServerRandom, sizeof(license->ServerRandom));
1078  WLog_DBG(TAG, "PremasterSecret:");
1079  winpr_HexDump(TAG, WLOG_DEBUG, license->PremasterSecret, sizeof(license->PremasterSecret));
1080  WLog_DBG(TAG, "MasterSecret:");
1081  winpr_HexDump(TAG, WLOG_DEBUG, license->MasterSecret, sizeof(license->MasterSecret));
1082  WLog_DBG(TAG, "SessionKeyBlob:");
1083  winpr_HexDump(TAG, WLOG_DEBUG, license->SessionKeyBlob, sizeof(license->SessionKeyBlob));
1084  WLog_DBG(TAG, "MacSaltKey:");
1085  winpr_HexDump(TAG, WLOG_DEBUG, license->MacSaltKey, sizeof(license->MacSaltKey));
1086  WLog_DBG(TAG, "LicensingEncryptionKey:");
1087  winpr_HexDump(TAG, WLOG_DEBUG, license->LicensingEncryptionKey,
1088  sizeof(license->LicensingEncryptionKey));
1089 #endif
1090  return ret;
1091 }
1092 
1098 BOOL license_generate_hwid(rdpLicense* license)
1099 {
1100  const BYTE* hashTarget = NULL;
1101  size_t targetLen = 0;
1102  BYTE macAddress[6] = { 0 };
1103 
1104  WINPR_ASSERT(license);
1105  WINPR_ASSERT(license->rdp);
1106  WINPR_ASSERT(license->rdp->settings);
1107 
1108  ZeroMemory(license->HardwareId, sizeof(license->HardwareId));
1109 
1110  if (license->rdp->settings->OldLicenseBehaviour)
1111  {
1112  hashTarget = macAddress;
1113  targetLen = sizeof(macAddress);
1114  }
1115  else
1116  {
1117  wStream buffer = { 0 };
1118  const char* hostname = license->rdp->settings->ClientHostname;
1119  wStream* s = Stream_StaticInit(&buffer, license->HardwareId, 4);
1120  Stream_Write_UINT32(s, license->PlatformId);
1121 
1122  hashTarget = (const BYTE*)hostname;
1123  targetLen = hostname ? strlen(hostname) : 0;
1124  }
1125 
1126  /* Allow FIPS override for use of MD5 here, really this does not have to be MD5 as we are just
1127  * taking a MD5 hash of the 6 bytes of 0's(macAddress) */
1128  /* and filling in the Data1-Data4 fields of the CLIENT_HARDWARE_ID structure(from MS-RDPELE
1129  * section 2.2.2.3.1). This is for RDP licensing packets */
1130  /* which will already be encrypted under FIPS, so the use of MD5 here is not for sensitive data
1131  * protection. */
1132  return winpr_Digest_Allow_FIPS(WINPR_MD_MD5, hashTarget, targetLen,
1133  &license->HardwareId[HWID_PLATFORM_ID_LENGTH],
1134  WINPR_MD5_DIGEST_LENGTH);
1135 }
1136 
1137 static BOOL license_get_server_rsa_public_key(rdpLicense* license)
1138 {
1139  rdpSettings* settings = NULL;
1140 
1141  WINPR_ASSERT(license);
1142  WINPR_ASSERT(license->certificate);
1143  WINPR_ASSERT(license->rdp);
1144 
1145  settings = license->rdp->settings;
1146  WINPR_ASSERT(settings);
1147 
1148  if (license->ServerCertificate->length < 1)
1149  {
1150  if (!freerdp_certificate_read_server_cert(license->certificate, settings->ServerCertificate,
1151  settings->ServerCertificateLength))
1152  return FALSE;
1153  }
1154 
1155  return TRUE;
1156 }
1157 
1158 BOOL license_encrypt_premaster_secret(rdpLicense* license)
1159 {
1160  WINPR_ASSERT(license);
1161  WINPR_ASSERT(license->certificate);
1162 
1163  if (!license_get_server_rsa_public_key(license))
1164  return FALSE;
1165 
1166  WINPR_ASSERT(license->EncryptedPremasterSecret);
1167 
1168  const rdpCertInfo* info = freerdp_certificate_get_info(license->certificate);
1169  if (!info)
1170  {
1171  WLog_ERR(TAG, "info=%p, license->certificate=%p", info, license->certificate);
1172  return FALSE;
1173  }
1174 
1175 #ifdef WITH_DEBUG_LICENSE
1176  WLog_DBG(TAG, "Modulus (%" PRIu32 " bits):", info->ModulusLength * 8);
1177  winpr_HexDump(TAG, WLOG_DEBUG, info->Modulus, info->ModulusLength);
1178  WLog_DBG(TAG, "Exponent:");
1179  winpr_HexDump(TAG, WLOG_DEBUG, info->exponent, sizeof(info->exponent));
1180 #endif
1181 
1182  BYTE* EncryptedPremasterSecret = (BYTE*)calloc(1, info->ModulusLength);
1183  if (!EncryptedPremasterSecret)
1184  {
1185  WLog_ERR(TAG, "EncryptedPremasterSecret=%p, info->ModulusLength=%" PRIu32,
1186  EncryptedPremasterSecret, info->ModulusLength);
1187  return FALSE;
1188  }
1189 
1190  license->EncryptedPremasterSecret->type = BB_RANDOM_BLOB;
1191  license->EncryptedPremasterSecret->length = sizeof(license->PremasterSecret);
1192 #ifndef LICENSE_NULL_PREMASTER_SECRET
1193  {
1194  const SSIZE_T length =
1195  crypto_rsa_public_encrypt(license->PremasterSecret, sizeof(license->PremasterSecret),
1196  info, EncryptedPremasterSecret, info->ModulusLength);
1197  if ((length < 0) || (length > UINT16_MAX))
1198  {
1199  WLog_ERR(TAG, "RSA public encrypt length=%" PRIdz " < 0 || > %" PRIu16, length,
1200  UINT16_MAX);
1201  return FALSE;
1202  }
1203  license->EncryptedPremasterSecret->length = (UINT16)length;
1204  }
1205 #endif
1206  license->EncryptedPremasterSecret->data = EncryptedPremasterSecret;
1207  return TRUE;
1208 }
1209 
1210 static BOOL license_rc4_with_licenseKey(const rdpLicense* license, const BYTE* input, size_t len,
1211  LICENSE_BLOB* target)
1212 {
1213  WINPR_ASSERT(license);
1214  WINPR_ASSERT(input || (len == 0));
1215  WINPR_ASSERT(target);
1216  WINPR_ASSERT(len <= UINT16_MAX);
1217 
1218  WINPR_RC4_CTX* rc4 = winpr_RC4_New_Allow_FIPS(license->LicensingEncryptionKey,
1219  sizeof(license->LicensingEncryptionKey));
1220  if (!rc4)
1221  {
1222  WLog_ERR(TAG, "Failed to allocate RC4");
1223  return FALSE;
1224  }
1225 
1226  BYTE* buffer = NULL;
1227  if (len > 0)
1228  buffer = realloc(target->data, len);
1229  if (!buffer)
1230  goto error_buffer;
1231 
1232  target->data = buffer;
1233  target->length = (UINT16)len;
1234 
1235  if (!winpr_RC4_Update(rc4, len, input, buffer))
1236  goto error_buffer;
1237 
1238  winpr_RC4_Free(rc4);
1239  return TRUE;
1240 
1241 error_buffer:
1242  WLog_ERR(TAG, "Failed to create/update RC4: len=%" PRIuz ", buffer=%p", len, buffer);
1243  winpr_RC4_Free(rc4);
1244  return FALSE;
1245 }
1246 
1257 static BOOL license_encrypt_and_MAC(rdpLicense* license, const BYTE* input, size_t len,
1258  LICENSE_BLOB* target, BYTE* mac, size_t mac_length)
1259 {
1260  WINPR_ASSERT(license);
1261  return license_rc4_with_licenseKey(license, input, len, target) &&
1262  security_mac_data(license->MacSaltKey, sizeof(license->MacSaltKey), input, len, mac,
1263  mac_length);
1264 }
1265 
1277 static BOOL license_decrypt_and_check_MAC(rdpLicense* license, const BYTE* input, size_t len,
1278  LICENSE_BLOB* target, const BYTE* packetMac)
1279 {
1280  BYTE macData[sizeof(license->MACData)] = { 0 };
1281 
1282  WINPR_ASSERT(license);
1283  WINPR_ASSERT(target);
1284 
1285  if (freerdp_settings_get_bool(license->rdp->settings, FreeRDP_TransportDumpReplay))
1286  {
1287  WLog_DBG(TAG, "TransportDumpReplay active, skipping...");
1288  return TRUE;
1289  }
1290 
1291  if (!license_rc4_with_licenseKey(license, input, len, target))
1292  return FALSE;
1293 
1294  if (!security_mac_data(license->MacSaltKey, sizeof(license->MacSaltKey), target->data, len,
1295  macData, sizeof(macData)))
1296  return FALSE;
1297 
1298  if (memcmp(packetMac, macData, sizeof(macData)) != 0)
1299  {
1300  WLog_ERR(TAG, "packetMac != expectedMac");
1301  return FALSE;
1302  }
1303  return TRUE;
1304 }
1305 
1313 BOOL license_read_product_info(wStream* s, LICENSE_PRODUCT_INFO* productInfo)
1314 {
1315  WINPR_ASSERT(productInfo);
1316 
1317  if (!license_check_stream_length(s, 8, "license product info::cbCompanyName"))
1318  return FALSE;
1319 
1320  Stream_Read_UINT32(s, productInfo->dwVersion); /* dwVersion (4 bytes) */
1321  Stream_Read_UINT32(s, productInfo->cbCompanyName); /* cbCompanyName (4 bytes) */
1322 
1323  /* Name must be >0, but there is no upper limit defined, use UINT32_MAX */
1324  if ((productInfo->cbCompanyName < 2) || (productInfo->cbCompanyName % 2 != 0))
1325  {
1326  WLog_WARN(TAG, "license product info invalid cbCompanyName %" PRIu32,
1327  productInfo->cbCompanyName);
1328  return FALSE;
1329  }
1330 
1331  if (!license_check_stream_length(s, productInfo->cbCompanyName,
1332  "license product info::CompanyName"))
1333  return FALSE;
1334 
1335  productInfo->pbProductId = NULL;
1336  productInfo->pbCompanyName = (BYTE*)malloc(productInfo->cbCompanyName);
1337  if (!productInfo->pbCompanyName)
1338  goto out_fail;
1339  Stream_Read(s, productInfo->pbCompanyName, productInfo->cbCompanyName);
1340 
1341  if (!license_check_stream_length(s, 4, "license product info::cbProductId"))
1342  goto out_fail;
1343 
1344  Stream_Read_UINT32(s, productInfo->cbProductId); /* cbProductId (4 bytes) */
1345 
1346  if ((productInfo->cbProductId < 2) || (productInfo->cbProductId % 2 != 0))
1347  {
1348  WLog_WARN(TAG, "license product info invalid cbProductId %" PRIu32,
1349  productInfo->cbProductId);
1350  goto out_fail;
1351  }
1352 
1353  if (!license_check_stream_length(s, productInfo->cbProductId,
1354  "license product info::ProductId"))
1355  goto out_fail;
1356 
1357  productInfo->pbProductId = (BYTE*)malloc(productInfo->cbProductId);
1358  if (!productInfo->pbProductId)
1359  goto out_fail;
1360  Stream_Read(s, productInfo->pbProductId, productInfo->cbProductId);
1361  return TRUE;
1362 
1363 out_fail:
1364  free(productInfo->pbCompanyName);
1365  free(productInfo->pbProductId);
1366  productInfo->pbCompanyName = NULL;
1367  productInfo->pbProductId = NULL;
1368  return FALSE;
1369 }
1370 
1371 static BOOL license_write_product_info(wStream* s, const LICENSE_PRODUCT_INFO* productInfo)
1372 {
1373  WINPR_ASSERT(productInfo);
1374 
1375  if (!license_check_stream_capacity(s, 8, "license product info::cbCompanyName"))
1376  return FALSE;
1377 
1378  Stream_Write_UINT32(s, productInfo->dwVersion); /* dwVersion (4 bytes) */
1379  Stream_Write_UINT32(s, productInfo->cbCompanyName); /* cbCompanyName (4 bytes) */
1380 
1381  /* Name must be >0, but there is no upper limit defined, use UINT32_MAX */
1382  if ((productInfo->cbCompanyName < 2) || (productInfo->cbCompanyName % 2 != 0) ||
1383  !productInfo->pbCompanyName)
1384  {
1385  WLog_WARN(TAG, "license product info invalid cbCompanyName %" PRIu32,
1386  productInfo->cbCompanyName);
1387  return FALSE;
1388  }
1389 
1390  if (!license_check_stream_capacity(s, productInfo->cbCompanyName,
1391  "license product info::CompanyName"))
1392  return FALSE;
1393 
1394  Stream_Write(s, productInfo->pbCompanyName, productInfo->cbCompanyName);
1395 
1396  if (!license_check_stream_capacity(s, 4, "license product info::cbProductId"))
1397  return FALSE;
1398 
1399  Stream_Write_UINT32(s, productInfo->cbProductId); /* cbProductId (4 bytes) */
1400 
1401  if ((productInfo->cbProductId < 2) || (productInfo->cbProductId % 2 != 0) ||
1402  !productInfo->pbProductId)
1403  {
1404  WLog_WARN(TAG, "license product info invalid cbProductId %" PRIu32,
1405  productInfo->cbProductId);
1406  return FALSE;
1407  }
1408 
1409  if (!license_check_stream_capacity(s, productInfo->cbProductId,
1410  "license product info::ProductId"))
1411  return FALSE;
1412 
1413  Stream_Write(s, productInfo->pbProductId, productInfo->cbProductId);
1414  return TRUE;
1415 }
1416 
1423 LICENSE_PRODUCT_INFO* license_new_product_info(void)
1424 {
1425  LICENSE_PRODUCT_INFO* productInfo =
1426  (LICENSE_PRODUCT_INFO*)calloc(1, sizeof(LICENSE_PRODUCT_INFO));
1427  if (!productInfo)
1428  return NULL;
1429  return productInfo;
1430 }
1431 
1438 void license_free_product_info(LICENSE_PRODUCT_INFO* productInfo)
1439 {
1440  if (productInfo)
1441  {
1442  free(productInfo->pbCompanyName);
1443  free(productInfo->pbProductId);
1444  free(productInfo);
1445  }
1446 }
1447 
1448 BOOL license_read_binary_blob_data(LICENSE_BLOB* blob, UINT16 wBlobType, const void* data,
1449  size_t length)
1450 {
1451  WINPR_ASSERT(blob);
1452  WINPR_ASSERT(length <= UINT16_MAX);
1453  WINPR_ASSERT(data || (length == 0));
1454 
1455  blob->length = (UINT16)length;
1456  free(blob->data);
1457  blob->data = NULL;
1458 
1459  if ((blob->type != wBlobType) && (blob->type != BB_ANY_BLOB))
1460  {
1461  WLog_ERR(TAG, "license binary blob::type expected %s, got %s",
1462  licencse_blob_type_string(wBlobType), licencse_blob_type_string(blob->type));
1463  }
1464 
1465  /*
1466  * Server can choose to not send data by setting length to 0.
1467  * If so, it may not bother to set the type, so shortcut the warning
1468  */
1469  if ((blob->type != BB_ANY_BLOB) && (blob->length == 0))
1470  {
1471  WLog_WARN(TAG, "license binary blob::type %s, length=0, skipping.",
1472  licencse_blob_type_string(blob->type));
1473  return TRUE;
1474  }
1475 
1476  blob->type = wBlobType;
1477  blob->data = NULL;
1478  if (blob->length > 0)
1479  blob->data = malloc(blob->length);
1480  if (!blob->data)
1481  {
1482  WLog_ERR(TAG, "license binary blob::length=%" PRIu16 ", blob::data=%p", blob->length,
1483  blob->data);
1484  return FALSE;
1485  }
1486  memcpy(blob->data, data, blob->length); /* blobData */
1487  return TRUE;
1488 }
1489 
1497 BOOL license_read_binary_blob(wStream* s, LICENSE_BLOB* blob)
1498 {
1499  UINT16 wBlobType = 0;
1500  UINT16 length = 0;
1501 
1502  WINPR_ASSERT(blob);
1503 
1504  if (!license_check_stream_length(s, 4, "license binary blob::type"))
1505  return FALSE;
1506 
1507  Stream_Read_UINT16(s, wBlobType); /* wBlobType (2 bytes) */
1508  Stream_Read_UINT16(s, length); /* wBlobLen (2 bytes) */
1509 
1510  if (!license_check_stream_length(s, length, "license binary blob::length"))
1511  return FALSE;
1512 
1513  if (!license_read_binary_blob_data(blob, wBlobType, Stream_Pointer(s), length))
1514  return FALSE;
1515 
1516  return Stream_SafeSeek(s, length);
1517 }
1518 
1526 BOOL license_write_binary_blob(wStream* s, const LICENSE_BLOB* blob)
1527 {
1528  WINPR_ASSERT(blob);
1529 
1530  if (!Stream_EnsureRemainingCapacity(s, blob->length + 4))
1531  return FALSE;
1532 
1533  Stream_Write_UINT16(s, blob->type); /* wBlobType (2 bytes) */
1534  Stream_Write_UINT16(s, blob->length); /* wBlobLen (2 bytes) */
1535 
1536  if (blob->length > 0)
1537  Stream_Write(s, blob->data, blob->length); /* blobData */
1538  return TRUE;
1539 }
1540 
1541 static BOOL license_write_encrypted_premaster_secret_blob(wStream* s, const LICENSE_BLOB* blob,
1542  UINT32 ModulusLength)
1543 {
1544  const UINT32 length = ModulusLength + 8;
1545 
1546  WINPR_ASSERT(blob);
1547  WINPR_ASSERT(length <= UINT16_MAX);
1548 
1549  if (blob->length > ModulusLength)
1550  {
1551  WLog_ERR(TAG, "invalid blob");
1552  return FALSE;
1553  }
1554 
1555  if (!Stream_EnsureRemainingCapacity(s, length + 4))
1556  return FALSE;
1557  Stream_Write_UINT16(s, blob->type); /* wBlobType (2 bytes) */
1558  Stream_Write_UINT16(s, (UINT16)length); /* wBlobLen (2 bytes) */
1559 
1560  if (blob->length > 0)
1561  Stream_Write(s, blob->data, blob->length); /* blobData */
1562 
1563  Stream_Zero(s, length - blob->length);
1564  return TRUE;
1565 }
1566 
1567 static BOOL license_read_encrypted_premaster_secret_blob(wStream* s, LICENSE_BLOB* blob,
1568  UINT32* ModulusLength)
1569 {
1570  if (!license_read_binary_blob(s, blob))
1571  return FALSE;
1572  WINPR_ASSERT(ModulusLength);
1573  *ModulusLength = blob->length;
1574  return TRUE;
1575 }
1576 
1583 LICENSE_BLOB* license_new_binary_blob(UINT16 type)
1584 {
1585  LICENSE_BLOB* blob = (LICENSE_BLOB*)calloc(1, sizeof(LICENSE_BLOB));
1586  if (blob)
1587  blob->type = type;
1588  return blob;
1589 }
1590 
1597 void license_free_binary_blob(LICENSE_BLOB* blob)
1598 {
1599  if (blob)
1600  {
1601  free(blob->data);
1602  free(blob);
1603  }
1604 }
1605 
1613 BOOL license_read_scope_list(wStream* s, SCOPE_LIST* scopeList)
1614 {
1615  UINT32 scopeCount = 0;
1616 
1617  WINPR_ASSERT(scopeList);
1618 
1619  if (!license_check_stream_length(s, 4, "license scope list"))
1620  return FALSE;
1621 
1622  Stream_Read_UINT32(s, scopeCount); /* ScopeCount (4 bytes) */
1623 
1624  if (!license_check_stream_length(s, 4ll * scopeCount, "license scope list::count"))
1625  return FALSE;
1626 
1627  if (!license_scope_list_resize(scopeList, scopeCount))
1628  return FALSE;
1629  /* ScopeArray */
1630  for (UINT32 i = 0; i < scopeCount; i++)
1631  {
1632  if (!license_read_binary_blob(s, scopeList->array[i]))
1633  return FALSE;
1634  }
1635 
1636  return TRUE;
1637 }
1638 
1639 BOOL license_write_scope_list(wStream* s, const SCOPE_LIST* scopeList)
1640 {
1641  WINPR_ASSERT(scopeList);
1642 
1643  if (!license_check_stream_capacity(s, 4, "license scope list"))
1644  return FALSE;
1645 
1646  Stream_Write_UINT32(s, scopeList->count); /* ScopeCount (4 bytes) */
1647 
1648  if (!license_check_stream_capacity(s, scopeList->count * 4ull, "license scope list::count"))
1649  return FALSE;
1650 
1651  /* ScopeArray */
1652  WINPR_ASSERT(scopeList->array || (scopeList->count == 0));
1653  for (UINT32 i = 0; i < scopeList->count; i++)
1654  {
1655  const LICENSE_BLOB* element = scopeList->array[i];
1656 
1657  if (!license_write_binary_blob(s, element))
1658  return FALSE;
1659  }
1660 
1661  return TRUE;
1662 }
1663 
1670 SCOPE_LIST* license_new_scope_list(void)
1671 {
1672  SCOPE_LIST* list = calloc(1, sizeof(SCOPE_LIST));
1673  return list;
1674 }
1675 
1676 BOOL license_scope_list_resize(SCOPE_LIST* scopeList, UINT32 count)
1677 {
1678  WINPR_ASSERT(scopeList);
1679  WINPR_ASSERT(scopeList->array || (scopeList->count == 0));
1680 
1681  for (UINT32 x = count; x < scopeList->count; x++)
1682  {
1683  license_free_binary_blob(scopeList->array[x]);
1684  scopeList->array[x] = NULL;
1685  }
1686 
1687  if (count > 0)
1688  {
1689  LICENSE_BLOB** tmp =
1690  (LICENSE_BLOB**)realloc((void*)scopeList->array, count * sizeof(LICENSE_BLOB*));
1691  if (!tmp)
1692  return FALSE;
1693  scopeList->array = tmp;
1694  }
1695  else
1696  {
1697  free((void*)scopeList->array);
1698  scopeList->array = NULL;
1699  }
1700 
1701  for (UINT32 x = scopeList->count; x < count; x++)
1702  {
1703  LICENSE_BLOB* blob = license_new_binary_blob(BB_SCOPE_BLOB);
1704  if (!blob)
1705  {
1706  scopeList->count = x;
1707  return FALSE;
1708  }
1709  scopeList->array[x] = blob;
1710  }
1711 
1712  scopeList->count = count;
1713  return TRUE;
1714 }
1715 
1722 void license_free_scope_list(SCOPE_LIST* scopeList)
1723 {
1724  if (!scopeList)
1725  return;
1726 
1727  license_scope_list_resize(scopeList, 0);
1728  free(scopeList);
1729 }
1730 
1731 BOOL license_send_license_info(rdpLicense* license, const LICENSE_BLOB* calBlob,
1732  const BYTE* signature, size_t signature_length)
1733 {
1734  WINPR_ASSERT(calBlob);
1735  WINPR_ASSERT(signature);
1736  WINPR_ASSERT(license->certificate);
1737 
1738  const rdpCertInfo* info = freerdp_certificate_get_info(license->certificate);
1739  if (!info)
1740  return FALSE;
1741 
1742  wStream* s = license_send_stream_init(license);
1743  if (!s)
1744  return FALSE;
1745 
1746  if (!license_check_stream_capacity(s, 8 + sizeof(license->ClientRandom),
1747  "license info::ClientRandom"))
1748  goto error;
1749 
1750  Stream_Write_UINT32(s,
1751  license->PreferredKeyExchangeAlg); /* PreferredKeyExchangeAlg (4 bytes) */
1752  Stream_Write_UINT32(s, license->PlatformId); /* PlatformId (4 bytes) */
1753 
1754  /* ClientRandom (32 bytes) */
1755  Stream_Write(s, license->ClientRandom, sizeof(license->ClientRandom));
1756 
1757  /* Licensing Binary Blob with EncryptedPreMasterSecret: */
1758  if (!license_write_encrypted_premaster_secret_blob(s, license->EncryptedPremasterSecret,
1759  info->ModulusLength))
1760  goto error;
1761 
1762  /* Licensing Binary Blob with LicenseInfo: */
1763  if (!license_write_binary_blob(s, calBlob))
1764  goto error;
1765 
1766  /* Licensing Binary Blob with EncryptedHWID */
1767  if (!license_write_binary_blob(s, license->EncryptedHardwareId))
1768  goto error;
1769 
1770  /* MACData */
1771  if (!license_check_stream_capacity(s, signature_length, "license info::MACData"))
1772  goto error;
1773  Stream_Write(s, signature, signature_length);
1774 
1775  return license_send(license, s, LICENSE_INFO);
1776 
1777 error:
1778  Stream_Release(s);
1779  return FALSE;
1780 }
1781 
1782 static BOOL license_check_preferred_alg(rdpLicense* license, UINT32 PreferredKeyExchangeAlg,
1783  const char* where)
1784 {
1785  WINPR_ASSERT(license);
1786  WINPR_ASSERT(where);
1787 
1788  if (license->PreferredKeyExchangeAlg != PreferredKeyExchangeAlg)
1789  {
1790  char buffer1[64] = { 0 };
1791  char buffer2[64] = { 0 };
1792  WLog_WARN(TAG, "%s::PreferredKeyExchangeAlg, expected %s, got %s", where,
1793  license_preferred_key_exchange_alg_string(license->PreferredKeyExchangeAlg,
1794  buffer1, sizeof(buffer1)),
1795  license_preferred_key_exchange_alg_string(PreferredKeyExchangeAlg, buffer2,
1796  sizeof(buffer2)));
1797  return FALSE;
1798  }
1799  return TRUE;
1800 }
1801 
1802 BOOL license_read_license_info(rdpLicense* license, wStream* s)
1803 {
1804  BOOL rc = FALSE;
1805  UINT32 PreferredKeyExchangeAlg = 0;
1806 
1807  WINPR_ASSERT(license);
1808  WINPR_ASSERT(license->certificate);
1809 
1810  const rdpCertInfo* info = freerdp_certificate_get_info(license->certificate);
1811  if (!info)
1812  goto error;
1813 
1814  /* ClientRandom (32 bytes) */
1815  if (!license_check_stream_length(s, 8 + sizeof(license->ClientRandom), "license info"))
1816  goto error;
1817 
1818  Stream_Read_UINT32(s, PreferredKeyExchangeAlg); /* PreferredKeyExchangeAlg (4 bytes) */
1819  if (!license_check_preferred_alg(license, PreferredKeyExchangeAlg, "license info"))
1820  goto error;
1821  Stream_Read_UINT32(s, license->PlatformId); /* PlatformId (4 bytes) */
1822 
1823  /* ClientRandom (32 bytes) */
1824  Stream_Read(s, license->ClientRandom, sizeof(license->ClientRandom));
1825 
1826  /* Licensing Binary Blob with EncryptedPreMasterSecret: */
1827  UINT32 ModulusLength = 0;
1828  if (!license_read_encrypted_premaster_secret_blob(s, license->EncryptedPremasterSecret,
1829  &ModulusLength))
1830  goto error;
1831 
1832  if (ModulusLength != info->ModulusLength)
1833  {
1834  WLog_WARN(TAG,
1835  "EncryptedPremasterSecret,::ModulusLength[%" PRIu32
1836  "] != rdpCertInfo::ModulusLength[%" PRIu32 "]",
1837  ModulusLength, info->ModulusLength);
1838  goto error;
1839  }
1840  /* Licensing Binary Blob with LicenseInfo: */
1841  if (!license_read_binary_blob(s, license->LicenseInfo))
1842  goto error;
1843 
1844  /* Licensing Binary Blob with EncryptedHWID */
1845  if (!license_read_binary_blob(s, license->EncryptedHardwareId))
1846  goto error;
1847 
1848  /* MACData */
1849  if (!license_check_stream_length(s, sizeof(license->MACData), "license info::MACData"))
1850  goto error;
1851  Stream_Read(s, license->MACData, sizeof(license->MACData));
1852 
1853  rc = TRUE;
1854 
1855 error:
1856  return rc;
1857 }
1858 
1866 BOOL license_read_license_request_packet(rdpLicense* license, wStream* s)
1867 {
1868  WINPR_ASSERT(license);
1869 
1870  /* ServerRandom (32 bytes) */
1871  if (!license_check_stream_length(s, sizeof(license->ServerRandom), "license request"))
1872  return FALSE;
1873 
1874  Stream_Read(s, license->ServerRandom, sizeof(license->ServerRandom));
1875 
1876  /* ProductInfo */
1877  if (!license_read_product_info(s, license->ProductInfo))
1878  return FALSE;
1879 
1880  /* KeyExchangeList */
1881  if (!license_read_binary_blob(s, license->KeyExchangeList))
1882  return FALSE;
1883 
1884  /* ServerCertificate */
1885  if (!license_read_binary_blob(s, license->ServerCertificate))
1886  return FALSE;
1887 
1888  /* ScopeList */
1889  if (!license_read_scope_list(s, license->ScopeList))
1890  return FALSE;
1891 
1892  /* Parse Server Certificate */
1893  if (!freerdp_certificate_read_server_cert(license->certificate,
1894  license->ServerCertificate->data,
1895  license->ServerCertificate->length))
1896  return FALSE;
1897 
1898  if (!license_generate_keys(license) || !license_generate_hwid(license) ||
1899  !license_encrypt_premaster_secret(license))
1900  return FALSE;
1901 
1902 #ifdef WITH_DEBUG_LICENSE
1903  WLog_DBG(TAG, "ServerRandom:");
1904  winpr_HexDump(TAG, WLOG_DEBUG, license->ServerRandom, sizeof(license->ServerRandom));
1905  license_print_product_info(license->ProductInfo);
1906  license_print_scope_list(license->ScopeList);
1907 #endif
1908  return TRUE;
1909 }
1910 
1911 BOOL license_write_license_request_packet(const rdpLicense* license, wStream* s)
1912 {
1913  WINPR_ASSERT(license);
1914 
1915  /* ServerRandom (32 bytes) */
1916  if (!license_check_stream_capacity(s, sizeof(license->ServerRandom), "license request"))
1917  return FALSE;
1918  Stream_Write(s, license->ServerRandom, sizeof(license->ServerRandom));
1919 
1920  /* ProductInfo */
1921  if (!license_write_product_info(s, license->ProductInfo))
1922  return FALSE;
1923 
1924  /* KeyExchangeList */
1925  if (!license_write_binary_blob(s, license->KeyExchangeList))
1926  return FALSE;
1927 
1928  /* ServerCertificate */
1929  if (!license_write_binary_blob(s, license->ServerCertificate))
1930  return FALSE;
1931 
1932  /* ScopeList */
1933  if (!license_write_scope_list(s, license->ScopeList))
1934  return FALSE;
1935 
1936  return TRUE;
1937 }
1938 
1939 static BOOL license_send_license_request_packet(rdpLicense* license)
1940 {
1941  wStream* s = license_send_stream_init(license);
1942  if (!s)
1943  return FALSE;
1944 
1945  if (!license_write_license_request_packet(license, s))
1946  goto fail;
1947 
1948  return license_send(license, s, LICENSE_REQUEST);
1949 
1950 fail:
1951  Stream_Release(s);
1952  return FALSE;
1953 }
1954 
1955 /*
1956  * Read a PLATFORM_CHALLENGE packet.
1957  * msdn{cc241921}
1958  * @param license license module
1959  * @param s stream
1960  */
1961 
1962 BOOL license_read_platform_challenge_packet(rdpLicense* license, wStream* s)
1963 {
1964  BYTE macData[LICENSING_ENCRYPTION_KEY_LENGTH] = { 0 };
1965  UINT32 ConnectFlags = 0;
1966 
1967  WINPR_ASSERT(license);
1968 
1969  DEBUG_LICENSE("Receiving Platform Challenge Packet");
1970 
1971  if (!license_check_stream_length(s, 4, "license platform challenge"))
1972  return FALSE;
1973 
1974  Stream_Read_UINT32(s, ConnectFlags); /* ConnectFlags, Reserved (4 bytes) */
1975 
1976  /* EncryptedPlatformChallenge */
1977  license->EncryptedPlatformChallenge->type = BB_ANY_BLOB;
1978  if (!license_read_binary_blob(s, license->EncryptedPlatformChallenge))
1979  return FALSE;
1980  license->EncryptedPlatformChallenge->type = BB_ENCRYPTED_DATA_BLOB;
1981 
1982  /* MACData (16 bytes) */
1983  if (!license_check_stream_length(s, sizeof(macData), "license platform challenge::MAC"))
1984  return FALSE;
1985 
1986  Stream_Read(s, macData, sizeof(macData));
1987  if (!license_decrypt_and_check_MAC(license, license->EncryptedPlatformChallenge->data,
1988  license->EncryptedPlatformChallenge->length,
1989  license->PlatformChallenge, macData))
1990  return FALSE;
1991 
1992 #ifdef WITH_DEBUG_LICENSE
1993  WLog_DBG(TAG, "ConnectFlags: 0x%08" PRIX32 "", ConnectFlags);
1994  WLog_DBG(TAG, "EncryptedPlatformChallenge:");
1995  winpr_HexDump(TAG, WLOG_DEBUG, license->EncryptedPlatformChallenge->data,
1996  license->EncryptedPlatformChallenge->length);
1997  WLog_DBG(TAG, "PlatformChallenge:");
1998  winpr_HexDump(TAG, WLOG_DEBUG, license->PlatformChallenge->data,
1999  license->PlatformChallenge->length);
2000  WLog_DBG(TAG, "MacData:");
2001  winpr_HexDump(TAG, WLOG_DEBUG, macData, sizeof(macData));
2002 #endif
2003  return TRUE;
2004 }
2005 
2006 BOOL license_send_error_alert(rdpLicense* license, UINT32 dwErrorCode, UINT32 dwStateTransition,
2007  const LICENSE_BLOB* info)
2008 {
2009  wStream* s = license_send_stream_init(license);
2010 
2011  if (!s)
2012  goto fail;
2013 
2014  if (!license_check_stream_capacity(s, 8, "license error alert"))
2015  goto fail;
2016  Stream_Write_UINT32(s, dwErrorCode);
2017  Stream_Write_UINT32(s, dwStateTransition);
2018 
2019  if (info)
2020  {
2021  if (!license_write_binary_blob(s, info))
2022  goto fail;
2023  }
2024 
2025  return license_send(license, s, ERROR_ALERT);
2026 fail:
2027  Stream_Release(s);
2028  return FALSE;
2029 }
2030 
2031 BOOL license_send_platform_challenge_packet(rdpLicense* license)
2032 {
2033  wStream* s = license_send_stream_init(license);
2034 
2035  if (!s)
2036  goto fail;
2037 
2038  DEBUG_LICENSE("Receiving Platform Challenge Packet");
2039 
2040  if (!license_check_stream_capacity(s, 4, "license platform challenge"))
2041  goto fail;
2042 
2043  Stream_Zero(s, 4); /* ConnectFlags, Reserved (4 bytes) */
2044 
2045  /* EncryptedPlatformChallenge */
2046  if (!license_write_binary_blob(s, license->EncryptedPlatformChallenge))
2047  goto fail;
2048 
2049  /* MACData (16 bytes) */
2050  if (!license_check_stream_length(s, sizeof(license->MACData),
2051  "license platform challenge::MAC"))
2052  goto fail;
2053 
2054  Stream_Write(s, license->MACData, sizeof(license->MACData));
2055 
2056  return license_send(license, s, PLATFORM_CHALLENGE);
2057 fail:
2058  Stream_Release(s);
2059  return FALSE;
2060 }
2061 
2062 static BOOL license_read_encrypted_blob(const rdpLicense* license, wStream* s, LICENSE_BLOB* target)
2063 {
2064  UINT16 wBlobType = 0;
2065  UINT16 wBlobLen = 0;
2066 
2067  WINPR_ASSERT(license);
2068  WINPR_ASSERT(target);
2069 
2070  if (!license_check_stream_length(s, 4, "license encrypted blob"))
2071  return FALSE;
2072 
2073  Stream_Read_UINT16(s, wBlobType);
2074  if (wBlobType != BB_ENCRYPTED_DATA_BLOB)
2075  {
2076  WLog_WARN(
2077  TAG,
2078  "expecting BB_ENCRYPTED_DATA_BLOB blob, probably a windows 2003 server, continuing...");
2079  }
2080 
2081  Stream_Read_UINT16(s, wBlobLen);
2082 
2083  BYTE* encryptedData = Stream_Pointer(s);
2084  if (!Stream_SafeSeek(s, wBlobLen))
2085  {
2086  WLog_WARN(TAG,
2087  "short license encrypted blob::length, expected %" PRIu16 " bytes, got %" PRIuz,
2088  wBlobLen, Stream_GetRemainingLength(s));
2089  return FALSE;
2090  }
2091 
2092  return license_rc4_with_licenseKey(license, encryptedData, wBlobLen, target);
2093 }
2094 
2102 BOOL license_read_new_or_upgrade_license_packet(rdpLicense* license, wStream* s)
2103 {
2104  UINT32 os_major = 0;
2105  UINT32 os_minor = 0;
2106  UINT32 cbScope = 0;
2107  UINT32 cbCompanyName = 0;
2108  UINT32 cbProductId = 0;
2109  UINT32 cbLicenseInfo = 0;
2110  wStream sbuffer = { 0 };
2111  wStream* licenseStream = NULL;
2112  BOOL ret = FALSE;
2113  BYTE computedMac[16] = { 0 };
2114  const BYTE* readMac = NULL;
2115 
2116  WINPR_ASSERT(license);
2117 
2118  DEBUG_LICENSE("Receiving Server New/Upgrade License Packet");
2119 
2120  LICENSE_BLOB* calBlob = license_new_binary_blob(BB_DATA_BLOB);
2121  if (!calBlob)
2122  return FALSE;
2123 
2124  /* EncryptedLicenseInfo */
2125  if (!license_read_encrypted_blob(license, s, calBlob))
2126  goto fail;
2127 
2128  /* compute MAC and check it */
2129  readMac = Stream_Pointer(s);
2130  if (!Stream_SafeSeek(s, sizeof(computedMac)))
2131  {
2132  WLog_WARN(TAG, "short license new/upgrade, expected 16 bytes, got %" PRIuz,
2133  Stream_GetRemainingLength(s));
2134  goto fail;
2135  }
2136 
2137  if (!security_mac_data(license->MacSaltKey, sizeof(license->MacSaltKey), calBlob->data,
2138  calBlob->length, computedMac, sizeof(computedMac)))
2139  goto fail;
2140 
2141  if (memcmp(computedMac, readMac, sizeof(computedMac)) != 0)
2142  {
2143  WLog_ERR(TAG, "new or upgrade license MAC mismatch");
2144  goto fail;
2145  }
2146 
2147  licenseStream = Stream_StaticConstInit(&sbuffer, calBlob->data, calBlob->length);
2148  if (!licenseStream)
2149  {
2150  WLog_ERR(TAG, "license::blob::data=%p, license::blob::length=%" PRIu16, calBlob->data,
2151  calBlob->length);
2152  goto fail;
2153  }
2154 
2155  if (!license_check_stream_length(licenseStream, 8, "license new/upgrade::blob::version"))
2156  goto fail;
2157 
2158  Stream_Read_UINT16(licenseStream, os_minor);
2159  Stream_Read_UINT16(licenseStream, os_major);
2160 
2161  WLog_DBG(TAG, "Version: %" PRIu16 ".%" PRIu16, os_major, os_minor);
2162 
2163  /* Scope */
2164  Stream_Read_UINT32(licenseStream, cbScope);
2165  if (!license_check_stream_length(licenseStream, cbScope, "license new/upgrade::blob::scope"))
2166  goto fail;
2167 
2168 #ifdef WITH_DEBUG_LICENSE
2169  WLog_DBG(TAG, "Scope:");
2170  winpr_HexDump(TAG, WLOG_DEBUG, Stream_Pointer(licenseStream), cbScope);
2171 #endif
2172  Stream_Seek(licenseStream, cbScope);
2173 
2174  /* CompanyName */
2175  if (!license_check_stream_length(licenseStream, 4, "license new/upgrade::blob::cbCompanyName"))
2176  goto fail;
2177 
2178  Stream_Read_UINT32(licenseStream, cbCompanyName);
2179  if (!license_check_stream_length(licenseStream, cbCompanyName,
2180  "license new/upgrade::blob::CompanyName"))
2181  goto fail;
2182 
2183 #ifdef WITH_DEBUG_LICENSE
2184  WLog_DBG(TAG, "Company name:");
2185  winpr_HexDump(TAG, WLOG_DEBUG, Stream_Pointer(licenseStream), cbCompanyName);
2186 #endif
2187  Stream_Seek(licenseStream, cbCompanyName);
2188 
2189  /* productId */
2190  if (!license_check_stream_length(licenseStream, 4, "license new/upgrade::blob::cbProductId"))
2191  goto fail;
2192 
2193  Stream_Read_UINT32(licenseStream, cbProductId);
2194 
2195  if (!license_check_stream_length(licenseStream, cbProductId,
2196  "license new/upgrade::blob::ProductId"))
2197  goto fail;
2198 
2199 #ifdef WITH_DEBUG_LICENSE
2200  WLog_DBG(TAG, "Product id:");
2201  winpr_HexDump(TAG, WLOG_DEBUG, Stream_Pointer(licenseStream), cbProductId);
2202 #endif
2203  Stream_Seek(licenseStream, cbProductId);
2204 
2205  /* licenseInfo */
2206  if (!license_check_stream_length(licenseStream, 4, "license new/upgrade::blob::cbLicenseInfo"))
2207  goto fail;
2208 
2209  Stream_Read_UINT32(licenseStream, cbLicenseInfo);
2210  if (!license_check_stream_length(licenseStream, cbLicenseInfo,
2211  "license new/upgrade::blob::LicenseInfo"))
2212  goto fail;
2213 
2214  license->type = LICENSE_TYPE_ISSUED;
2215  ret = license_set_state(license, LICENSE_STATE_COMPLETED);
2216 
2217  if (!license->rdp->settings->OldLicenseBehaviour)
2218  ret = saveCal(license->rdp->settings, Stream_Pointer(licenseStream), cbLicenseInfo,
2219  license->rdp->settings->ClientHostname);
2220 
2221 fail:
2222  license_free_binary_blob(calBlob);
2223  return ret;
2224 }
2225 
2233 BOOL license_read_error_alert_packet(rdpLicense* license, wStream* s)
2234 {
2235  UINT32 dwErrorCode = 0;
2236  UINT32 dwStateTransition = 0;
2237 
2238  WINPR_ASSERT(license);
2239  WINPR_ASSERT(license->rdp);
2240 
2241  if (!license_check_stream_length(s, 8ul, "error alert"))
2242  return FALSE;
2243 
2244  Stream_Read_UINT32(s, dwErrorCode); /* dwErrorCode (4 bytes) */
2245  Stream_Read_UINT32(s, dwStateTransition); /* dwStateTransition (4 bytes) */
2246 
2247  if (!license_read_binary_blob(s, license->ErrorInfo)) /* bbErrorInfo */
2248  return FALSE;
2249 
2250 #ifdef WITH_DEBUG_LICENSE
2251  WLog_DBG(TAG, "dwErrorCode: %s, dwStateTransition: %s", error_codes[dwErrorCode],
2252  state_transitions[dwStateTransition]);
2253 #endif
2254 
2255  if (dwErrorCode == STATUS_VALID_CLIENT)
2256  {
2257  license->type = LICENSE_TYPE_NONE;
2258  return license_set_state(license, LICENSE_STATE_COMPLETED);
2259  }
2260 
2261  switch (dwStateTransition)
2262  {
2263  case ST_TOTAL_ABORT:
2264  license_set_state(license, LICENSE_STATE_ABORTED);
2265  break;
2266  case ST_NO_TRANSITION:
2267  license_set_state(license, LICENSE_STATE_COMPLETED);
2268  break;
2269  case ST_RESET_PHASE_TO_START:
2270  license_set_state(license, LICENSE_STATE_CONFIGURED);
2271  break;
2272  case ST_RESEND_LAST_MESSAGE:
2273  break;
2274  default:
2275  break;
2276  }
2277 
2278  return TRUE;
2279 }
2280 
2288 BOOL license_write_new_license_request_packet(const rdpLicense* license, wStream* s)
2289 {
2290  WINPR_ASSERT(license);
2291 
2292  const rdpCertInfo* info = freerdp_certificate_get_info(license->certificate);
2293  if (!info)
2294  return FALSE;
2295 
2296  if (!license_check_stream_capacity(s, 8 + sizeof(license->ClientRandom), "License Request"))
2297  return FALSE;
2298 
2299  Stream_Write_UINT32(s,
2300  license->PreferredKeyExchangeAlg); /* PreferredKeyExchangeAlg (4 bytes) */
2301  Stream_Write_UINT32(s, license->PlatformId); /* PlatformId (4 bytes) */
2302  Stream_Write(s, license->ClientRandom,
2303  sizeof(license->ClientRandom)); /* ClientRandom (32 bytes) */
2304 
2305  if (/* EncryptedPremasterSecret */
2306  !license_write_encrypted_premaster_secret_blob(s, license->EncryptedPremasterSecret,
2307  info->ModulusLength) ||
2308  /* ClientUserName */
2309  !license_write_binary_blob(s, license->ClientUserName) ||
2310  /* ClientMachineName */
2311  !license_write_binary_blob(s, license->ClientMachineName))
2312  {
2313  return FALSE;
2314  }
2315 
2316 #ifdef WITH_DEBUG_LICENSE
2317  WLog_DBG(TAG, "PreferredKeyExchangeAlg: 0x%08" PRIX32 "", license->PreferredKeyExchangeAlg);
2318  WLog_DBG(TAG, "ClientRandom:");
2319  winpr_HexDump(TAG, WLOG_DEBUG, license->ClientRandom, sizeof(license->ClientRandom));
2320  WLog_DBG(TAG, "EncryptedPremasterSecret");
2321  winpr_HexDump(TAG, WLOG_DEBUG, license->EncryptedPremasterSecret->data,
2322  license->EncryptedPremasterSecret->length);
2323  WLog_DBG(TAG, "ClientUserName (%" PRIu16 "): %s", license->ClientUserName->length,
2324  (char*)license->ClientUserName->data);
2325  WLog_DBG(TAG, "ClientMachineName (%" PRIu16 "): %s", license->ClientMachineName->length,
2326  (char*)license->ClientMachineName->data);
2327 #endif
2328  return TRUE;
2329 }
2330 
2331 BOOL license_read_new_license_request_packet(rdpLicense* license, wStream* s)
2332 {
2333  UINT32 PreferredKeyExchangeAlg = 0;
2334 
2335  WINPR_ASSERT(license);
2336 
2337  if (!license_check_stream_length(s, 8ull + sizeof(license->ClientRandom),
2338  "new license request"))
2339  return FALSE;
2340 
2341  Stream_Read_UINT32(s, PreferredKeyExchangeAlg); /* PreferredKeyExchangeAlg (4 bytes) */
2342  if (!license_check_preferred_alg(license, PreferredKeyExchangeAlg, "new license request"))
2343  return FALSE;
2344 
2345  Stream_Read_UINT32(s, license->PlatformId); /* PlatformId (4 bytes) */
2346  Stream_Read(s, license->ClientRandom,
2347  sizeof(license->ClientRandom)); /* ClientRandom (32 bytes) */
2348 
2349  /* EncryptedPremasterSecret */
2350  UINT32 ModulusLength = 0;
2351  if (!license_read_encrypted_premaster_secret_blob(s, license->EncryptedPremasterSecret,
2352  &ModulusLength))
2353  return FALSE;
2354 
2355  const rdpCertInfo* info = freerdp_certificate_get_info(license->certificate);
2356  if (!info)
2357  WLog_WARN(TAG, "Missing license certificate, skipping ModulusLength checks");
2358  else if (ModulusLength != info->ModulusLength)
2359  {
2360  WLog_WARN(TAG,
2361  "EncryptedPremasterSecret expected to be %" PRIu32 " bytes, but read %" PRIu32
2362  " bytes",
2363  info->ModulusLength, ModulusLength);
2364  return FALSE;
2365  }
2366 
2367  /* ClientUserName */
2368  if (!license_read_binary_blob(s, license->ClientUserName))
2369  return FALSE;
2370  /* ClientMachineName */
2371  if (!license_read_binary_blob(s, license->ClientMachineName))
2372  return FALSE;
2373 
2374  return TRUE;
2375 }
2376 
2383 BOOL license_answer_license_request(rdpLicense* license)
2384 {
2385  wStream* s = NULL;
2386  BYTE* license_data = NULL;
2387  size_t license_size = 0;
2388  BOOL status = 0;
2389  char* username = NULL;
2390 
2391  WINPR_ASSERT(license);
2392  WINPR_ASSERT(license->rdp);
2393  WINPR_ASSERT(license->rdp->settings);
2394 
2395  if (!license->rdp->settings->OldLicenseBehaviour)
2396  license_data = loadCalFile(license->rdp->settings, license->rdp->settings->ClientHostname,
2397  &license_size);
2398 
2399  if (license_data)
2400  {
2401  LICENSE_BLOB* calBlob = NULL;
2402  BYTE signature[LICENSING_ENCRYPTION_KEY_LENGTH] = { 0 };
2403 
2404  DEBUG_LICENSE("Sending Saved License Packet");
2405 
2406  WINPR_ASSERT(license->EncryptedHardwareId);
2407  license->EncryptedHardwareId->type = BB_ENCRYPTED_DATA_BLOB;
2408  if (!license_encrypt_and_MAC(license, license->HardwareId, sizeof(license->HardwareId),
2409  license->EncryptedHardwareId, signature, sizeof(signature)))
2410  {
2411  free(license_data);
2412  return FALSE;
2413  }
2414 
2415  calBlob = license_new_binary_blob(BB_DATA_BLOB);
2416  if (!calBlob)
2417  {
2418  free(license_data);
2419  return FALSE;
2420  }
2421  calBlob->data = license_data;
2422  WINPR_ASSERT(license_size <= UINT16_MAX);
2423  calBlob->length = (UINT16)license_size;
2424 
2425  status = license_send_license_info(license, calBlob, signature, sizeof(signature));
2426  license_free_binary_blob(calBlob);
2427 
2428  return status;
2429  }
2430 
2431  DEBUG_LICENSE("Sending New License Packet");
2432 
2433  s = license_send_stream_init(license);
2434  if (!s)
2435  return FALSE;
2436  if (license->rdp->settings->Username != NULL)
2437  username = license->rdp->settings->Username;
2438  else
2439  username = "username";
2440 
2441  {
2442  WINPR_ASSERT(license->ClientUserName);
2443  const size_t len = strlen(username) + 1;
2444  WINPR_ASSERT(len <= UINT16_MAX);
2445 
2446  license->ClientUserName->data = (BYTE*)username;
2447  license->ClientUserName->length = (UINT16)len;
2448  }
2449 
2450  {
2451  WINPR_ASSERT(license->ClientMachineName);
2452  const size_t len = strlen(license->rdp->settings->ClientHostname) + 1;
2453  WINPR_ASSERT(len <= UINT16_MAX);
2454 
2455  license->ClientMachineName->data = (BYTE*)license->rdp->settings->ClientHostname;
2456  license->ClientMachineName->length = (UINT16)len;
2457  }
2458  status = license_write_new_license_request_packet(license, s);
2459 
2460  WINPR_ASSERT(license->ClientUserName);
2461  license->ClientUserName->data = NULL;
2462  license->ClientUserName->length = 0;
2463 
2464  WINPR_ASSERT(license->ClientMachineName);
2465  license->ClientMachineName->data = NULL;
2466  license->ClientMachineName->length = 0;
2467 
2468  if (!status)
2469  {
2470  Stream_Release(s);
2471  return FALSE;
2472  }
2473 
2474  return license_send(license, s, NEW_LICENSE_REQUEST);
2475 }
2476 
2483 BOOL license_send_platform_challenge_response(rdpLicense* license)
2484 {
2485  wStream* challengeRespData = NULL;
2486  BYTE* buffer = NULL;
2487  BOOL status = 0;
2488 
2489  WINPR_ASSERT(license);
2490  WINPR_ASSERT(license->PlatformChallenge);
2491  WINPR_ASSERT(license->MacSaltKey);
2492  WINPR_ASSERT(license->EncryptedPlatformChallenge);
2493  WINPR_ASSERT(license->EncryptedHardwareId);
2494 
2495  DEBUG_LICENSE("Sending Platform Challenge Response Packet");
2496 
2497  license->EncryptedPlatformChallenge->type = BB_DATA_BLOB;
2498 
2499  /* prepare the PLATFORM_CHALLENGE_RESPONSE_DATA */
2500  challengeRespData = Stream_New(NULL, 8 + license->PlatformChallenge->length);
2501  if (!challengeRespData)
2502  return FALSE;
2503  Stream_Write_UINT16(challengeRespData, PLATFORM_CHALLENGE_RESPONSE_VERSION); /* wVersion */
2504  Stream_Write_UINT16(challengeRespData, license->ClientType); /* wClientType */
2505  Stream_Write_UINT16(challengeRespData, license->LicenseDetailLevel); /* wLicenseDetailLevel */
2506  Stream_Write_UINT16(challengeRespData, license->PlatformChallenge->length); /* cbChallenge */
2507  Stream_Write(challengeRespData, license->PlatformChallenge->data,
2508  license->PlatformChallenge->length); /* pbChallenge */
2509  Stream_SealLength(challengeRespData);
2510 
2511  /* compute MAC of PLATFORM_CHALLENGE_RESPONSE_DATA + HWID */
2512  const size_t length = Stream_Length(challengeRespData) + sizeof(license->HardwareId);
2513  buffer = (BYTE*)malloc(length);
2514  if (!buffer)
2515  {
2516  Stream_Free(challengeRespData, TRUE);
2517  return FALSE;
2518  }
2519 
2520  CopyMemory(buffer, Stream_Buffer(challengeRespData), Stream_Length(challengeRespData));
2521  CopyMemory(&buffer[Stream_Length(challengeRespData)], license->HardwareId,
2522  sizeof(license->HardwareId));
2523  status = security_mac_data(license->MacSaltKey, sizeof(license->MacSaltKey), buffer, length,
2524  license->MACData, sizeof(license->MACData));
2525  free(buffer);
2526 
2527  if (!status)
2528  {
2529  Stream_Free(challengeRespData, TRUE);
2530  return FALSE;
2531  }
2532 
2533  license->EncryptedHardwareId->type = BB_ENCRYPTED_DATA_BLOB;
2534  if (!license_rc4_with_licenseKey(license, license->HardwareId, sizeof(license->HardwareId),
2535  license->EncryptedHardwareId))
2536  {
2537  Stream_Free(challengeRespData, TRUE);
2538  return FALSE;
2539  }
2540 
2541  status = license_rc4_with_licenseKey(license, Stream_Buffer(challengeRespData),
2542  Stream_Length(challengeRespData),
2543  license->EncryptedPlatformChallengeResponse);
2544  Stream_Free(challengeRespData, TRUE);
2545  if (!status)
2546  return FALSE;
2547 
2548 #ifdef WITH_DEBUG_LICENSE
2549  WLog_DBG(TAG, "LicensingEncryptionKey:");
2550  winpr_HexDump(TAG, WLOG_DEBUG, license->LicensingEncryptionKey, 16);
2551  WLog_DBG(TAG, "HardwareId:");
2552  winpr_HexDump(TAG, WLOG_DEBUG, license->HardwareId, sizeof(license->HardwareId));
2553  WLog_DBG(TAG, "EncryptedHardwareId:");
2554  winpr_HexDump(TAG, WLOG_DEBUG, license->EncryptedHardwareId->data,
2555  license->EncryptedHardwareId->length);
2556 #endif
2557  wStream* s = license_send_stream_init(license);
2558  if (!s)
2559  return FALSE;
2560 
2561  if (license_write_client_platform_challenge_response(license, s))
2562  return license_send(license, s, PLATFORM_CHALLENGE_RESPONSE);
2563 
2564  Stream_Release(s);
2565  return FALSE;
2566 }
2567 
2568 BOOL license_read_platform_challenge_response(rdpLicense* license, wStream* s)
2569 {
2570  UINT16 wVersion = 0;
2571  UINT16 cbChallenge = 0;
2572  const BYTE* pbChallenge = NULL;
2573 
2574  WINPR_ASSERT(license);
2575  WINPR_ASSERT(license->PlatformChallenge);
2576  WINPR_ASSERT(license->MacSaltKey);
2577  WINPR_ASSERT(license->EncryptedPlatformChallenge);
2578  WINPR_ASSERT(license->EncryptedHardwareId);
2579 
2580  DEBUG_LICENSE("Receiving Platform Challenge Response Packet");
2581 
2582  if (!license_check_stream_length(s, 8, "PLATFORM_CHALLENGE_RESPONSE_DATA"))
2583  return FALSE;
2584 
2585  Stream_Read_UINT16(s, wVersion);
2586  if (wVersion != PLATFORM_CHALLENGE_RESPONSE_VERSION)
2587  {
2588  WLog_WARN(TAG,
2589  "Invalid PLATFORM_CHALLENGE_RESPONSE_DATA::wVersion 0x%04" PRIx16
2590  ", expected 0x04" PRIx16,
2591  wVersion, PLATFORM_CHALLENGE_RESPONSE_VERSION);
2592  return FALSE;
2593  }
2594  Stream_Read_UINT16(s, license->ClientType);
2595  Stream_Read_UINT16(s, license->LicenseDetailLevel);
2596  Stream_Read_UINT16(s, cbChallenge);
2597 
2598  if (!license_check_stream_length(s, cbChallenge,
2599  "PLATFORM_CHALLENGE_RESPONSE_DATA::pbChallenge"))
2600  return FALSE;
2601 
2602  pbChallenge = Stream_Pointer(s);
2603  if (!license_read_binary_blob_data(license->EncryptedPlatformChallengeResponse, BB_DATA_BLOB,
2604  pbChallenge, cbChallenge))
2605  return FALSE;
2606  return Stream_SafeSeek(s, cbChallenge);
2607 }
2608 
2609 BOOL license_write_client_platform_challenge_response(rdpLicense* license, wStream* s)
2610 {
2611  WINPR_ASSERT(license);
2612 
2613  if (!license_write_binary_blob(s, license->EncryptedPlatformChallengeResponse))
2614  return FALSE;
2615  if (!license_write_binary_blob(s, license->EncryptedHardwareId))
2616  return FALSE;
2617  if (!license_check_stream_capacity(s, sizeof(license->MACData),
2618  "CLIENT_PLATFORM_CHALLENGE_RESPONSE::MACData"))
2619  return FALSE;
2620  Stream_Write(s, license->MACData, sizeof(license->MACData));
2621  return TRUE;
2622 }
2623 
2624 BOOL license_read_client_platform_challenge_response(rdpLicense* license, wStream* s)
2625 {
2626  WINPR_ASSERT(license);
2627 
2628  if (!license_read_binary_blob(s, license->EncryptedPlatformChallengeResponse))
2629  return FALSE;
2630  if (!license_read_binary_blob(s, license->EncryptedHardwareId))
2631  return FALSE;
2632  if (!license_check_stream_length(s, sizeof(license->MACData),
2633  "CLIENT_PLATFORM_CHALLENGE_RESPONSE::MACData"))
2634  return FALSE;
2635  Stream_Read(s, license->MACData, sizeof(license->MACData));
2636  return TRUE;
2637 }
2638 
2648 BOOL license_send_valid_client_error_packet(rdpRdp* rdp)
2649 {
2650  WINPR_ASSERT(rdp);
2651  rdpLicense* license = rdp->license;
2652  WINPR_ASSERT(license);
2653 
2654  license->state = LICENSE_STATE_COMPLETED;
2655  license->type = LICENSE_TYPE_NONE;
2656  return license_send_error_alert(license, STATUS_VALID_CLIENT, ST_NO_TRANSITION,
2657  license->ErrorInfo);
2658 }
2659 
2666 rdpLicense* license_new(rdpRdp* rdp)
2667 {
2668  rdpLicense* license = NULL;
2669  WINPR_ASSERT(rdp);
2670 
2671  license = (rdpLicense*)calloc(1, sizeof(rdpLicense));
2672  if (!license)
2673  return NULL;
2674 
2675  license->PlatformId = PLATFORMID;
2676  license->ClientType = OTHER_PLATFORM_CHALLENGE_TYPE;
2677  license->LicenseDetailLevel = LICENSE_DETAIL_DETAIL;
2678  license->PreferredKeyExchangeAlg = KEY_EXCHANGE_ALG_RSA;
2679  license->rdp = rdp;
2680 
2681  license_set_state(license, LICENSE_STATE_INITIAL);
2682  if (!(license->certificate = freerdp_certificate_new()))
2683  goto out_error;
2684  if (!(license->ProductInfo = license_new_product_info()))
2685  goto out_error;
2686  if (!(license->ErrorInfo = license_new_binary_blob(BB_ERROR_BLOB)))
2687  goto out_error;
2688  if (!(license->LicenseInfo = license_new_binary_blob(BB_DATA_BLOB)))
2689  goto out_error;
2690  if (!(license->KeyExchangeList = license_new_binary_blob(BB_KEY_EXCHG_ALG_BLOB)))
2691  goto out_error;
2692  if (!(license->ServerCertificate = license_new_binary_blob(BB_CERTIFICATE_BLOB)))
2693  goto out_error;
2694  if (!(license->ClientUserName = license_new_binary_blob(BB_CLIENT_USER_NAME_BLOB)))
2695  goto out_error;
2696  if (!(license->ClientMachineName = license_new_binary_blob(BB_CLIENT_MACHINE_NAME_BLOB)))
2697  goto out_error;
2698  if (!(license->PlatformChallenge = license_new_binary_blob(BB_ANY_BLOB)))
2699  goto out_error;
2700  if (!(license->EncryptedPlatformChallenge = license_new_binary_blob(BB_ANY_BLOB)))
2701  goto out_error;
2702  if (!(license->EncryptedPlatformChallengeResponse =
2703  license_new_binary_blob(BB_ENCRYPTED_DATA_BLOB)))
2704  goto out_error;
2705  if (!(license->EncryptedPremasterSecret = license_new_binary_blob(BB_ANY_BLOB)))
2706  goto out_error;
2707  if (!(license->EncryptedHardwareId = license_new_binary_blob(BB_ENCRYPTED_DATA_BLOB)))
2708  goto out_error;
2709  if (!(license->EncryptedLicenseInfo = license_new_binary_blob(BB_ENCRYPTED_DATA_BLOB)))
2710  goto out_error;
2711  if (!(license->ScopeList = license_new_scope_list()))
2712  goto out_error;
2713 
2714  license_generate_randoms(license);
2715 
2716  return license;
2717 
2718 out_error:
2719  WINPR_PRAGMA_DIAG_PUSH
2720  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
2721  license_free(license);
2722  WINPR_PRAGMA_DIAG_POP
2723  return NULL;
2724 }
2725 
2731 void license_free(rdpLicense* license)
2732 {
2733  if (license)
2734  {
2735  freerdp_certificate_free(license->certificate);
2736  license_free_product_info(license->ProductInfo);
2737  license_free_binary_blob(license->ErrorInfo);
2738  license_free_binary_blob(license->LicenseInfo);
2739  license_free_binary_blob(license->KeyExchangeList);
2740  license_free_binary_blob(license->ServerCertificate);
2741  license_free_binary_blob(license->ClientUserName);
2742  license_free_binary_blob(license->ClientMachineName);
2743  license_free_binary_blob(license->PlatformChallenge);
2744  license_free_binary_blob(license->EncryptedPlatformChallenge);
2745  license_free_binary_blob(license->EncryptedPlatformChallengeResponse);
2746  license_free_binary_blob(license->EncryptedPremasterSecret);
2747  license_free_binary_blob(license->EncryptedHardwareId);
2748  license_free_binary_blob(license->EncryptedLicenseInfo);
2749  license_free_scope_list(license->ScopeList);
2750  free(license);
2751  }
2752 }
2753 
2754 LICENSE_STATE license_get_state(const rdpLicense* license)
2755 {
2756  WINPR_ASSERT(license);
2757  return license->state;
2758 }
2759 
2760 LICENSE_TYPE license_get_type(const rdpLicense* license)
2761 {
2762  WINPR_ASSERT(license);
2763  return license->type;
2764 }
2765 
2766 BOOL license_set_state(rdpLicense* license, LICENSE_STATE state)
2767 {
2768  WINPR_ASSERT(license);
2769  license->state = state;
2770  switch (state)
2771  {
2772  case LICENSE_STATE_COMPLETED:
2773  break;
2774  case LICENSE_STATE_ABORTED:
2775  default:
2776  license->type = LICENSE_TYPE_INVALID;
2777  break;
2778  }
2779 
2780  return TRUE;
2781 }
2782 
2783 const char* license_get_state_string(LICENSE_STATE state)
2784 {
2785  switch (state)
2786  {
2787  case LICENSE_STATE_INITIAL:
2788  return "LICENSE_STATE_INITIAL";
2789  case LICENSE_STATE_CONFIGURED:
2790  return "LICENSE_STATE_CONFIGURED";
2791  case LICENSE_STATE_REQUEST:
2792  return "LICENSE_STATE_REQUEST";
2793  case LICENSE_STATE_NEW_REQUEST:
2794  return "LICENSE_STATE_NEW_REQUEST";
2795  case LICENSE_STATE_PLATFORM_CHALLENGE:
2796  return "LICENSE_STATE_PLATFORM_CHALLENGE";
2797  case LICENSE_STATE_PLATFORM_CHALLENGE_RESPONSE:
2798  return "LICENSE_STATE_PLATFORM_CHALLENGE_RESPONSE";
2799  case LICENSE_STATE_COMPLETED:
2800  return "LICENSE_STATE_COMPLETED";
2801  case LICENSE_STATE_ABORTED:
2802  return "LICENSE_STATE_ABORTED";
2803  default:
2804  return "LICENSE_STATE_UNKNOWN";
2805  }
2806 }
2807 
2808 BOOL license_server_send_request(rdpLicense* license)
2809 {
2810  if (!license_ensure_state(license, LICENSE_STATE_CONFIGURED, LICENSE_REQUEST))
2811  return FALSE;
2812  if (!license_send_license_request_packet(license))
2813  return FALSE;
2814  return license_set_state(license, LICENSE_STATE_REQUEST);
2815 }
2816 
2817 static BOOL license_set_string(const char* what, const char* value, BYTE** bdst, UINT32* dstLen)
2818 {
2819  WINPR_ASSERT(what);
2820  WINPR_ASSERT(value);
2821  WINPR_ASSERT(bdst);
2822  WINPR_ASSERT(dstLen);
2823 
2824  union
2825  {
2826  WCHAR** w;
2827  BYTE** b;
2828  } cnv;
2829  cnv.b = bdst;
2830 
2831  size_t len = 0;
2832  *cnv.w = ConvertUtf8ToWCharAlloc(value, &len);
2833  if (!*cnv.w || (len > UINT32_MAX / sizeof(WCHAR)))
2834  {
2835  WLog_ERR(TAG, "license->ProductInfo: %s == %p || %" PRIu32 " > UINT32_MAX", what, *cnv.w,
2836  len);
2837  return FALSE;
2838  }
2839  *dstLen = (UINT32)(len * sizeof(WCHAR));
2840  return TRUE;
2841 }
2842 
2843 BOOL license_server_configure(rdpLicense* license)
2844 {
2845  wStream* s = NULL;
2846  UINT32 algs[] = { KEY_EXCHANGE_ALG_RSA };
2847 
2848  WINPR_ASSERT(license);
2849  WINPR_ASSERT(license->rdp);
2850 
2851  const rdpSettings* settings = license->rdp->settings;
2852 
2853  const char* CompanyName =
2854  freerdp_settings_get_string(settings, FreeRDP_ServerLicenseCompanyName);
2855 
2856  const char* ProductName =
2857  freerdp_settings_get_string(settings, FreeRDP_ServerLicenseProductName);
2858  const UINT32 ProductVersion =
2859  freerdp_settings_get_uint32(settings, FreeRDP_ServerLicenseProductVersion);
2860  const UINT32 issuerCount =
2861  freerdp_settings_get_uint32(settings, FreeRDP_ServerLicenseProductIssuersCount);
2862 
2863  const void* ptr = freerdp_settings_get_pointer(settings, FreeRDP_ServerLicenseProductIssuers);
2864  const char** issuers = WINPR_REINTERPRET_CAST(ptr, const void*, const char**);
2865 
2866  WINPR_ASSERT(CompanyName);
2867  WINPR_ASSERT(ProductName);
2868  WINPR_ASSERT(ProductVersion > 0);
2869  WINPR_ASSERT(issuers || (issuerCount == 0));
2870 
2871  if (!license_ensure_state(license, LICENSE_STATE_INITIAL, LICENSE_REQUEST))
2872  return FALSE;
2873 
2874  license->ProductInfo->dwVersion = ProductVersion;
2875  if (!license_set_string("pbCompanyName", CompanyName, &license->ProductInfo->pbCompanyName,
2876  &license->ProductInfo->cbCompanyName))
2877  return FALSE;
2878 
2879  if (!license_set_string("pbProductId", ProductName, &license->ProductInfo->pbProductId,
2880  &license->ProductInfo->cbProductId))
2881  return FALSE;
2882 
2883  if (!license_read_binary_blob_data(license->KeyExchangeList, BB_KEY_EXCHG_ALG_BLOB, algs,
2884  sizeof(algs)))
2885  return FALSE;
2886 
2887  if (!freerdp_certificate_read_server_cert(license->certificate, settings->ServerCertificate,
2888  settings->ServerCertificateLength))
2889  return FALSE;
2890 
2891  s = Stream_New(NULL, 1024);
2892  if (!s)
2893  return FALSE;
2894  else
2895  {
2896  BOOL r = FALSE;
2897  SSIZE_T res =
2898  freerdp_certificate_write_server_cert(license->certificate, CERT_CHAIN_VERSION_2, s);
2899  if (res >= 0)
2900  r = license_read_binary_blob_data(license->ServerCertificate, BB_CERTIFICATE_BLOB,
2901  Stream_Buffer(s), Stream_GetPosition(s));
2902 
2903  Stream_Free(s, TRUE);
2904  if (!r)
2905  return FALSE;
2906  }
2907 
2908  if (!license_scope_list_resize(license->ScopeList, issuerCount))
2909  return FALSE;
2910  for (size_t x = 0; x < issuerCount; x++)
2911  {
2912  LICENSE_BLOB* blob = license->ScopeList->array[x];
2913  const char* name = issuers[x];
2914  const size_t length = strnlen(name, UINT16_MAX) + 1;
2915  if ((length == 0) || (length > UINT16_MAX))
2916  {
2917  WLog_WARN(TAG,
2918  "%s: Invalid issuer at position %" PRIuz ": length 0 < %" PRIuz " <= %" PRIu16
2919  " ['%s']",
2920  x, length, UINT16_MAX, name);
2921  return FALSE;
2922  }
2923  if (!license_read_binary_blob_data(blob, BB_SCOPE_BLOB, name, length))
2924  return FALSE;
2925  }
2926 
2927  return license_set_state(license, LICENSE_STATE_CONFIGURED);
2928 }
2929 
2930 rdpLicense* license_get(rdpContext* context)
2931 {
2932  WINPR_ASSERT(context);
2933  WINPR_ASSERT(context->rdp);
2934  return context->rdp->license;
2935 }
FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.
FREERDP_API const void * freerdp_settings_get_pointer(const rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id)
Returns a immutable pointer settings value.
FREERDP_API const char * freerdp_settings_get_string(const rdpSettings *settings, FreeRDP_Settings_Keys_String id)
Returns a immutable string settings value.