2 * Copyright (c) 2000-2015 Samsung Electronics Co., Ltd.
4 * Licensed under the Flora License, Version 1.1 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://floralicense.org/license/
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
25 #include <openssl/bio.h>
26 #include <openssl/evp.h>
27 #include <openssl/buffer.h>
28 #include <openssl/bn.h>
29 #include <openssl/crypto.h>
30 #include <openssl/err.h>
31 #include <openssl/pem.h>
32 #include <openssl/rsa.h>
33 #include <openssl/aes.h>
34 #include <openssl/sha.h>
37 #include <drm-tizen-apps.h>
38 #include <TADC_Util.h>
40 #include "drm_testutil.h"
42 #define _INITIALIZED 0
43 #define _UNINITIALIZED -1
45 using Binary = std::vector<unsigned char>;
47 static unsigned char g_baAESKey[32] = {
48 0xf8, 0x87, 0x0a, 0xc5, 0xd3, 0x6d, 0x44, 0x49,
49 0x03, 0x9f, 0xbd, 0x1e, 0xa8, 0x2f, 0xf6, 0xc3,
50 0xdf, 0x3b, 0x02, 0x13, 0x58, 0x1b, 0x12, 0x30,
51 0x1c, 0xd7, 0xad, 0xa5, 0x1f, 0x5d, 0x01, 0x33
55 int __initialized = _UNINITIALIZED;
59 if (__initialized != _INITIALIZED) {
60 ERR_load_crypto_strings();
61 OpenSSL_add_all_algorithms();
62 __initialized = _INITIALIZED;
66 int __get_random_bytes(char *output, int random_len)
68 FILE *fp = fopen("/dev/urandom", "r");
69 auto size = fread(output, 1, random_len, fp);
73 if (size != static_cast<size_t>(random_len))
74 return DRMTEST_ERR_IO;
76 return DRMTEST_SUCCESS;
79 int __file_copy(const char *target_path, const char *source_path)
81 int ret = DRMTEST_SUCCESS;
85 unsigned char buffer[8192];
87 source = fopen(source_path, "r");
94 target = fopen(target_path, "w");
101 while ((l1 = fread(buffer, 1, sizeof buffer, source)) > 0) {
102 l2 = fwrite(buffer, 1, l1, target);
105 if (ferror(target)) {
106 ret = DRMTEST_ERR_IO;
123 void _base64_encode(const unsigned char *input, int length, char **output)
125 *output = Base64Encode((unsigned char *)input, length);
128 void _base64_decode(const char *input, unsigned char **output, int *out_len)
130 *output = Base64Decode((char *)input, out_len);
133 char *_replace_all(char *s, const char *olds, const char *news)
135 char *result = NULL, *sr = NULL;
137 size_t oldlen = strlen(olds);
139 if (oldlen < 1) return s;
141 size_t newlen = strlen(news);
143 if (newlen != oldlen) {
144 for (i = 0; s[i] != '\0';) {
145 if (memcmp(&s[i], olds, oldlen) == 0) count++, i += oldlen;
152 result = (char *) malloc(i + 1 + count * (newlen - oldlen));
154 if (result == NULL) return NULL;
159 if (memcmp(s, olds, oldlen) == 0) {
160 memcpy(sr, news, newlen);
173 Binary _read_ro_file(const char *filename)
176 std::ifstream is(filename, std::ifstream::binary);
178 if (!is || !is.is_open())
182 int length = is.tellg();
185 Binary buffer(length + 1); /* for null-terminated */
187 is.read(reinterpret_cast<char *>(buffer.data()), length);
194 std::cerr << "Failed to read ro file: " << filename << std::endl;
199 int _create_dh_key(const char *dh_key_p_hex, const char *dh_key_g_hex,
202 int ret = DRMTEST_SUCCESS;
205 if ((pDH = DH_new()) == NULL) {
206 printf("...FAIL: DH_new() error");
207 ret = DRMTEST_ERR_CRYPTO;
211 BN_hex2bn(&(pDH->p), dh_key_p_hex);
212 BN_hex2bn(&(pDH->g), dh_key_g_hex);
214 /* Set a to run with normal modexp and b to use constant time */
215 pDH->flags &= ~DH_FLAG_NO_EXP_CONSTTIME;
218 if (!DH_generate_key(pDH)) {
219 printf("...FAIL: DH_generate_key");
220 ret = DRMTEST_ERR_CRYPTO;
227 if (ret != DRMTEST_SUCCESS && pDH != NULL)
233 int _free_dh_key(DH *pkey)
238 return DRMTEST_SUCCESS;
242 int _get_dh_hex_pubkey(const DH *pkey, char **dh_pubkey)
244 *dh_pubkey = BN_bn2hex(pkey->pub_key);
245 return DRMTEST_SUCCESS;
248 int _get_dh_shared_secret_key(const char *dh_hex_pubkey, DH *pkey,
249 unsigned char **dh_shared_secret_key, int *dh_sec_key_len)
251 int ret = DRMTEST_SUCCESS;
253 BIGNUM *pPubKey = NULL;
254 unsigned char *secret_key_buff = NULL;
255 unsigned char tmp_buff[DH_size(pkey)] = { 0, };
257 BN_hex2bn(&pPubKey, dh_hex_pubkey);
259 if (DH_compute_key(tmp_buff, pPubKey, pkey) < 0) {
260 ret = DRMTEST_ERR_CRYPTO;
264 secret_key_buff = (unsigned char *) malloc(DH_size(pkey) / 2);
266 if (secret_key_buff == NULL) {
267 ret = DRMTEST_ERR_CRYPTO;
271 memset(secret_key_buff, 0, DH_size(pkey) / 2);
273 printf("APP_DRM TEST: shared secret : ");
275 for (int i = 0; i < (DH_size(pkey) / 2); i++) {
276 secret_key_buff[i] = tmp_buff[i * 2] ^ tmp_buff[(i * 2) + 1];
277 printf("%02x", secret_key_buff[i]);
282 *dh_shared_secret_key = secret_key_buff;
283 *dh_sec_key_len = DH_size(pkey) / 2;
289 if (ret != DRMTEST_SUCCESS && secret_key_buff != NULL)
290 free(secret_key_buff);
296 int _create_right_object_without_signature(const char *ro_template_path,
297 const char *cid, const char *duid,
300 int ret = DRMTEST_SUCCESS;
301 char *cid_filled = NULL;
302 char *duid_filled = NULL;
304 auto buf = _read_ro_file(ro_template_path);
306 cid_filled = _replace_all(reinterpret_cast<char *>(buf.data()),
307 STR_PLACE_HOLDER_CID, cid);
308 duid_filled = _replace_all(cid_filled, STR_PLACE_HOLDER_DUID, duid);
310 *ro_buff = duid_filled;
312 if (cid_filled != NULL)
315 if (ret != DRMTEST_SUCCESS && duid_filled != NULL)
321 int _create_ro_signature(const char *ro_buff, const char *signer_prikey_path,
324 int ret = DRMTEST_SUCCESS;
326 EVP_PKEY *pkey = NULL;
328 const char *END_STR = "</CertificateChain>";
329 const char *tmp_end_hash_input = NULL;
330 int hash_input_size = 0;
331 unsigned char hash_value[20];
332 unsigned char sig_value[MAX_CERT_SIZE]; // enough buffer
333 unsigned int sig_len = 0;
334 char *b64_sig_value = NULL;
339 file = fopen(signer_prikey_path, "r");
342 ret = DRMTEST_ERR_IO;
346 pkey = PEM_read_PrivateKey(file, &pkey, NULL, NULL);
349 ret = DRMTEST_ERR_IO;
353 prsa = EVP_PKEY_get1_RSA(pkey);
356 ret = DRMTEST_ERR_CRYPTO;
360 // get hash input size
361 tmp_end_hash_input = strstr(ro_buff, END_STR);
362 hash_input_size = (tmp_end_hash_input - ro_buff) + strlen(END_STR);
367 SHA1_Update(&alginfo, ro_buff, hash_input_size);
368 SHA1_Final(hash_value, &alginfo);
370 // get signature value
371 if (1 != RSA_sign(NID_sha1, hash_value, 20, sig_value, &sig_len, prsa)) {
372 ret = DRMTEST_ERR_CRYPTO;
376 // convert to base64 string
377 _base64_encode(sig_value, (int) sig_len, &b64_sig_value);
379 *signature = b64_sig_value;
388 if (ret != DRMTEST_SUCCESS && b64_sig_value != NULL)
394 int _add_signature_to_ro(const char *ro_buff, const char *signature,
395 char **ro_with_signature)
397 int ret = DRMTEST_SUCCESS;
399 buff = _replace_all((char *)ro_buff, STR_PLACE_HOLDER_SIGNATURE, signature);
400 *ro_with_signature = buff;
404 int _encrypt_ro_with_dh_sec_key(const char *ro_with_signature,
405 const unsigned char *dh_secret_key, const int dh_sec_key_len,
408 int ret = DRMTEST_SUCCESS;
409 TADC_U8 key[16] = {0, };
410 TADC_U8 iv[16] = {0, };
411 int encrypted_len = 0;
412 unsigned char encrypted_buff[MAX_CERT_SIZE] = {0, };;
414 (void) dh_sec_key_len; // to prevent unused varialbe error
416 TADC_IF_MemCpy(key, dh_secret_key, 16);
417 TADC_IF_MemCpy(iv, (dh_secret_key + 16), 16);
418 ret = TADC_IF_AES_CTR(key, 16, iv, strlen(ro_with_signature),
419 (unsigned char *)ro_with_signature,
420 &encrypted_len, (unsigned char *)encrypted_buff);
423 ret = DRMTEST_ERR_CRYPTO;
427 _base64_encode(encrypted_buff, encrypted_len, encrypted_ro);
433 int _create_response_data_in_ro_response(const char *reqid,
434 const char *encrypted_ro, const char *dh_pubkey,
435 char **response_data)
437 int ret = DRMTEST_SUCCESS;
438 char tmp_buff[MAX_CERT_SIZE] = { 0, };
439 unsigned char hashed_reqid[20] = { 0, };
440 char hex_hashed_reqid[256] = { 0, };
441 unsigned char hash_value[20] = { 0, };
443 unsigned char hmac[1024 * 10] = { 0, };
444 char *hmac_base64 = NULL;
445 char *resp_data = NULL;
448 SHA_CTX alginfoForReqId;
449 SHA1_Init(&alginfoForReqId);
450 SHA1_Update(&alginfoForReqId, reqid, strlen(reqid));
451 SHA1_Final(hashed_reqid, &alginfoForReqId);
453 for (size_t i = 0; i < sizeof(hashed_reqid); i++)
454 sprintf(hex_hashed_reqid + i * 2, "%02x", hashed_reqid[i]);
456 sprintf(tmp_buff, "reqid=%s;B=%s;license=%s", hex_hashed_reqid, dh_pubkey,
462 SHA1_Update(&alginfo, tmp_buff, strlen(tmp_buff));
463 SHA1_Final(hash_value, &alginfo);
465 // encrypt hash value
466 TADC_U8 key[16] = {0, };
467 TADC_U8 iv[16] = {0, };
469 TADC_IF_MemCpy(key, g_baAESKey, 16);
470 TADC_IF_MemCpy(iv, (g_baAESKey + 16), 16);
471 ret = TADC_IF_AES_CTR(key, 16, iv, 20, hash_value, &hmac_len, hmac);
474 ret = DRMTEST_ERR_CRYPTO;
479 _base64_encode(hmac, 20, &hmac_base64);
482 strncat(tmp_buff, ";hmac=", strlen(";hmac="));
483 strncat(tmp_buff, hmac_base64, strlen(hmac_base64));
486 resp_data = (char *) malloc(strlen(tmp_buff) + 1);
488 if (resp_data == NULL) {
489 ret = DRMTEST_ERR_MEMORY;
493 memset(resp_data, 0, strlen(tmp_buff) + 1);
494 strncpy(resp_data, tmp_buff, strlen(tmp_buff));
496 *response_data = resp_data;
500 if (hmac_base64 != NULL)
503 if (ret != DRMTEST_SUCCESS && resp_data != NULL)
509 int _create_time_stamp(const unsigned char *dh_secret_key, char **time_stamp)
511 int ret = DRMTEST_SUCCESS;
513 char tmp_time_buff[128] = {0, };
514 unsigned char enc_time_buff[512] = {0, };
515 char *time_base64 = NULL;
516 int enc_time_buff_len = 0;
517 time_t now = time(NULL);
518 const struct tm *gt = gmtime(&now);
520 sprintf(tmp_time_buff, "%d-%d-%dT%d:%d:00:Z",
521 gt->tm_year + 1900, gt->tm_mon + 1, gt->tm_mday,
522 gt->tm_hour + 1, gt->tm_min + 1);
524 // encrypt time_stamp
525 TADC_U8 key[16] = {0, };
526 TADC_U8 iv[16] = {0, };
528 TADC_IF_MemCpy(key, dh_secret_key, 16);
529 TADC_IF_MemCpy(iv, (dh_secret_key + 16), 16);
530 ret = TADC_IF_AES_CTR(key, 16, iv, strlen(tmp_time_buff),
531 (unsigned char *)tmp_time_buff,
532 &enc_time_buff_len, enc_time_buff);
535 ret = DRMTEST_ERR_CRYPTO;
540 _base64_encode(enc_time_buff, enc_time_buff_len, &time_base64);
542 *time_stamp = time_base64;
545 if (ret != DRMTEST_SUCCESS && time_base64 != NULL)
551 int generate_purchase_response(char **purchase_response_buff, char **req_id)
553 int ret = DRMTEST_SUCCESS;
554 char resp_buff[1024 * 5] = {0, };
557 char random[64] = {0, };
559 const char *format1 = "<?xml version=\"1.0\">\n";
560 const char *format2 = "<response result=\"0\" message=\"\">\n";
561 const char *format3 = " <DRMType>%d</DRMType>\n";
562 const char *format4 = " <riurl>%s</riurl>\n";
563 const char *format5 = " <reqid>%s</reqid>\n";
564 const char *format6 = "</response>";
566 resp = (char *) malloc(sizeof(resp_buff));
569 ret = DRMTEST_ERR_MEMORY;
573 memset(resp, 0, sizeof(resp_buff));
575 __get_random_bytes(random, sizeof(random));
576 rid = (char *) malloc(1024);
579 ret = DRMTEST_ERR_MEMORY;
583 memset(rid, 0, 1024);
585 for (size_t i = 0; i < sizeof(random); i++)
586 sprintf(rid + i * 2, "%02x", random[i]);
588 strncat(resp_buff, format1, strlen(format1));
589 strncat(resp_buff, format2, strlen(format2));
590 strncat(resp_buff, format3, strlen(format3));
591 strncat(resp_buff, format4, strlen(format4));
592 strncat(resp_buff, format5, strlen(format5));
593 strncat(resp_buff, format6, strlen(format6));
595 sprintf(resp, resp_buff, 1, RIURL, rid);
597 *purchase_response_buff = resp;
602 if (ret != DRMTEST_SUCCESS && resp != NULL)
605 if (ret != DRMTEST_SUCCESS && rid != NULL)
611 int generate_right_object_request(const char *license_response_buff)
613 int ret = DRMTEST_SUCCESS;
614 unsigned int req_buff_len = 1024 * 5;
615 char url_buff[1024] = {0, };
616 unsigned int url_buff_len = sizeof(url_buff);
617 char *req_buff = NULL;
619 req_buff = (char *)malloc(1024 * 5);
621 if (req_buff == NULL) {
622 ret = DRMTEST_ERR_MEMORY;
626 memset(req_buff, 0, req_buff_len);
628 ret = drm_tizen_generate_license_request(license_response_buff,
629 strlen(license_response_buff),
630 req_buff, &req_buff_len, url_buff, &url_buff_len);
633 ret = DRMTEST_ERR_TIZDRM;
639 if (ret != DRMTEST_SUCCESS && req_buff != NULL)
646 int get_dh_key_from_ro_request(const char *ro_request_buff,
647 char **dh_key_p, char **dh_key_g, char **dh_key_a)
649 int ret = DRMTEST_SUCCESS;
651 const char *PFX_P = "p=";
652 const char *PFX_G = ";g=";
653 const char *PFX_A = ";A=";
654 const char *PFX_HMAC = ";hmac=";
656 const char *idx_p = strstr(ro_request_buff, PFX_P);
657 const char *idx_g = strstr(ro_request_buff, PFX_G);
658 const char *idx_a = strstr(ro_request_buff, PFX_A);
659 const char *idx_hmac = strstr(ro_request_buff, PFX_HMAC);
661 int len_p = idx_g - idx_p - strlen(PFX_P);
662 int len_g = idx_a - idx_g - strlen(PFX_G);
663 int len_a = idx_hmac - idx_a - strlen(PFX_A);
669 buff_p = (char *)malloc(len_p + 1);
671 if (buff_p == NULL) {
672 ret = DRMTEST_ERR_MEMORY;
676 memset(buff_p, 0, len_p + 1);
677 strncpy(buff_p, idx_p + strlen(PFX_P), len_p);
680 buff_g = (char *)malloc(len_g + 1);
682 if (buff_g == NULL) {
683 ret = DRMTEST_ERR_MEMORY;
687 memset(buff_g, 0, len_g + 1);
688 strncpy(buff_g, idx_g + strlen(PFX_G), len_g);
691 buff_a = (char *)malloc(len_a + 1);
693 if (buff_a == NULL) {
694 ret = DRMTEST_ERR_MEMORY;
698 memset(buff_a, 0, len_a + 1);
699 strncpy(buff_a, idx_a + strlen(PFX_A), len_a);
704 if (ret != DRMTEST_SUCCESS && buff_p != NULL)
707 if (ret != DRMTEST_SUCCESS && buff_g != NULL)
710 if (ret != DRMTEST_SUCCESS && buff_a != NULL)
716 int generate_right_object_response(const char *dh_key_p, const char *dh_key_g,
717 const char *dh_key_a,
718 const char *req_id, const char *cid,
719 const char *ro_template_path,
720 const char *duid, char **ro_response_buff)
722 int ret = DRMTEST_SUCCESS;
725 char *dh_pubkey = NULL;
726 unsigned char *dh_shared_secret_key = NULL;
727 int dh_sec_key_len = 0;
728 char *ro_buff = NULL;
729 char *ro_signature = NULL;
730 char *ro_with_signature = NULL;
731 char *encrypted_ro = NULL;
732 char *response_data = NULL;
733 char *time_stamp = NULL;
734 char *ro_resp_buff = NULL;
735 int ro_resp_buff_len = 0;
737 const char *format = "<?xml version=\"1.0\">\n"
738 "<response result=\"0\" message=\"\">\n"
739 " <responsedata>%s</responsedata>\n"
740 " <timeStamp>%s</timeStamp>\n"
743 ret = _create_dh_key(dh_key_p, dh_key_g, &pkey);
745 if (ret != DRMTEST_SUCCESS) {
749 ret = _get_dh_hex_pubkey(pkey, &dh_pubkey);
751 if (ret != DRMTEST_SUCCESS) {
755 ret = _get_dh_shared_secret_key(dh_key_a, pkey, &dh_shared_secret_key,
758 if (ret != DRMTEST_SUCCESS) {
762 ret = _create_right_object_without_signature(ro_template_path, cid, duid,
765 if (ret != DRMTEST_SUCCESS) {
769 ret = _create_ro_signature(ro_buff, RO_ISSUER_SIGNER_KEY_FILE, &ro_signature);
771 if (ret != DRMTEST_SUCCESS) {
775 ret = _add_signature_to_ro(ro_buff, ro_signature, &ro_with_signature);
777 if (ret != DRMTEST_SUCCESS) {
781 //printf("...right object:\n%s\n", ro_with_signature);
783 ret = _encrypt_ro_with_dh_sec_key(ro_with_signature, dh_shared_secret_key,
787 if (ret != DRMTEST_SUCCESS) {
791 ret = _create_response_data_in_ro_response(req_id, encrypted_ro, dh_pubkey,
794 if (ret != DRMTEST_SUCCESS) {
798 ret = _create_time_stamp(dh_shared_secret_key, &time_stamp);
800 if (ret != DRMTEST_SUCCESS) {
804 ro_resp_buff_len = strlen(format) + strlen(response_data) + strlen(
806 ro_resp_buff = (char *) malloc(ro_resp_buff_len);
808 if (ro_resp_buff == NULL) {
809 ret = DRMTEST_ERR_MEMORY;
813 memset(ro_resp_buff, 0, ro_resp_buff_len);
814 sprintf(ro_resp_buff, format, response_data, time_stamp);
816 *ro_response_buff = ro_resp_buff;
823 if (dh_pubkey != NULL)
826 if (dh_shared_secret_key != NULL)
827 free(dh_shared_secret_key);
832 if (ro_signature != NULL)
835 if (ro_with_signature != NULL)
836 free(ro_with_signature);
838 if (encrypted_ro != NULL)
841 if (response_data != NULL)
844 if (time_stamp != NULL)
847 if (ret != DRMTEST_SUCCESS && ro_resp_buff != NULL)
854 int is_identical_files(const char *file1, const char *file2, int *identical)
856 int ret = DRMTEST_SUCCESS;
858 FILE *fp1 = NULL, *fp2 = NULL;
861 fp1 = fopen(file1, "r");
864 ret = DRMTEST_ERR_IO;
868 fp2 = fopen(file2, "r");
871 ret = DRMTEST_ERR_IO;
878 while ((ch1 != EOF) && (ch2 != EOF) && (ch1 == ch2)) {
884 *identical = DRMTEST_IDENTICAL;
886 *identical = DRMTEST_NOTIDENTICAL;