Initial commit - from Precise source
[freerdp-ubuntu-pcb-backport.git] / libfreerdp-core / license.c
1 /**
2  * FreeRDP: A Remote Desktop Protocol Client
3  * RDP Licensing
4  *
5  * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6  *
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
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
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.
18  */
19
20 #include "redirection.h"
21
22 #include "license.h"
23
24 #ifdef WITH_DEBUG_LICENSE
25 static const char* const LICENSE_MESSAGE_STRINGS[] =
26 {
27                 "",
28                 "License Request",
29                 "Platform Challenge",
30                 "New License",
31                 "Upgrade License",
32                 "", "", "", "", "", "",
33                 "", "", "", "", "", "",
34                 "",
35                 "License Info",
36                 "New License Request",
37                 "",
38                 "Platform Challenge Response",
39                 "", "", "", "", "", "", "", "", "",
40                 "Error Alert"
41 };
42
43 static const char* const error_codes[] =
44 {
45         "ERR_UNKNOWN",
46         "ERR_INVALID_SERVER_CERTIFICATE",
47         "ERR_NO_LICENSE",
48         "ERR_INVALID_MAC",
49         "ERR_INVALID_SCOPE",
50         "ERR_UNKNOWN",
51         "ERR_NO_LICENSE_SERVER",
52         "STATUS_VALID_CLIENT",
53         "ERR_INVALID_CLIENT",
54         "ERR_UNKNOWN",
55         "ERR_UNKNOWN",
56         "ERR_INVALID_PRODUCT_ID",
57         "ERR_INVALID_MESSAGE_LENGTH"
58 };
59
60 static const char* const  state_transitions[] =
61 {
62         "ST_UNKNOWN",
63         "ST_TOTAL_ABORT",
64         "ST_NO_TRANSITION",
65         "ST_RESET_PHASE_TO_START",
66         "ST_RESEND_LAST_MESSAGE"
67 };
68 #endif
69
70 /**
71  * Read a licensing preamble.\n
72  * @msdn{cc240480}
73  * @param s stream
74  * @param bMsgType license message type
75  * @param flags message flags
76  * @param wMsgSize message size
77  */
78
79 void license_read_preamble(STREAM* s, uint8* bMsgType, uint8* flags, uint16* wMsgSize)
80 {
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) */
85 }
86
87 /**
88  * Write a licensing preamble.\n
89  * @msdn{cc240480}
90  * @param s stream
91  * @param bMsgType license message type
92  * @param flags message flags
93  * @param wMsgSize message size
94  */
95
96 void license_write_preamble(STREAM* s, uint8 bMsgType, uint8 flags, uint16 wMsgSize)
97 {
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) */
102 }
103
104 /**
105  * Initialize a license packet stream.\n
106  * @param license license module
107  * @return stream
108  */
109
110 STREAM* license_send_stream_init(rdpLicense* license)
111 {
112         STREAM* s;
113         s = transport_send_stream_init(license->rdp->transport, 4096);
114         stream_seek(s, LICENSE_PACKET_HEADER_MAX_LENGTH);
115         return s;
116 }
117
118 /**
119  * Send an RDP licensing packet.\n
120  * @msdn{cc240479}
121  * @param license license module
122  * @param s stream
123  */
124
125 boolean license_send(rdpLicense* license, STREAM* s, uint8 type)
126 {
127         int length;
128         uint8 flags;
129         uint16 wMsgSize;
130         uint16 sec_flags;
131
132         DEBUG_LICENSE("Sending %s Packet", LICENSE_MESSAGE_STRINGS[type & 0x1F]);
133
134         length = stream_get_length(s);
135         stream_set_pos(s, 0);
136
137         sec_flags = SEC_LICENSE_PKT;
138         wMsgSize = length - LICENSE_PACKET_HEADER_MAX_LENGTH + 4;
139         /**
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.
142          */
143         flags = PREAMBLE_VERSION_3_0;
144
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);
148
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);
152 #endif
153
154         stream_set_pos(s, length);
155         if (transport_write(license->rdp->transport, s) < 0)
156                 return false;
157
158         return true;
159 }
160
161 /**
162  * Receive an RDP licensing packet.\n
163  * @msdn{cc240479}
164  * @param license license module
165  * @param s stream
166  */
167
168 boolean license_recv(rdpLicense* license, STREAM* s)
169 {
170         uint16 length;
171         uint16 channelId;
172         uint16 sec_flags;
173         uint8 flags;
174         uint8 bMsgType;
175         uint16 wMsgSize;
176
177         if (!rdp_read_header(license->rdp, s, &length, &channelId))
178         {
179                 printf("Incorrect RDP header.\n");
180                 return false;
181         }
182
183         rdp_read_security_header(s, &sec_flags);
184         if (!(sec_flags & SEC_LICENSE_PKT))
185         {
186                 stream_rewind(s, RDP_SECURITY_HEADER_LENGTH);
187                 if (rdp_recv_out_of_sequence_pdu(license->rdp, s) != true)
188                 {
189                         printf("Unexpected license packet.\n");
190                         return false;
191                 }
192                 return true;
193         }
194
195         license_read_preamble(s, &bMsgType, &flags, &wMsgSize); /* preamble (4 bytes) */
196
197         DEBUG_LICENSE("Receiving %s Packet", LICENSE_MESSAGE_STRINGS[bMsgType & 0x1F]);
198
199         switch (bMsgType)
200         {
201                 case LICENSE_REQUEST:
202                         license_read_license_request_packet(license, s);
203                         license_send_new_license_request_packet(license);
204                         break;
205
206                 case PLATFORM_CHALLENGE:
207                         license_read_platform_challenge_packet(license, s);
208                         license_send_platform_challenge_response_packet(license);
209                         break;
210
211                 case NEW_LICENSE:
212                         license_read_new_license_packet(license, s);
213                         break;
214
215                 case UPGRADE_LICENSE:
216                         license_read_upgrade_license_packet(license, s);
217                         break;
218
219                 case ERROR_ALERT:
220                         license_read_error_alert_packet(license, s);
221                         break;
222
223                 default:
224                         printf("invalid bMsgType:%d\n", bMsgType);
225                         return false;
226         }
227
228         return true;
229 }
230
231 void license_generate_randoms(rdpLicense* license)
232 {
233 #if 0
234         crypto_nonce(license->client_random, CLIENT_RANDOM_LENGTH); /* ClientRandom */
235         crypto_nonce(license->premaster_secret, PREMASTER_SECRET_LENGTH); /* PremasterSecret */
236 #else
237         memset(license->client_random, 0, CLIENT_RANDOM_LENGTH); /* ClientRandom */
238         memset(license->premaster_secret, 0, PREMASTER_SECRET_LENGTH); /* PremasterSecret */
239 #endif
240 }
241
242 /**
243  * Generate License Cryptographic Keys.
244  * @param license license module
245  */
246
247 void license_generate_keys(rdpLicense* license)
248 {
249         security_master_secret(license->premaster_secret, license->client_random,
250                         license->server_random, license->master_secret); /* MasterSecret */
251
252         security_session_key_blob(license->master_secret, license->client_random,
253                         license->server_random, license->session_key_blob); /* SessionKeyBlob */
254
255         security_mac_salt_key(license->session_key_blob, license->client_random,
256                         license->server_random, license->mac_salt_key); /* MacSaltKey */
257
258         security_licensing_encryption_key(license->session_key_blob, license->client_random,
259                         license->server_random, license->licensing_encryption_key); /* LicensingEncryptionKey */
260
261 #ifdef WITH_DEBUG_LICENSE
262         printf("ClientRandom:\n");
263         freerdp_hexdump(license->client_random, CLIENT_RANDOM_LENGTH);
264
265         printf("ServerRandom:\n");
266         freerdp_hexdump(license->server_random, SERVER_RANDOM_LENGTH);
267
268         printf("PremasterSecret:\n");
269         freerdp_hexdump(license->premaster_secret, PREMASTER_SECRET_LENGTH);
270
271         printf("MasterSecret:\n");
272         freerdp_hexdump(license->master_secret, MASTER_SECRET_LENGTH);
273
274         printf("SessionKeyBlob:\n");
275         freerdp_hexdump(license->session_key_blob, SESSION_KEY_BLOB_LENGTH);
276
277         printf("MacSaltKey:\n");
278         freerdp_hexdump(license->mac_salt_key, MAC_SALT_KEY_LENGTH);
279
280         printf("LicensingEncryptionKey:\n");
281         freerdp_hexdump(license->licensing_encryption_key, LICENSING_ENCRYPTION_KEY_LENGTH);
282 #endif
283 }
284
285 /**
286  * Generate Unique Hardware Identifier (CLIENT_HARDWARE_ID).\n
287  * @param license license module
288  */
289
290 void license_generate_hwid(rdpLicense* license)
291 {
292         CryptoMd5 md5;
293         uint8* mac_address;
294
295         memset(license->hwid, 0, HWID_LENGTH);
296         mac_address = license->rdp->transport->tcp->mac_address;
297
298         md5 = crypto_md5_init();
299         crypto_md5_update(md5, mac_address, 6);
300         crypto_md5_final(md5, &license->hwid[HWID_PLATFORM_ID_LENGTH]);
301 }
302
303 void license_encrypt_premaster_secret(rdpLicense* license)
304 {
305         uint8* encrypted_premaster_secret;
306 #if 0
307         int key_length;
308         uint8* modulus;
309         uint8* exponent;
310         rdpCertificate *certificate;
311
312         if (license->server_certificate->length)
313                 certificate = license->certificate;
314         else
315                 certificate = license->rdp->settings->server_cert;
316
317         exponent = certificate->cert_info.exponent;
318         modulus = certificate->cert_info.modulus.data;
319         key_length = certificate->cert_info.modulus.length;
320
321 #ifdef WITH_DEBUG_LICENSE
322         printf("modulus (%d bits):\n", key_length * 8);
323         freerdp_hexdump(modulus, key_length);
324
325         printf("exponent:\n");
326         freerdp_hexdump(exponent, 4);
327 #endif
328
329         encrypted_premaster_secret = (uint8*) xmalloc(MODULUS_MAX_SIZE);
330         memset(encrypted_premaster_secret, 0, MODULUS_MAX_SIZE);
331
332         crypto_rsa_public_encrypt(license->premaster_secret, PREMASTER_SECRET_LENGTH,
333                         key_length, modulus, exponent, encrypted_premaster_secret);
334
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;
338 #else
339         encrypted_premaster_secret = (uint8*) xmalloc(MODULUS_MAX_SIZE);
340         memset(encrypted_premaster_secret, 0, MODULUS_MAX_SIZE);
341
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;
345 #endif
346 }
347
348 void license_decrypt_platform_challenge(rdpLicense* license)
349 {
350         CryptoRc4 rc4;
351
352         license->platform_challenge->data =
353                         (uint8*) xmalloc(license->encrypted_platform_challenge->length);
354         license->platform_challenge->length =
355                         license->encrypted_platform_challenge->length;
356
357         rc4 = crypto_rc4_init(license->licensing_encryption_key, LICENSING_ENCRYPTION_KEY_LENGTH);
358
359         crypto_rc4(rc4, license->encrypted_platform_challenge->length,
360                         license->encrypted_platform_challenge->data,
361                         license->platform_challenge->data);
362
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);
367
368         printf("platform challenge:\n");
369         freerdp_hexdump(license->platform_challenge->data, license->platform_challenge->length);
370 #endif
371
372         crypto_rc4_free(rc4);
373 }
374
375 /**
376  * Read Product Information (PRODUCT_INFO).\n
377  * @msdn{cc241915}
378  * @param s stream
379  * @param productInfo product information
380  */
381
382 void license_read_product_info(STREAM* s, PRODUCT_INFO* productInfo)
383 {
384         stream_read_uint32(s, productInfo->dwVersion); /* dwVersion (4 bytes) */
385
386         stream_read_uint32(s, productInfo->cbCompanyName); /* cbCompanyName (4 bytes) */
387
388         productInfo->pbCompanyName = (uint8*) xmalloc(productInfo->cbCompanyName);
389         stream_read(s, productInfo->pbCompanyName, productInfo->cbCompanyName);
390
391         stream_read_uint32(s, productInfo->cbProductId); /* cbProductId (4 bytes) */
392
393         productInfo->pbProductId = (uint8*) xmalloc(productInfo->cbProductId);
394         stream_read(s, productInfo->pbProductId, productInfo->cbProductId);
395 }
396
397 /**
398  * Allocate New Product Information (PRODUCT_INFO).\n
399  * @msdn{cc241915}
400  * @return new product information
401  */
402
403 PRODUCT_INFO* license_new_product_info()
404 {
405         PRODUCT_INFO* productInfo;
406
407         productInfo = (PRODUCT_INFO*) xmalloc(sizeof(PRODUCT_INFO));
408
409         productInfo->dwVersion = 0;
410         productInfo->cbCompanyName = 0;
411         productInfo->pbCompanyName = NULL;
412         productInfo->cbProductId = 0;
413         productInfo->pbProductId = NULL;
414
415         return productInfo;
416 }
417
418 /**
419  * Free Product Information (PRODUCT_INFO).\n
420  * @msdn{cc241915}
421  * @param productInfo product information
422  */
423
424 void license_free_product_info(PRODUCT_INFO* productInfo)
425 {
426         if (productInfo->pbCompanyName != NULL)
427                 xfree(productInfo->pbCompanyName);
428
429         if (productInfo->pbProductId != NULL)
430                 xfree(productInfo->pbProductId);
431
432         xfree(productInfo);
433 }
434
435 /**
436  * Read License Binary Blob (LICENSE_BINARY_BLOB).\n
437  * @msdn{cc240481}
438  * @param s stream
439  * @param blob license binary blob
440  */
441
442 void license_read_binary_blob(STREAM* s, LICENSE_BLOB* blob)
443 {
444         uint16 wBlobType;
445
446         stream_read_uint16(s, wBlobType); /* wBlobType (2 bytes) */
447         stream_read_uint16(s, blob->length); /* wBlobLen (2 bytes) */
448
449         /*
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
452          */
453         if (blob->type != BB_ANY_BLOB && blob->length == 0)
454                 return;
455
456         if (blob->type != wBlobType && blob->type != BB_ANY_BLOB)
457         {
458                 printf("license binary blob type (%x) does not match expected type (%x).\n", wBlobType, blob->type);
459         }
460
461         blob->type = wBlobType;
462         blob->data = (uint8*) xmalloc(blob->length);
463
464         stream_read(s, blob->data, blob->length); /* blobData */
465 }
466
467 /**
468  * Write License Binary Blob (LICENSE_BINARY_BLOB).\n
469  * @msdn{cc240481}
470  * @param s stream
471  * @param blob license binary blob
472  */
473
474 void license_write_binary_blob(STREAM* s, LICENSE_BLOB* blob)
475 {
476         stream_write_uint16(s, blob->type); /* wBlobType (2 bytes) */
477         stream_write_uint16(s, blob->length); /* wBlobLen (2 bytes) */
478
479         if (blob->length > 0)
480                 stream_write(s, blob->data, blob->length); /* blobData */
481 }
482
483 void license_write_padded_binary_blob(STREAM* s, LICENSE_BLOB* blob)
484 {
485         uint16 pad_len;
486
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) */
490
491         if (blob->length > 0)
492                 stream_write(s, blob->data, blob->length); /* blobData */
493
494         stream_write_zero(s, pad_len);
495 }
496
497 /**
498  * Allocate New License Binary Blob (LICENSE_BINARY_BLOB).\n
499  * @msdn{cc240481}
500  * @return new license binary blob
501  */
502
503 LICENSE_BLOB* license_new_binary_blob(uint16 type)
504 {
505         LICENSE_BLOB* blob;
506
507         blob = (LICENSE_BLOB*) xmalloc(sizeof(LICENSE_BLOB));
508         blob->type = type;
509         blob->length = 0;
510         blob->data = NULL;
511
512         return blob;
513 }
514
515 /**
516  * Free License Binary Blob (LICENSE_BINARY_BLOB).\n
517  * @msdn{cc240481}
518  * @param blob license binary blob
519  */
520
521 void license_free_binary_blob(LICENSE_BLOB* blob)
522 {
523         if (blob->data != NULL)
524                 xfree(blob->data);
525
526         xfree(blob);
527 }
528
529 /**
530  * Read License Scope List (SCOPE_LIST).\n
531  * @msdn{cc241916}
532  * @param s stream
533  * @param scopeList scope list
534  */
535
536 void license_read_scope_list(STREAM* s, SCOPE_LIST* scopeList)
537 {
538         uint32 i;
539         uint32 scopeCount;
540
541         stream_read_uint32(s, scopeCount); /* ScopeCount (4 bytes) */
542
543         scopeList->count = scopeCount;
544         scopeList->array = (LICENSE_BLOB*) xmalloc(sizeof(LICENSE_BLOB) * scopeCount);
545
546         /* ScopeArray */
547         for (i = 0; i < scopeCount; i++)
548         {
549                 scopeList->array[i].type = BB_SCOPE_BLOB;
550                 license_read_binary_blob(s, &scopeList->array[i]);
551         }
552 }
553
554 /**
555  * Allocate New License Scope List (SCOPE_LIST).\n
556  * @msdn{cc241916}
557  * @return new scope list
558  */
559
560 SCOPE_LIST* license_new_scope_list()
561 {
562         SCOPE_LIST* scopeList;
563
564         scopeList = (SCOPE_LIST*) xmalloc(sizeof(SCOPE_LIST));
565         scopeList->count = 0;
566         scopeList->array = NULL;
567
568         return scopeList;
569 }
570
571 /**
572  * Free License Scope List (SCOPE_LIST).\n
573  * @msdn{cc241916}
574  * @param scopeList scope list
575  */
576
577 void license_free_scope_list(SCOPE_LIST* scopeList)
578 {
579         uint32 i;
580
581         for (i = 0; i < scopeList->count; i++)
582         {
583                 license_free_binary_blob(&scopeList->array[i]);
584         }
585
586         xfree(scopeList);
587 }
588
589 /**
590  * Read a LICENSE_REQUEST packet.\n
591  * @msdn{cc241914}
592  * @param license license module
593  * @param s stream
594  */
595
596 void license_read_license_request_packet(rdpLicense* license, STREAM* s)
597 {
598         /* ServerRandom (32 bytes) */
599         stream_read(s, license->server_random, 32);
600
601         /* ProductInfo */
602         license_read_product_info(s, license->product_info);
603
604         /* KeyExchangeList */
605         license_read_binary_blob(s, license->key_exchange_list);
606
607         /* ServerCertificate */
608         license_read_binary_blob(s, license->server_certificate);
609
610         /* ScopeList */
611         license_read_scope_list(s, license->scope_list);
612
613         /* Parse Server Certificate */
614         certificate_read_server_certificate(license->certificate,
615                         license->server_certificate->data, license->server_certificate->length);
616
617         license_generate_keys(license);
618         license_generate_hwid(license);
619         license_encrypt_premaster_secret(license);
620 }
621
622 /**
623  * Read a PLATFORM_CHALLENGE packet.\n
624  * @msdn{cc241921}
625  * @param license license module
626  * @param s stream
627  */
628
629 void license_read_platform_challenge_packet(rdpLicense* license, STREAM* s)
630 {
631         DEBUG_LICENSE("Receiving Platform Challenge Packet");
632
633         stream_seek(s, 4); /* ConnectFlags, Reserved (4 bytes) */
634
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;
639
640         /* MACData (16 bytes) */
641         stream_seek(s, 16);
642
643         license_decrypt_platform_challenge(license);
644 }
645
646 /**
647  * Read a NEW_LICENSE packet.\n
648  * @msdn{cc241926}
649  * @param license license module
650  * @param s stream
651  */
652
653 void license_read_new_license_packet(rdpLicense* license, STREAM* s)
654 {
655         DEBUG_LICENSE("Receiving New License Packet");
656         license->state = LICENSE_STATE_COMPLETED;
657 }
658
659 /**
660  * Read an UPGRADE_LICENSE packet.\n
661  * @msdn{cc241924}
662  * @param license license module
663  * @param s stream
664  */
665
666 void license_read_upgrade_license_packet(rdpLicense* license, STREAM* s)
667 {
668         DEBUG_LICENSE("Receiving Upgrade License Packet");
669         license->state = LICENSE_STATE_COMPLETED;
670 }
671
672 /**
673  * Read an ERROR_ALERT packet.\n
674  * @msdn{cc240482}
675  * @param license license module
676  * @param s stream
677  */
678
679 void license_read_error_alert_packet(rdpLicense* license, STREAM* s)
680 {
681         uint32 dwErrorCode;
682         uint32 dwStateTransition;
683
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 */
687
688 #ifdef WITH_DEBUG_LICENSE
689         printf("dwErrorCode: %s, dwStateTransition: %s\n",
690                         error_codes[dwErrorCode], state_transitions[dwStateTransition]);
691 #endif
692
693         if (dwErrorCode == STATUS_VALID_CLIENT)
694         {
695                 license->state = LICENSE_STATE_COMPLETED;
696                 return;
697         }
698
699         switch (dwStateTransition)
700         {
701                 case ST_TOTAL_ABORT:
702                         license->state = LICENSE_STATE_ABORTED;
703                         break;
704
705                 case ST_NO_TRANSITION:
706                         license->state = LICENSE_STATE_COMPLETED;
707                         break;
708
709                 case ST_RESET_PHASE_TO_START:
710                         license->state = LICENSE_STATE_AWAIT;
711                         break;
712
713                 case ST_RESEND_LAST_MESSAGE:
714                         break;
715
716                 default:
717                         break;
718         }
719 }
720
721 /**
722  * Write Platform ID.\n
723  * @msdn{cc241918}
724  * @param license license module
725  * @param s stream
726  */
727
728 void license_write_platform_id(rdpLicense* license, STREAM* s)
729 {
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 */
733 }
734
735 /**
736  * Write a NEW_LICENSE_REQUEST packet.\n
737  * @msdn{cc241918}
738  * @param license license module
739  * @param s stream
740  */
741
742 void license_write_new_license_request_packet(rdpLicense* license, STREAM* s)
743 {
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 */
750 }
751
752 /**
753  * Send a NEW_LICENSE_REQUEST packet.\n
754  * @msdn{cc241918}
755  * @param license license module
756  */
757
758 void license_send_new_license_request_packet(rdpLicense* license)
759 {
760         STREAM* s;
761         char* username;
762
763         s = license_send_stream_init(license);
764
765         if (license->rdp->settings->username != NULL)
766                 username = license->rdp->settings->username;
767         else
768                 username = "username";
769
770         license->client_user_name->data = (uint8*) username;
771         license->client_user_name->length = strlen(username) + 1;
772
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;
775
776         license_write_new_license_request_packet(license, s);
777
778         license_send(license, s, NEW_LICENSE_REQUEST);
779
780         license->client_user_name->data = NULL;
781         license->client_user_name->length = 0;
782
783         license->client_machine_name->data = NULL;
784         license->client_machine_name->length = 0;
785 }
786
787 /**
788  * Write Client Challenge Response Packet.\n
789  * @msdn{cc241922}
790  * @param license license module
791  * @param s stream
792  * @param mac_data signature
793  */
794
795 void license_write_platform_challenge_response_packet(rdpLicense* license, STREAM* s, uint8* mac_data)
796 {
797         /* EncryptedPlatformChallengeResponse */
798         license_write_binary_blob(s, license->encrypted_platform_challenge);
799
800         /* EncryptedHWID */
801         license_write_binary_blob(s, license->encrypted_hwid);
802
803         /* MACData */
804         stream_write(s, mac_data, 16);
805 }
806
807 /**
808  * Send Client Challenge Response Packet.\n
809  * @msdn{cc241922}
810  * @param license license module
811  */
812
813 void license_send_platform_challenge_response_packet(rdpLicense* license)
814 {
815         STREAM* s;
816         int length;
817         uint8* buffer;
818         CryptoRc4 rc4;
819         uint8 mac_data[16];
820
821         s = license_send_stream_init(license);
822         DEBUG_LICENSE("Sending Platform Challenge Response Packet");
823
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);
830         xfree(buffer);
831
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);
836
837 #ifdef WITH_DEBUG_LICENSE
838         printf("Licensing Encryption Key:\n");
839         freerdp_hexdump(license->licensing_encryption_key, 16);
840
841         printf("HardwareID:\n");
842         freerdp_hexdump(license->hwid, 20);
843
844         printf("Encrypted HardwareID:\n");
845         freerdp_hexdump(buffer, 20);
846 #endif
847
848         license->encrypted_hwid->type = BB_DATA_BLOB;
849         license->encrypted_hwid->data = buffer;
850         license->encrypted_hwid->length = HWID_LENGTH;
851
852         license_write_platform_challenge_response_packet(license, s, mac_data);
853
854         license_send(license, s, PLATFORM_CHALLENGE_RESPONSE);
855 }
856
857 /**
858  * Send Server License Error - Valid Client Packet.\n
859  * @msdn{cc241922}
860  * @param license license module
861  */
862
863 boolean license_send_valid_client_error_packet(rdpLicense* license)
864 {
865         STREAM* s;
866
867         s = license_send_stream_init(license);
868
869         stream_write_uint32(s, STATUS_VALID_CLIENT); /* dwErrorCode */
870         stream_write_uint32(s, ST_NO_TRANSITION); /* dwStateTransition */
871
872         license_write_binary_blob(s, license->error_info);
873
874         license_send(license, s, ERROR_ALERT);
875
876         return true;
877 }
878
879 /**
880  * Instantiate new license module.
881  * @param rdp RDP module
882  * @return new license module
883  */
884
885 rdpLicense* license_new(rdpRdp* rdp)
886 {
887         rdpLicense* license;
888
889         license = (rdpLicense*) xzalloc(sizeof(rdpLicense));
890
891         if (license != NULL)
892         {
893                 license->rdp = rdp;
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);
909         }
910
911         return license;
912 }
913
914 /**
915  * Free license module.
916  * @param license license module to be freed
917  */
918
919 void license_free(rdpLicense* license)
920 {
921         if (license != NULL)
922         {
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);
935                 xfree(license);
936         }
937 }
938