LCOV - code coverage report
Current view: top level - media_tools - crypt_tools.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 304 447 68.0 %
Date: 2021-04-29 23:48:07 Functions: 12 14 85.7 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2000-2021
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / Media Tools sub-project
       9             :  *
      10             :  *  GPAC is free software; you can redistribute it and/or modify
      11             :  *  it under the terms of the GNU Lesser General Public License as published by
      12             :  *  the Free Software Foundation; either version 2, or (at your option)
      13             :  *  any later version.
      14             :  *
      15             :  *  GPAC is distributed in the hope that it will be useful,
      16             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :  *  GNU Lesser General Public License for more details.
      19             :  *
      20             :  *  You should have received a copy of the GNU Lesser General Public
      21             :  *  License along with this library; see the file COPYING.  If not, write to
      22             :  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
      23             :  *
      24             :  */
      25             : 
      26             : 
      27             : 
      28             : #include <gpac/crypt_tools.h>
      29             : #include <gpac/xml.h>
      30             : #include <gpac/base_coding.h>
      31             : #include <gpac/constants.h>
      32             : #include <gpac/filters.h>
      33             : #include <gpac/network.h>
      34             : 
      35             : 
      36             : #if !defined(GPAC_DISABLE_CRYPTO)
      37             : 
      38         230 : static u32 cryptinfo_get_crypt_type(char *cr_type)
      39             : {
      40         230 :         if (!stricmp(cr_type, "ISMA") || !stricmp(cr_type, "iAEC"))
      41             :                 return GF_CRYPT_TYPE_ISMA;
      42         219 :         else if (!stricmp(cr_type, "CENC AES-CTR") || !stricmp(cr_type, "cenc"))
      43             :                 return GF_CRYPT_TYPE_CENC;
      44          80 :         else if (!stricmp(cr_type, "piff"))
      45             :                 return GF_CRYPT_TYPE_PIFF;
      46          80 :         else if (!stricmp(cr_type, "CENC AES-CBC") || !stricmp(cr_type, "cbc1"))
      47             :                 return GF_CRYPT_TYPE_CBC1;
      48          66 :         else if (!stricmp(cr_type, "ADOBE") || !stricmp(cr_type, "adkm"))
      49             :                 return GF_CRYPT_TYPE_ADOBE;
      50          56 :         else if (!stricmp(cr_type, "CENC AES-CTR Pattern") || !stricmp(cr_type, "cens"))
      51             :                 return GF_CRYPT_TYPE_CENS;
      52          30 :         else if (!stricmp(cr_type, "CENC AES-CBC Pattern") || !stricmp(cr_type, "cbcs"))
      53             :                 return GF_CRYPT_TYPE_CBCS;
      54           0 :         else if (!stricmp(cr_type, "OMA"))
      55             :                 return GF_ISOM_OMADRM_SCHEME;
      56             : 
      57           0 :         GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[CENC] Unrecognized crypto type %s\n", cr_type));
      58             :         return 0;
      59             : }
      60             : 
      61        2429 : static void cryptinfo_node_start(void *sax_cbck, const char *node_name, const char *name_space, const GF_XMLAttribute *attributes, u32 nb_attributes)
      62             : {
      63             :         GF_XMLAttribute *att;
      64             :         GF_TrackCryptInfo *tkc;
      65             :         u32 i;
      66             :         GF_CryptInfo *info = (GF_CryptInfo *)sax_cbck;
      67             : 
      68        2429 :         if (!strcmp(node_name, "OMATextHeader")) {
      69           0 :                 info->in_text_header = 1;
      70           0 :                 return;
      71             :         }
      72        2429 :         if (!strcmp(node_name, "GPACDRM")) {
      73         230 :                 for (i=0; i<nb_attributes; i++) {
      74         230 :                         att = (GF_XMLAttribute *) &attributes[i];
      75         230 :                         if (!stricmp(att->name, "type")) {
      76         230 :                                 info->def_crypt_type = cryptinfo_get_crypt_type(att->value);
      77             :                         }
      78             :                 }
      79             :                 return;
      80             :         }
      81             : 
      82             : 
      83        2199 :         if (!strcmp(node_name, "CrypTrack")) {
      84             :                 Bool has_key = GF_FALSE;
      85             :                 Bool has_common_key = GF_TRUE;
      86         230 :                 GF_SAFEALLOC(tkc, GF_TrackCryptInfo);
      87         230 :                 if (!tkc) {
      88           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[CENC] Cannnot allocate crypt track, skipping\n"));
      89           0 :                         info->last_parse_error = GF_OUT_OF_MEM;
      90           0 :                         return;
      91             :                 }
      92             :                 //by default track is encrypted
      93         230 :                 tkc->IsEncrypted = 1;
      94         230 :                 tkc->sai_saved_box_type = GF_ISOM_BOX_TYPE_SENC;
      95         230 :                 tkc->scheme_type = info->def_crypt_type;
      96             : 
      97             :                 //allocate a key to store the default values in single-key mode
      98         230 :                 tkc->keys = gf_malloc(sizeof(GF_CryptKeyInfo));
      99         230 :                 if (!tkc->keys) {
     100           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[CENC] Cannnot allocate key IDs\n"));
     101           0 :                         gf_free(tkc);
     102           0 :                         info->last_parse_error = GF_OUT_OF_MEM;
     103           0 :                         return;
     104             :                 }
     105             :                 memset(tkc->keys, 0, sizeof(GF_CryptKeyInfo));
     106         230 :                 gf_list_add(info->tcis, tkc);
     107             : 
     108        1550 :                 for (i=0; i<nb_attributes; i++) {
     109        1320 :                         att = (GF_XMLAttribute *) &attributes[i];
     110        1320 :                         if (!stricmp(att->name, "trackID") || !stricmp(att->name, "ID")) {
     111         230 :                                 if (!strcmp(att->value, "*")) info->has_common_key = 1;
     112             :                                 else {
     113         230 :                                         tkc->trackID = atoi(att->value);
     114             :                                         has_common_key = GF_FALSE;
     115             :                                 }
     116             :                         }
     117        1090 :                         else if (!stricmp(att->name, "type")) {
     118           0 :                                 tkc->scheme_type = cryptinfo_get_crypt_type(att->value);
     119             :                         }
     120        1090 :                         else if (!stricmp(att->name, "forceType")) {
     121           0 :                                 tkc->force_type = GF_TRUE;
     122             :                         }
     123        1090 :                         else if (!stricmp(att->name, "key")) {
     124             :                                 GF_Err e;
     125             :                                 has_key = GF_TRUE;
     126          11 :                                 e = gf_bin128_parse(att->value, tkc->keys[0].key );
     127          11 :                 if (e != GF_OK) {
     128           0 :                     GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Cannnot parse key value in CrypTrack\n"));
     129           0 :                                         info->last_parse_error = GF_BAD_PARAM;
     130           0 :                     return;
     131             :                 }
     132             :                         }
     133        1079 :                         else if (!stricmp(att->name, "salt")) {
     134             :                                 u32 len, j;
     135          11 :                                 char *sKey = att->value;
     136          11 :                                 if (!strnicmp(sKey, "0x", 2)) sKey += 2;
     137          11 :                                 len = (u32) strlen(sKey);
     138          99 :                                 for (j=0; j<len; j+=2) {
     139             :                                         char szV[5];
     140             :                                         u32 v;
     141          88 :                                         sprintf(szV, "%c%c", sKey[j], sKey[j+1]);
     142          88 :                                         sscanf(szV, "%x", &v);
     143          88 :                                         tkc->keys[0].IV[j/2] = v;
     144          88 :                                         if (j>=30) break;
     145             :                                 }
     146             :                         }
     147        1068 :                         else if (!stricmp(att->name, "kms_URI") || !stricmp(att->name, "rightsIssuerURL")) {
     148          11 :                                 if (tkc->KMS_URI) gf_free(tkc->KMS_URI);
     149          11 :                                 tkc->KMS_URI = gf_strdup(att->value);
     150             :                         }
     151        1057 :                         else if (!stricmp(att->name, "scheme_URI") || !stricmp(att->name, "contentID")) {
     152           0 :                                 if (tkc->Scheme_URI) gf_free(tkc->Scheme_URI);
     153           0 :                                 tkc->Scheme_URI = gf_strdup(att->value);
     154             :                         }
     155        1057 :                         else if (!stricmp(att->name, "selectiveType")) {
     156          44 :                                 if (!stricmp(att->value, "Rap")) tkc->sel_enc_type = GF_CRYPT_SELENC_RAP;
     157           8 :                                 else if (!stricmp(att->value, "Non-Rap")) tkc->sel_enc_type = GF_CRYPT_SELENC_NON_RAP;
     158           8 :                                 else if (!stricmp(att->value, "Rand")) tkc->sel_enc_type = GF_CRYPT_SELENC_RAND;
     159           8 :                                 else if (!strnicmp(att->value, "Rand", 4)) {
     160           0 :                                         tkc->sel_enc_type = GF_CRYPT_SELENC_RAND_RANGE;
     161           0 :                                         tkc->sel_enc_range = atoi(&att->value[4]);
     162             :                                 }
     163           8 :                                 else if (sscanf(att->value, "%u", &tkc->sel_enc_range)==1) {
     164           0 :                                         if (tkc->sel_enc_range==1) tkc->sel_enc_range = 0;
     165           0 :                                         else tkc->sel_enc_type = GF_CRYPT_SELENC_RANGE;
     166             :                                 }
     167           8 :                                 else if (!strnicmp(att->value, "Preview", 7)) {
     168           0 :                                         tkc->sel_enc_type = GF_CRYPT_SELENC_PREVIEW;
     169             :                                 }
     170           8 :                                 else if (!strnicmp(att->value, "Clear", 5)) {
     171           0 :                                         tkc->sel_enc_type = GF_CRYPT_SELENC_CLEAR;
     172             :                                 }
     173           8 :                                 else if (!strnicmp(att->value, "ForceClear", 10)) {
     174           8 :                                         char *sep = strchr(att->value, '=');
     175          16 :                                         if (sep) tkc->sel_enc_range = atoi(sep+1);
     176           8 :                                         tkc->sel_enc_type = GF_CRYPT_SELENC_CLEAR_FORCED;
     177             :                                 }
     178           0 :                                 else if (!stricmp(att->value, "None")) {
     179             :                                 } else {
     180           0 :                                         GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Unrecognized selective mode %s, ignoring\n", att->value));
     181             :                                 }
     182             :                         }
     183        1013 :                         else if (!stricmp(att->name, "clearStsd")) {
     184           6 :                                 if (!strcmp(att->value, "none")) tkc->force_clear_stsd_idx = 0;
     185           6 :                                 else if (!strcmp(att->value, "before")) tkc->force_clear_stsd_idx = 1;
     186           4 :                                 else if (!strcmp(att->value, "after")) tkc->force_clear_stsd_idx = 2;
     187             :                                 else {
     188           0 :                                         GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Unrecognized clear stsd type %s, defaulting to no stsd for clear samples\n", att->value));
     189             :                                 }
     190             :                         }
     191        1007 :                         else if (!stricmp(att->name, "Preview")) {
     192           0 :                                 tkc->sel_enc_type = GF_CRYPT_SELENC_PREVIEW;
     193           0 :                                 sscanf(att->value, "%u", &tkc->sel_enc_range);
     194             :                         }
     195        1007 :                         else if (!stricmp(att->name, "ipmpType")) {
     196           0 :                                 if (!stricmp(att->value, "None")) tkc->ipmp_type = 0;
     197           0 :                                 else if (!stricmp(att->value, "IPMP")) tkc->sel_enc_type = 1;
     198           0 :                                 else if (!stricmp(att->value, "IPMPX")) tkc->sel_enc_type = 2;
     199             :                         }
     200        1007 :                         else if (!stricmp(att->name, "ipmpDescriptorID")) tkc->ipmp_desc_id = atoi(att->value);
     201        1007 :                         else if (!stricmp(att->name, "encryptionMethod")) {
     202           0 :                                 if (!strcmp(att->value, "AES_128_CBC")) tkc->encryption = 1;
     203           0 :                                 else if (!strcmp(att->value, "None")) tkc->encryption = 0;
     204           0 :                                 else if (!strcmp(att->value, "AES_128_CTR") || !strcmp(att->value, "default")) tkc->encryption = 2;
     205             :                                 else {
     206           0 :                                         GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Unrecognized encryption algo %s, ignoring\n", att->value));
     207             :                                 }
     208             :                         }
     209        1007 :                         else if (!stricmp(att->name, "transactionID")) {
     210           0 :                                 if (strlen(att->value)<=16) strcpy(tkc->TransactionID, att->value);
     211             :                         }
     212        1007 :                         else if (!stricmp(att->name, "textualHeaders")) {
     213             :                         }
     214        1007 :                         else if (!stricmp(att->name, "IsEncrypted")) {
     215         219 :                                 if (!stricmp(att->value, "1"))
     216         219 :                                         tkc->IsEncrypted = 1;
     217             :                                 else
     218           0 :                                         tkc->IsEncrypted = 0;
     219             :                         }
     220         788 :                         else if (!stricmp(att->name, "IV_size")) {
     221         388 :                                 tkc->keys[0].IV_size = atoi(att->value);
     222             :                         }
     223         594 :                         else if (!stricmp(att->name, "first_IV")) {
     224         204 :                                 char *sKey = att->value;
     225         204 :                                 if (!strnicmp(sKey, "0x", 2)) sKey += 2;
     226         204 :                                 if ((strlen(sKey) == 16) || (strlen(sKey) == 32)) {
     227             :                                         u32 j;
     228        3024 :                                         for (j=0; j<strlen(sKey); j+=2) {
     229             :                                                 u32 v;
     230             :                                                 char szV[5];
     231        3024 :                                                 sprintf(szV, "%c%c", sKey[j], sKey[j+1]);
     232        3024 :                                                 sscanf(szV, "%x", &v);
     233        3024 :                                                 tkc->keys[0].IV[j/2] = v;
     234             :                                         }
     235         204 :                                         if (!tkc->keys[0].IV_size) tkc->keys[0].IV_size = (u8) strlen(sKey) / 2;
     236             :                                 }
     237             :                         }
     238         390 :                         else if (!stricmp(att->name, "saiSavedBox")) {
     239         206 :                                 if (!stricmp(att->value, "uuid_psec")) tkc->sai_saved_box_type = GF_ISOM_BOX_UUID_PSEC;
     240         194 :                                 else if (!stricmp(att->value, "senc")) tkc->sai_saved_box_type = GF_ISOM_BOX_TYPE_SENC;
     241             :                                 else {
     242           0 :                                         GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Unrecognized SAI location %s, ignoring\n", att->value));
     243             :                                 }
     244             :                         }
     245         184 :                         else if (!stricmp(att->name, "keyRoll")) {
     246          27 :                                 if (!strncmp(att->value, "idx=", 4))
     247           0 :                                         tkc->defaultKeyIdx = atoi(att->value+4);
     248          27 :                                 else if (!strncmp(att->value, "roll=", 5))
     249          26 :                                         tkc->keyRoll = atoi(att->value+5);
     250          14 :                                 else if (!strcmp(att->value, "rap"))
     251           0 :                                         tkc->roll_rap = GF_TRUE;
     252             :                                 else {
     253          14 :                                         GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Unrecognized roll parameter %s, ignoring\n", att->value));
     254             :                                 }
     255             :                         }
     256         157 :                         else if (!stricmp(att->name, "metadata")) {
     257          10 :                                 u32 l = 2 * (u32) strlen(att->value);
     258          10 :                                 tkc->metadata = gf_malloc(sizeof(char) * l);
     259          10 :                                 l = gf_base64_encode(att->value, (u32) strlen(att->value), tkc->metadata, l);
     260          10 :                                 tkc->metadata[l] = 0;
     261             :                         }
     262         147 :                         else if (!stricmp(att->name, "crypt_byte_block")) {
     263          52 :                                 tkc->crypt_byte_block = atoi(att->value);
     264             :                         }
     265         121 :                         else if (!stricmp(att->name, "skip_byte_block")) {
     266          52 :                                 tkc->skip_byte_block = atoi(att->value);
     267             :                         }
     268          95 :                         else if (!stricmp(att->name, "clear_bytes")) {
     269           4 :                                 tkc->clear_bytes = atoi(att->value);
     270             :                         }
     271          93 :                         else if (!stricmp(att->name, "constant_IV_size")) {
     272          30 :                                 tkc->keys[0].constant_IV_size = atoi(att->value);
     273          15 :                                 if ((tkc->keys[0].constant_IV_size != 8) && (tkc->keys[0].constant_IV_size != 16)) {
     274           0 :                                         GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Constant IV size %d is not 8 or 16\n", att->value));
     275             :                                 }
     276             :                         }
     277          78 :                         else if (!stricmp(att->name, "constant_IV")) {
     278          15 :                                 char *sKey = att->value;
     279          15 :                                 if (!strnicmp(sKey, "0x", 2)) sKey += 2;
     280          15 :                                 if ((strlen(sKey) == 16) || (strlen(sKey) == 32)) {
     281             :                                         u32 j;
     282         240 :                                         for (j=0; j<strlen(sKey); j+=2) {
     283             :                                                 u32 v;
     284             :                                                 char szV[5];
     285         240 :                                                 sprintf(szV, "%c%c", sKey[j], sKey[j+1]);
     286         240 :                                                 sscanf(szV, "%x", &v);
     287         240 :                                                 tkc->keys[0].IV[j/2] = v;
     288             :                                         }
     289          15 :                                         if (!tkc->keys[0].constant_IV_size) tkc->keys[0].constant_IV_size = (u8) strlen(sKey) / 2;
     290             :                                 }
     291             :                         }
     292          63 :                         else if (!stricmp(att->name, "encryptSliceHeader")) {
     293          17 :                                 tkc->allow_encrypted_slice_header = !strcmp(att->value, "yes") ? GF_TRUE : GF_FALSE;
     294             :                         }
     295          46 :                         else if (!stricmp(att->name, "blockAlign")) {
     296          32 :                                 if (!strcmp(att->value, "disable")) tkc->block_align = 1;
     297          15 :                                 else if (!strcmp(att->value, "always")) tkc->block_align = 2;
     298           0 :                                 else tkc->block_align = 0;
     299             :                         }
     300          14 :                         else if (!stricmp(att->name, "subsamples")) {
     301           1 :                                 char *val = att->value;
     302           2 :                                 while (val) {
     303           1 :                                         char *sep = strchr(val, ';');
     304           1 :                                         if (sep) sep[0] = 0;
     305           1 :                                         if (!strncmp(val, "subs=", 5)) {
     306           1 :                                                 if (tkc->subs_crypt) gf_free(tkc->subs_crypt);
     307           1 :                                                 tkc->subs_crypt = gf_strdup(val+4);
     308             :                                         }
     309           0 :                                         else if (!strncmp(val, "rand", 4)) {
     310           0 :                                                 tkc->subs_rand = 2;
     311           0 :                                                 if (val[4]=='=')
     312           0 :                                                         tkc->subs_rand = atoi(val+5);
     313             :                                         }
     314             :                                         else {
     315           0 :                                                 GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[CENC] unrecognized attribute value %s for `subsamples`, ignoring\n", val));
     316             :                                         }
     317           1 :                                         if (!sep) break;
     318           0 :                                         sep[0] = ';';
     319           0 :                                         val = sep+1;
     320             :                                 }
     321             :                         }
     322          13 :                         else if (!stricmp(att->name, "multiKey")) {
     323           3 :                                 if (!strcmp(att->value, "all") || !strcmp(att->value, "on")) tkc->multi_key = GF_TRUE;
     324           2 :                                 else if (!strcmp(att->value, "no")) tkc->multi_key = GF_FALSE;
     325             :                                 else {
     326             :                                         char *val = att->value;
     327           2 :                                         tkc->multi_key = GF_TRUE;
     328           4 :                                         while (val) {
     329           2 :                                                 char *sep = strchr(val, ';');
     330           2 :                                                 if (sep) sep[0] = 0;
     331           2 :                                                 if (!strncmp(val, "roll=", 5)) {
     332           2 :                                                         tkc->mkey_roll_plus_one = 1 + atoi(val+5);
     333             :                                                 }
     334           1 :                                                 else if (!strncmp(val, "subs=", 5)) {
     335           1 :                                                         if (tkc->mkey_subs) gf_free(tkc->mkey_subs);
     336           1 :                                                         tkc->mkey_subs = gf_strdup(val+5);
     337             :                                                 }
     338             :                                                 else {
     339           0 :                                                         GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[CENC] unrecognized attribute value %s for `multiKey`, ignoring\n", val));
     340           0 :                                                         tkc->multi_key = GF_FALSE;
     341           0 :                                                         if (sep) sep[0] = ';';
     342             :                                                         break;
     343             :                                                 }
     344           2 :                                                 if (!sep) break;
     345           0 :                                                 sep[0] = ';';
     346           0 :                                                 val = sep+1;
     347             :                                         }
     348             :                                 }
     349             :                         }
     350             :                 }
     351         230 :                 if (tkc->scheme_type==GF_CRYPT_TYPE_PIFF) {
     352           0 :                         tkc->sai_saved_box_type = GF_ISOM_BOX_UUID_PSEC;
     353             :                 }
     354         230 :                 if (has_common_key) info->has_common_key = 1;
     355             : 
     356         230 :                 if ((tkc->keys[0].IV_size != 0) && (tkc->keys[0].IV_size != 8) && (tkc->keys[0].IV_size != 16)) {
     357           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[CENC] wrong IV size %d for AES-128, using 16\n", (u32) tkc->keys[0].IV_size));
     358           0 :                         tkc->keys[0].IV_size = 16;
     359             :                 }
     360             : 
     361         230 :                 if ((tkc->scheme_type == GF_CRYPT_TYPE_CENC) || (tkc->scheme_type == GF_CRYPT_TYPE_CBC1)) {
     362         153 :                         if (tkc->crypt_byte_block || tkc->skip_byte_block) {
     363           0 :                                 GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[CENC] Using scheme type %s, crypt_byte_block and skip_byte_block shall be 0\n", gf_4cc_to_str(tkc->scheme_type) ));
     364           0 :                                 tkc->crypt_byte_block = tkc->skip_byte_block = 0;
     365             :                         }
     366             :                 }
     367             : 
     368         230 :                 if ((tkc->scheme_type == GF_CRYPT_TYPE_CENC) || (tkc->scheme_type == GF_CRYPT_TYPE_CBC1) || (tkc->scheme_type == GF_CRYPT_TYPE_CENS)) {
     369         179 :                         if (tkc->keys[0].constant_IV_size) {
     370           0 :                                 if (!tkc->keys[0].IV_size) {
     371           0 :                                         tkc->keys[0].IV_size = tkc->keys[0].constant_IV_size;
     372           0 :                                         GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[CENC] Using scheme type %s, constant IV shall not be used, using constant IV as first IV\n", gf_4cc_to_str(tkc->scheme_type)));
     373           0 :                                         tkc->keys[0].constant_IV_size = 0;
     374             :                                 } else {
     375           0 :                                         tkc->keys[0].constant_IV_size = 0;
     376           0 :                                         GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[CENC] Using scheme type %s, constant IV shall not be used, ignoring\n", gf_4cc_to_str(tkc->scheme_type)));
     377             :                                 }
     378             :                         }
     379             :                 }
     380         230 :                 if (tkc->scheme_type == GF_ISOM_OMADRM_SCHEME) {
     381             :                         /*default to AES 128 in OMA*/
     382           0 :                         tkc->encryption = 2;
     383             :                 }
     384             : 
     385         230 :                 if (has_key) tkc->nb_keys = 1;
     386             :         }
     387             : 
     388        2199 :         if (!strcmp(node_name, "key")) {
     389             :                 u32 IV_size, const_IV_size;
     390             :                 Bool kas_civ = GF_FALSE;
     391         275 :                 tkc = (GF_TrackCryptInfo *)gf_list_last(info->tcis);
     392         275 :                 if (!tkc) return;
     393             :                 //only realloc for 2nd and more
     394         275 :                 if (tkc->nb_keys) {
     395          56 :                         tkc->keys = (GF_CryptKeyInfo *)gf_realloc(tkc->keys, sizeof(GF_CryptKeyInfo)*(tkc->nb_keys+1));
     396          56 :                         memset(&tkc->keys[tkc->nb_keys], 0, sizeof(GF_CryptKeyInfo));
     397             :                 }
     398         275 :                 IV_size = tkc->keys[0].IV_size;
     399         275 :                 const_IV_size = tkc->keys[0].constant_IV_size;
     400             : 
     401         854 :                 for (i=0; i<nb_attributes; i++) {
     402         579 :                         att = (GF_XMLAttribute *) &attributes[i];
     403             : 
     404         579 :                         if (!stricmp(att->name, "KID")) {
     405         265 :                                 GF_Err e = gf_bin128_parse(att->value, tkc->keys[tkc->nb_keys].KID);
     406         265 :                 if (e != GF_OK) {
     407           0 :                     GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Cannnot parse KID\n"));
     408             :                     return;
     409             :                 }
     410             :                         }
     411         314 :                         else if (!stricmp(att->name, "value")) {
     412         275 :                                 GF_Err e = gf_bin128_parse(att->value, tkc->keys[tkc->nb_keys].key);
     413         275 :                 if (e != GF_OK) {
     414           0 :                     GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Cannnot parse key value\n"));
     415             :                     return;
     416             :                 }
     417             :                         }
     418          39 :                         else if (!stricmp(att->name, "hlsInfo")) {
     419          39 :                                 if (!strstr(att->value, "URI=\"")) {
     420           0 :                     GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Missing URI in HLS info %s\n", att->value));
     421             :                     return;
     422             :                                 }
     423          39 :                                 tkc->keys[tkc->nb_keys].hls_info = gf_strdup(att->value);
     424             :                         }
     425           0 :                         else if (!stricmp(att->name, "IV_size")) {
     426           0 :                                 IV_size = atoi(att->value);
     427             :                         }
     428           0 :                         else if (!stricmp(att->name, "constant_IV")) {
     429           0 :                                 char *sKey = att->value;
     430           0 :                                 if (!strnicmp(sKey, "0x", 2)) sKey += 2;
     431           0 :                                 if ((strlen(sKey) == 16) || (strlen(sKey) == 32)) {
     432             :                                         u32 j;
     433           0 :                                         for (j=0; j<strlen(sKey); j+=2) {
     434             :                                                 u32 v;
     435             :                                                 char szV[5];
     436           0 :                                                 sprintf(szV, "%c%c", sKey[j], sKey[j+1]);
     437           0 :                                                 sscanf(szV, "%x", &v);
     438           0 :                                                 tkc->keys[tkc->nb_keys].IV[j/2] = v;
     439             :                                         }
     440           0 :                                         const_IV_size = (u8) strlen(sKey) / 2;
     441             :                                         kas_civ = GF_TRUE;
     442             :                                 }
     443             :                         }
     444             :                 }
     445         275 :                 tkc->keys[tkc->nb_keys].IV_size = IV_size;
     446         275 :                 tkc->keys[tkc->nb_keys].constant_IV_size = const_IV_size;
     447         275 :                 if (!kas_civ && tkc->nb_keys)
     448          56 :                         memcpy(tkc->keys[tkc->nb_keys].IV, tkc->keys[0].IV, 16);
     449         275 :                 tkc->nb_keys++;
     450             :         }
     451             : }
     452             : 
     453        2429 : static void cryptinfo_node_end(void *sax_cbck, const char *node_name, const char *name_space)
     454             : {
     455             :         GF_CryptInfo *info = (GF_CryptInfo *)sax_cbck;
     456        2429 :         if (!strcmp(node_name, "OMATextHeader")) {
     457           0 :                 info->in_text_header = 0;
     458           0 :                 return;
     459             :         }
     460             : }
     461             : 
     462        3230 : static void cryptinfo_text(void *sax_cbck, const char *text, Bool is_cdata)
     463             : {
     464             :         u32 len, len2;
     465             :         GF_TrackCryptInfo *tkc;
     466             :         GF_CryptInfo *info = (GF_CryptInfo *)sax_cbck;
     467             : 
     468        3230 :         if (!info->in_text_header) return;
     469             : 
     470           0 :         tkc = (GF_TrackCryptInfo *) gf_list_last(info->tcis);
     471           0 :         len = (u32) strlen(text);
     472           0 :         len2 = tkc->TextualHeaders ? (u32) strlen(tkc->TextualHeaders) : 0;
     473             : 
     474           0 :         tkc->TextualHeaders = gf_realloc(tkc->TextualHeaders, sizeof(char) * (len+len2+1));
     475           0 :         if (!len2) strcpy(tkc->TextualHeaders, "");
     476           0 :         strcat(tkc->TextualHeaders, text);
     477             : }
     478             : 
     479         230 : void gf_crypt_info_del(GF_CryptInfo *info)
     480             : {
     481         690 :         while (gf_list_count(info->tcis)) {
     482             :                 u32 i;
     483         230 :                 GF_TrackCryptInfo *tci = (GF_TrackCryptInfo *)gf_list_last(info->tcis);
     484         516 :                 for (i=0; i<tci->nb_keys; i++) {
     485         286 :                         if (tci->keys[i].hls_info)
     486          39 :                                 gf_free(tci->keys[i].hls_info);
     487             :                 }
     488         230 :                 if (tci->keys) gf_free(tci->keys);
     489         230 :                 if (tci->metadata) gf_free(tci->metadata);
     490         230 :                 if (tci->KMS_URI) gf_free(tci->KMS_URI);
     491         230 :                 if (tci->Scheme_URI) gf_free(tci->Scheme_URI);
     492         230 :                 if (tci->TextualHeaders) gf_free(tci->TextualHeaders);
     493         230 :                 if (tci->subs_crypt) gf_free(tci->subs_crypt);
     494         230 :                 if (tci->mkey_subs) gf_free(tci->mkey_subs);
     495         230 :                 gf_list_rem_last(info->tcis);
     496         230 :                 gf_free(tci);
     497             :         }
     498         230 :         gf_list_del(info->tcis);
     499         230 :         gf_free(info);
     500         230 : }
     501             : 
     502         230 : GF_CryptInfo *gf_crypt_info_load(const char *file, GF_Err *out_err)
     503             : {
     504             :         GF_Err e;
     505             :         GF_CryptInfo *info;
     506             :         GF_SAXParser *sax;
     507         230 :         GF_SAFEALLOC(info, GF_CryptInfo);
     508         230 :         if (!info) {
     509           0 :                 if (out_err) *out_err = GF_OUT_OF_MEM;
     510             :                 return NULL;
     511             :         }
     512         230 :         info->tcis = gf_list_new();
     513         230 :         sax = gf_xml_sax_new(cryptinfo_node_start, cryptinfo_node_end, cryptinfo_text, info);
     514         230 :         e = gf_xml_sax_parse_file(sax, file, NULL);
     515         230 :         if (e<0) {
     516           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[DRM] Failed to parse DRM config file: %s", gf_xml_sax_get_error(sax) ));
     517           0 :                 if (out_err) *out_err = e;
     518           0 :                 gf_crypt_info_del(info);
     519             :                 info = NULL;
     520         230 :         } else if (info->last_parse_error) {
     521           0 :                 if (out_err) *out_err = info->last_parse_error;
     522           0 :                 gf_crypt_info_del(info);
     523             :                 info = NULL;
     524             :         } else {
     525         230 :                 if (out_err) *out_err = GF_OK;
     526             :         }
     527         230 :         gf_xml_sax_del(sax);
     528         230 :         return info;
     529             : }
     530             : 
     531             : extern char gf_prog_lf;
     532             : 
     533           0 : static Bool on_decrypt_event(void *_udta, GF_Event *evt)
     534             : {
     535             :         Double progress;
     536             :         u32 *prev_progress = (u32 *)_udta;
     537           0 :         if (!_udta) return GF_FALSE;
     538           0 :         if (evt->type != GF_EVENT_PROGRESS) return GF_FALSE;
     539           0 :         if (!evt->progress.total) return GF_FALSE;
     540             : 
     541           0 :         progress = (Double) (100*evt->progress.done) / evt->progress.total;
     542           0 :         if ((u32) progress==*prev_progress)
     543             :                 return GF_FALSE;
     544             : 
     545           0 :         *prev_progress = (u32) progress;
     546             : #ifndef GPAC_DISABLE_LOG
     547           0 :         GF_LOG(GF_LOG_INFO, GF_LOG_APP, ("Decrypting: % 2.2f %%%c", progress, gf_prog_lf));
     548             : #else
     549             :         fprintf(stderr, "Decrypting: % 2.2f %%%c", progress, gf_prog_lf);
     550             : #endif
     551             :         return GF_FALSE;
     552             : }
     553             : 
     554         107 : static GF_Err gf_decrypt_file_ex(GF_ISOFile *mp4, const char *drm_file, const char *dst_file, Double interleave_time, const char *fragment_name, u32 fs_dump_flags)
     555             : {
     556         107 :         char *szArgs = NULL;
     557             :         char an_arg[100];
     558             :         GF_Filter *src, *dst, *dcrypt;
     559             :         GF_FilterSession *fsess;
     560         107 :         GF_Err e = GF_OK;
     561         107 :         u32 progress = (u32) -1;
     562             : 
     563         107 :         fsess = gf_fs_new_defaults(0);
     564         107 :         if (!fsess) {
     565           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[Decrypter] Failed to create filter session\n"));
     566             :                 return GF_OUT_OF_MEM;
     567             :         }
     568             : 
     569             :         sprintf(an_arg, "mp4dmx:mov=%p", mp4);
     570         107 :         gf_dynstrcat(&szArgs, an_arg, NULL);
     571         107 :         if (fragment_name) {
     572           1 :                 gf_dynstrcat(&szArgs, ":sigfrag:catseg=", NULL);
     573           1 :                 gf_dynstrcat(&szArgs, fragment_name, NULL);
     574             :         }
     575         107 :         src = gf_fs_load_filter(fsess, szArgs, &e);
     576         107 :         gf_free(szArgs);
     577         107 :         szArgs = NULL;
     578             : 
     579         107 :         if (!src) {
     580           0 :                 gf_fs_del(fsess);
     581           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[Decrypter] Cannot load demux filter for source file\n"));
     582           0 :                 return e;
     583             :         }
     584             : 
     585         107 :         gf_dynstrcat(&szArgs, "cdcrypt:FID=1", NULL);
     586         107 :         if (drm_file) {
     587         100 :                 gf_dynstrcat(&szArgs, ":cfile=", NULL);
     588         100 :                 gf_dynstrcat(&szArgs, drm_file, NULL);
     589             :         }
     590         107 :         dcrypt = gf_fs_load_filter(fsess, szArgs, &e);
     591         107 :         gf_free(szArgs);
     592         107 :         szArgs = NULL;
     593         107 :         if (!dcrypt) {
     594           0 :                 gf_fs_del(fsess);
     595           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[Decrypter] Cannot load decryptor filter\n"));
     596           0 :                 return e;
     597             :         }
     598             : 
     599         107 :         gf_dynstrcat(&szArgs, "SID=1", NULL);
     600         107 :         if (fragment_name) {
     601           1 :                 gf_dynstrcat(&szArgs, ":sseg:noinit:store=frag:refrag:cdur=1000000000", NULL);
     602             :         } else {
     603         106 :                 if (interleave_time) {
     604             :                         sprintf(an_arg, ":cdur=%g", interleave_time);
     605         106 :                         gf_dynstrcat(&szArgs, an_arg, NULL);
     606             :                 } else {
     607           0 :                         gf_dynstrcat(&szArgs, ":store=flat", NULL);
     608             :                 }
     609             :         }
     610         107 :         if (gf_isom_has_keep_utc_times(mp4))
     611           0 :                 gf_dynstrcat(&szArgs, ":keep_utc", NULL);
     612             : 
     613         107 :         dst = gf_fs_load_destination(fsess, dst_file, szArgs, NULL, &e);
     614         107 :         gf_free(szArgs);
     615         107 :         szArgs = NULL;
     616             : 
     617         107 :         if (!dst) {
     618           0 :                 gf_fs_del(fsess);
     619           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[Decrypter] Cannot load destination muxer\n"));
     620             :                 return GF_FILTER_NOT_FOUND;
     621             :         }
     622             : 
     623         107 :         if (!gf_sys_is_test_mode()
     624             : #ifndef GPAC_DISABLE_LOG
     625           0 :                 && (gf_log_get_tool_level(GF_LOG_APP)!=GF_LOG_QUIET)
     626             : #endif
     627           0 :                 && !gf_sys_is_quiet()
     628             :         ) {
     629           0 :                 gf_fs_enable_reporting(fsess, GF_TRUE);
     630           0 :                 gf_fs_set_ui_callback(fsess, on_decrypt_event, &progress);
     631             :         }
     632             : #ifdef GPAC_ENABLE_COVERAGE
     633         107 :         else if (gf_sys_is_cov_mode()) {
     634             :                 on_decrypt_event(NULL, NULL);
     635             :         }
     636             : #endif //GPAC_ENABLE_COVERAGE
     637             : 
     638         107 :         e = gf_fs_run(fsess);
     639         107 :         if (e>GF_OK) e = GF_OK;
     640         107 :         if (!e) e = gf_fs_get_last_connect_error(fsess);
     641         107 :         if (!e) e = gf_fs_get_last_process_error(fsess);
     642             : 
     643         107 :         if (!e) gf_fs_print_unused_args(fsess, NULL);
     644         107 :         gf_fs_print_non_connected(fsess);
     645         107 :         if (fs_dump_flags & 1) gf_fs_print_stats(fsess);
     646         107 :         if (fs_dump_flags & 2) gf_fs_print_connections(fsess);
     647             : 
     648         107 :         gf_fs_del(fsess);
     649         107 :         return e;
     650             : }
     651             : 
     652             : GF_EXPORT
     653           1 : GF_Err gf_decrypt_fragment(GF_ISOFile *mp4, const char *drm_file, const char *dst_file, const char *fragment_name, u32 fs_dump_flags)
     654             : {
     655           1 :         return gf_decrypt_file_ex(mp4, drm_file, dst_file, 0, fragment_name, fs_dump_flags);
     656             : }
     657             : GF_EXPORT
     658         106 : GF_Err gf_decrypt_file(GF_ISOFile *mp4, const char *drm_file, const char *dst_file, Double interleave_time, u32 fs_dump_flags)
     659             : {
     660         106 :         return gf_decrypt_file_ex(mp4, drm_file, dst_file, interleave_time, NULL, fs_dump_flags);
     661             : }
     662           0 : static Bool on_crypt_event(void *_udta, GF_Event *evt)
     663             : {
     664             :         Double progress;
     665             :         u32 *prev_progress = (u32 *)_udta;
     666           0 :         if (!_udta) return GF_FALSE;
     667           0 :         if (evt->type != GF_EVENT_PROGRESS) return GF_FALSE;
     668           0 :         if (!evt->progress.total) return GF_FALSE;
     669             : 
     670           0 :         progress = (Double) (100*evt->progress.done) / evt->progress.total;
     671           0 :         if ((u32) progress==*prev_progress)
     672             :                 return GF_FALSE;
     673             : 
     674           0 :         *prev_progress = (u32) progress;
     675             : #ifndef GPAC_DISABLE_LOG
     676           0 :         GF_LOG(GF_LOG_INFO, GF_LOG_APP, ("Encrypting: % 2.2f %%%c", progress, gf_prog_lf));
     677             : #else
     678             :         fprintf(stderr, "Encrypting: % 2.2f %%%c", progress, gf_prog_lf);
     679             : #endif
     680             :         return GF_FALSE;
     681             : }
     682             : 
     683         115 : static GF_Err gf_crypt_file_ex(GF_ISOFile *mp4, const char *drm_file, const char *dst_file, Double interleave_time, const char *fragment_name, u32 fs_dump_flags)
     684             : {
     685         115 :         char *szArgs=NULL;
     686             :         char an_arg[100];
     687             :         char *arg_dst=NULL;
     688         115 :         u32 progress = (u32) -1;
     689             :         GF_Filter *src, *dst, *crypt;
     690             :         GF_FilterSession *fsess;
     691         115 :         GF_Err e = GF_OK;
     692             : 
     693         115 :         fsess = gf_fs_new_defaults(0);
     694         115 :         if (!fsess) {
     695           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[Encrypter] Failed to create filter session\n"));
     696             :                 return GF_OUT_OF_MEM;
     697             :         }
     698             : 
     699             :         sprintf(an_arg, "mp4dmx:mov=%p", mp4);
     700         115 :         gf_dynstrcat(&szArgs, an_arg, NULL);
     701         115 :         if (fragment_name) {
     702           2 :                 gf_dynstrcat(&szArgs, ":sigfrag:catseg=", NULL);
     703           2 :                 gf_dynstrcat(&szArgs, fragment_name, NULL);
     704             :         }
     705         115 :         src = gf_fs_load_filter(fsess, szArgs, &e);
     706             : 
     707         115 :         gf_free(szArgs);
     708         115 :         szArgs = NULL;
     709             : 
     710         115 :         if (!src) {
     711           0 :                 gf_fs_del(fsess);
     712           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[Encrypter] Cannot load demux for source file: %s\n", gf_error_to_string(e)));
     713           0 :                 return e;
     714             :         }
     715             : 
     716         115 :         gf_dynstrcat(&szArgs, "cecrypt:FID=1:cfile=", NULL);
     717         115 :         gf_dynstrcat(&szArgs, drm_file, NULL);
     718         115 :         crypt = gf_fs_load_filter(fsess, szArgs, &e);
     719             : 
     720         115 :         gf_free(szArgs);
     721         115 :         szArgs = NULL;
     722             : 
     723         115 :         if (!crypt) {
     724           0 :                 gf_fs_del(fsess);
     725           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[Encrypter] Cannot load encryptor: %s\n", gf_error_to_string(e) ));
     726           0 :                 return e;
     727             :         }
     728             : 
     729         115 :         gf_dynstrcat(&szArgs, "SID=1", NULL);
     730         115 :         if (fragment_name) {
     731           2 :                 gf_dynstrcat(&szArgs, ":sseg:noinit:store=frag:refrag:cdur=1000000000", NULL);
     732             :         } else {
     733         113 :                 if (interleave_time) {
     734             :                         sprintf(an_arg, ":cdur=%g", interleave_time);
     735         113 :                         gf_dynstrcat(&szArgs, an_arg, NULL);
     736             :                 } else {
     737           0 :                         gf_dynstrcat(&szArgs, ":store=flat", NULL);
     738             :                 }
     739             :         }
     740             : 
     741         115 :         if (gf_isom_has_keep_utc_times(mp4))
     742           0 :                 gf_dynstrcat(&szArgs, ":keep_utc", NULL);
     743             : 
     744         115 :         arg_dst = gf_url_colon_suffix(dst_file);
     745         115 :         if (arg_dst) {
     746           0 :                 gf_dynstrcat(&szArgs, arg_dst, NULL);
     747           0 :                 arg_dst[0]=0;
     748             :         }
     749         115 :         dst = gf_fs_load_destination(fsess, dst_file, szArgs, NULL, &e);
     750             : 
     751         115 :         gf_free(szArgs);
     752         115 :         szArgs = NULL;
     753         115 :         if (!dst) {
     754           0 :                 gf_fs_del(fsess);
     755           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[Encrypter] Cannot load destination muxer\n"));
     756             :                 return GF_FILTER_NOT_FOUND;
     757             :         }
     758             : 
     759         115 :         if (!gf_sys_is_test_mode()
     760             : #ifndef GPAC_DISABLE_LOG
     761           0 :                 && (gf_log_get_tool_level(GF_LOG_APP)!=GF_LOG_QUIET)
     762             : #endif
     763           0 :                 && !gf_sys_is_quiet()
     764             :         ) {
     765           0 :                 gf_fs_enable_reporting(fsess, GF_TRUE);
     766           0 :                 gf_fs_set_ui_callback(fsess, on_crypt_event, &progress);
     767             :         }
     768             : #ifdef GPAC_ENABLE_COVERAGE
     769         115 :         else if (gf_sys_is_cov_mode()) {
     770             :                 on_crypt_event(NULL, NULL);
     771             :         }
     772             : #endif //GPAC_ENABLE_COVERAGE
     773         115 :         e = gf_fs_run(fsess);
     774         115 :         if (e>GF_OK) e = GF_OK;
     775         115 :         if (!e) e = gf_fs_get_last_connect_error(fsess);
     776         115 :         if (!e) e = gf_fs_get_last_process_error(fsess);
     777             : 
     778         115 :         if (!e) gf_fs_print_unused_args(fsess, NULL);
     779         115 :         gf_fs_print_non_connected(fsess);
     780         115 :         if (fs_dump_flags & 1) gf_fs_print_stats(fsess);
     781         115 :         if (fs_dump_flags & 2) gf_fs_print_connections(fsess);
     782         115 :         gf_fs_del(fsess);
     783         115 :         return e;
     784             : }
     785             : 
     786             : GF_EXPORT
     787           2 : GF_Err gf_crypt_fragment(GF_ISOFile *mp4, const char *drm_file, const char *dst_file, const char *fragment_name, u32 fs_dump_flags)
     788             : {
     789           2 :         return gf_crypt_file_ex(mp4, drm_file, dst_file, 0, fragment_name, fs_dump_flags);
     790             : }
     791             : 
     792             : GF_EXPORT
     793         113 : GF_Err gf_crypt_file(GF_ISOFile *mp4, const char *drm_file, const char *dst_file, Double interleave_time, u32 fs_dump_flags)
     794             : {
     795         113 :         return gf_crypt_file_ex(mp4, drm_file, dst_file, interleave_time, NULL, fs_dump_flags);
     796             : 
     797             : }
     798             : #endif /* !defined(GPAC_DISABLE_ISOM_WRITE)*/
     799             : 

Generated by: LCOV version 1.13