LCOV - code coverage report
Current view: top level - filters - decrypt_cenc_isma.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 537 680 79.0 %
Date: 2021-04-29 23:48:07 Functions: 18 18 100.0 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2018-2021
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / CENC and ISMA decrypt filter
       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             : #include <gpac/filters.h>
      27             : #include <gpac/constants.h>
      28             : #include <gpac/crypt_tools.h>
      29             : #include <gpac/crypt.h>
      30             : #include <gpac/base_coding.h>
      31             : #include <gpac/download.h>
      32             : 
      33             : #ifndef GPAC_DISABLE_CRYPTO
      34             : 
      35             : //#define OLD_KEY_FETCHERS
      36             : 
      37             : enum
      38             : {
      39             :         DECRYPT_STATE_ERROR,
      40             :         DECRYPT_STATE_SETUP,
      41             :         DECRYPT_STATE_PLAY,
      42             : };
      43             : 
      44             : enum
      45             : {
      46             :         DECRYPT_FULL=0,
      47             :         DECRYPT_NOKEY,
      48             :         DECRYPT_SKIP,
      49             : };
      50             : 
      51             : typedef struct
      52             : {
      53             :         GF_Crypt *crypt;
      54             :         bin128 key;
      55             :         u32 key_valid;
      56             : } CENCDecKey;
      57             : 
      58             : typedef struct
      59             : {
      60             :         GF_FilterPid *ipid, *opid;
      61             : 
      62             :         u32 state;
      63             :         u32 pssh_crc;
      64             :         u32 scheme_type, scheme_version;
      65             : 
      66             :         GF_Err key_error;
      67             : 
      68             :         CENCDecKey *crypts;
      69             :         u32 nb_crypts;
      70             : 
      71             :         //ISMA & OMA
      72             :         char salt[8];
      73             :         u64 last_IV;
      74             :         u32 nb_allow_play;
      75             :         Bool is_oma, is_adobe;
      76             :         u32 preview_range;
      77             :         Bool is_nalu;
      78             :         Bool selective_encryption;
      79             :         u32 IV_length, KI_length;
      80             : 
      81             :         /*CENC*/
      82             :         Bool is_cenc;
      83             :         Bool is_cbc;
      84             :         u32 KID_count;
      85             :         bin128 *KIDs;
      86             :         bin128 *keys;
      87             : 
      88             :         const GF_PropertyValue *cenc_ki;
      89             :         u32 multikey;
      90             :         const GF_PropertyValue *cenc_pattern;
      91             : 
      92             :         /*adobe and CENC*/
      93             :         Bool crypt_init;
      94             : 
      95             : 
      96             : } GF_CENCDecStream;
      97             : 
      98             : typedef struct
      99             : {
     100             :         const char *cfile;
     101             :         u32 decrypt;
     102             :         GF_PropUIntList drop_keys;
     103             :         GF_PropStringList kids;
     104             :         GF_PropStringList keys;
     105             :         GF_CryptInfo *cinfo;
     106             :         
     107             :         GF_List *streams;
     108             :         GF_BitStream *bs_r;
     109             : 
     110             :         GF_DownloadManager *dm;
     111             : } GF_CENCDecCtx;
     112             : 
     113             : 
     114             : #ifdef OLD_KEY_FETCHERS
     115             : static void cenc_dec_kms_netio(void *cbck, GF_NETIO_Parameter *par)
     116             : {
     117             : }
     118             : 
     119             : static GF_Err gf_ismacryp_gpac_get_info(u32 stream_id, char *drm_file, char *key, char *salt)
     120             : {
     121             :         GF_Err e;
     122             :         u32 i, count;
     123             :         GF_CryptInfo *info;
     124             : 
     125             :         e = GF_OK;
     126             :         info = gf_crypt_info_load(drm_file, &e);
     127             :         if (!info) return e;
     128             :         count = gf_list_count(info->tcis);
     129             :         for (i=0; i<count; i++) {
     130             :                 GF_TrackCryptInfo *tci = (GF_TrackCryptInfo *) gf_list_get(info->tcis, i);
     131             :                 if ((info->has_common_key && !tci->trackID) || (tci->trackID == stream_id) ) {
     132             :                         if (tci->KID_count)
     133             :                                 memcpy(key, tci->keys[0], sizeof(char)*16);
     134             :                         memcpy(salt, tci->first_IV, sizeof(char)*8);
     135             :                         e = GF_OK;
     136             :                         break;
     137             :                 }
     138             :         }
     139             :         gf_crypt_info_del(info);
     140             :         return e;
     141             : }
     142             : 
     143             : static GF_Err cenc_dec_get_gpac_kms(GF_CENCDecCtx *ctx, GF_CENCDecStream *cstr, const char *kms_url)
     144             : {
     145             :         const GF_PropertyValue *prop;
     146             :         FILE *t;
     147             :         u32 id = 0;
     148             :         GF_FilterPid *pid = cstr->ipid;
     149             :         GF_Err e;
     150             :         GF_DownloadSession * sess;
     151             : 
     152             :         prop = gf_filter_pid_get_property(pid, GF_PROP_PID_ID);
     153             :         if (!prop) prop = gf_filter_pid_get_property(pid, GF_PROP_PID_ESID);
     154             :         if (prop) id = prop->value.uint;
     155             : 
     156             :         if (!strnicmp(kms_url, "(ipmp)", 6)) return GF_NOT_SUPPORTED;
     157             :         else if (!strnicmp(kms_url, "(uri)", 5)) kms_url += 5;
     158             :         else if (!strnicmp(kms_url, "file://", 7)) kms_url += 7;
     159             : 
     160             :         /*try local*/
     161             :         t = (strstr(kms_url, "://") == NULL) ? gf_fopen(kms_url, "rb") : NULL;
     162             :         if (t) {
     163             :                 gf_fclose(t);
     164             :                 return gf_ismacryp_gpac_get_info(id, (char *)kms_url, cstr->key, cstr->salt);
     165             :         }
     166             :         /*note that gpac doesn't have TLS support -> not really useful. As a general remark, ISMACryp
     167             :         is supported as a proof of concept, crypto and IPMP being the last priority on gpac...*/
     168             :         GF_LOG(GF_LOG_INFO, GF_LOG_MEDIA, ("[CENC/ISMA] Fetching ISMACryp key for channel %d\n", id) );
     169             : 
     170             :         sess = gf_dm_sess_new(ctx->dm, kms_url, GF_NETIO_SESSION_NOT_THREADED, cenc_dec_kms_netio, ctx, NULL);
     171             :         if (!sess) return GF_IO_ERR;
     172             : 
     173             :         while (1) {
     174             :                 GF_NetIOStatus status;
     175             :                 e = gf_dm_sess_process(sess);
     176             :                 if (e) break;
     177             :                 gf_dm_sess_get_stats(sess, NULL, NULL, NULL, NULL, NULL, &status);
     178             :                 if (status>=GF_NETIO_DATA_TRANSFERED) break;
     179             :         }
     180             :         if (e >= GF_EOS) {
     181             :                 e = gf_ismacryp_gpac_get_info(id, (char *) gf_dm_sess_get_cache_name(sess), cstr->key, cstr->salt);
     182             :         }
     183             :         gf_dm_sess_del(sess);
     184             :         return e;
     185             : }
     186             : 
     187             : static Bool gf_ismacryp_mpeg4ip_get_info(char *kms_uri, char *key, char *salt)
     188             : {
     189             :         char szPath[1024], catKey[24], line[101];
     190             :         u32 i, x;
     191             :         Bool got_it;
     192             :         FILE *kms;
     193             :         strcpy(szPath, getenv("HOME"));
     194             :         strcat(szPath , "/.kms_data");
     195             :         got_it = 0;
     196             :         kms = gf_fopen(szPath, "rt");
     197             :         while (kms && !gf_feof(kms)) {
     198             :                 if (!gf_fgets(szPath, 1024, kms)) break;
     199             :                 szPath[strlen(szPath) - 1] = 0;
     200             :                 if (stricmp(szPath, kms_uri)) continue;
     201             :                 gf_fgets(line, 1, 100, kms);
     202             :                 line[100] = 0;
     203             :                 for (i=0; i<24; i++) {
     204             :                         char szV[3];
     205             :                         szV[0] = line[2*i];
     206             :                         szV[1] = line[2*i + 1];
     207             :                         szV[2] = 0;
     208             :                         if (!sscanf(szV, "%x", &x)) break;
     209             :                         catKey[i] = x;
     210             :                 }
     211             :                 if (i==24) got_it = 1;
     212             :                 break;
     213             :         }
     214             :         if (kms) gf_fclose(kms);
     215             :         if (got_it) {
     216             :                 /*watchout, MPEG4IP stores SALT|KEY, NOT KEY|SALT*/
     217             :                 memcpy(key, catKey+8, sizeof(char)*16);
     218             :                 memcpy(salt, catKey, sizeof(char)*8);
     219             :                 return 1;
     220             :         }
     221             :         return 0;
     222             : }
     223             : #endif
     224             : 
     225             : 
     226           5 : static GF_Err cenc_dec_setup_isma(GF_CENCDecCtx *ctx, GF_CENCDecStream *cstr, u32 scheme_type, u32 scheme_version, const char *scheme_uri, const char *kms_uri)
     227             : {
     228             :         u32 kms_crc=0;
     229             :         const GF_PropertyValue *p;
     230           5 :         cstr->state = DECRYPT_STATE_ERROR;
     231             : 
     232           5 :         if (scheme_type != GF_ISOM_ISMACRYP_SCHEME) return GF_NOT_SUPPORTED;
     233           5 :         if (scheme_version != 1) return GF_NOT_SUPPORTED;
     234           5 :         if (!kms_uri) return GF_NON_COMPLIANT_BITSTREAM;
     235             : 
     236           5 :         kms_crc = gf_crc_32(kms_uri, (u32) strlen(kms_uri));
     237           5 :         if (cstr->pssh_crc == kms_crc) return GF_OK;
     238           5 :         cstr->pssh_crc = kms_crc;
     239             : 
     240             :         /*try to fetch the keys*/
     241             :         /*base64 inband encoding*/
     242           5 :         if (!strnicmp(kms_uri, "(key)", 5)) {
     243             :                 char data[100];
     244           5 :                 gf_base64_decode((char*) kms_uri+5, (u32)strlen(kms_uri)-5, data, 100);
     245           5 :                 memcpy(cstr->crypts[0].key, data, sizeof(char)*16);
     246           5 :                 memcpy(cstr->salt, data+16, sizeof(char)*8);
     247             :         }
     248             :         /*hexadecimal inband encoding*/
     249           0 :         else if (!strnicmp(kms_uri, "(key-hexa)", 10)) {
     250             :                 u32 v;
     251             :                 char szT[3], *k;
     252             :                 u32 i;
     253           0 :                 szT[2] = 0;
     254           0 :                 if (strlen(kms_uri) < 10+32+16) return GF_NON_COMPLIANT_BITSTREAM;
     255             : 
     256           0 :                 k = (char *)kms_uri + 10;
     257           0 :                 for (i=0; i<16; i++) {
     258           0 :                         szT[0] = k[2*i];
     259           0 :                         szT[1] = k[2*i + 1];
     260           0 :                         sscanf(szT, "%X", &v);
     261           0 :                         cstr->crypts[0].key[i] = v;
     262             :                 }
     263             : 
     264           0 :                 k = (char *)kms_uri + 10 + 32;
     265           0 :                 for (i=0; i<8; i++) {
     266           0 :                         szT[0] = k[2*i];
     267           0 :                         szT[1] = k[2*i + 1];
     268           0 :                         sscanf(szT, "%X", &v);
     269           0 :                         cstr->salt[i] = v;
     270             :                 }
     271             :         }
     272             :         /*MPEG4-IP KMS*/
     273           0 :         else if (!stricmp(kms_uri, "AudioKey") || !stricmp(kms_uri, "VideoKey")) {
     274             : #ifdef OLD_KEY_FETCHERS
     275             :                 if (!gf_ismacryp_mpeg4ip_get_info((char *) kms_uri, cstr->key, cstr->salt)) {
     276             :                         return GF_BAD_PARAM;
     277             :                 }
     278             : #else
     279             :                 return GF_NOT_SUPPORTED;
     280             : #endif
     281             :         }
     282             :         /*gpac default scheme is used, fetch file from KMS and load keys*/
     283           0 :         else if (scheme_uri && !stricmp(scheme_uri, "urn:gpac:isma:encryption_scheme")) {
     284             : #ifdef OLD_KEY_FETCHERS
     285             :                 e = cenc_dec_get_gpac_kms(ctx, cstr, kms_uri);
     286             :                 if (e) return e;
     287             : #else
     288             :                 return GF_NOT_SUPPORTED;
     289             : #endif
     290             :         }
     291             :         /*hardcoded keys*/
     292             :         else {
     293             :                 static u8 mysalt[] = { 8,7,6,5,4,3,2,1, 0,0,0,0,0,0,0,0 };
     294             :                 static u8 mykey[][16]  = {
     295             :                         {       0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
     296             :                                 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
     297             :                         }
     298             :                 };
     299           0 :                 memcpy(cstr->salt, mysalt, sizeof(char)*8);
     300           0 :                 memcpy(cstr->crypts[0].key, mykey, sizeof(char)*16);
     301             :         }
     302           5 :         cstr->state = DECRYPT_STATE_SETUP;
     303             : 
     304           5 :         p = gf_filter_pid_get_property(cstr->ipid, GF_PROP_PID_ISMA_SELECTIVE_ENC);
     305           5 :         if (p) cstr->selective_encryption = p->value.boolean;
     306           5 :         p = gf_filter_pid_get_property(cstr->ipid, GF_PROP_PID_ISMA_IV_LENGTH);
     307           5 :         if (p) cstr->IV_length = p->value.uint;
     308           5 :         p = gf_filter_pid_get_property(cstr->ipid, GF_PROP_PID_ISMA_KI_LENGTH);
     309           5 :         if (p) cstr->KI_length = p->value.uint;
     310             : 
     311             : 
     312             :         //ctx->nb_allow_play = 1;
     313             :         return GF_OK;
     314             : }
     315             : 
     316           5 : static GF_Err cenc_dec_access_isma(GF_CENCDecCtx *ctx, GF_CENCDecStream *cstr, Bool is_play)
     317             : {
     318             :         GF_Err e;
     319             : 
     320           5 :         if (is_play) {
     321             :                 char IV[16];
     322           5 :                 if (cstr->state != DECRYPT_STATE_SETUP)
     323             :                         return GF_SERVICE_ERROR;
     324             :                 assert(!cstr->crypts[0].crypt);
     325             : 
     326             :                 //if (!ctx->nb_allow_play) return GF_AUTHENTICATION_FAILURE;
     327             :                 //ctx->nb_allow_play--;
     328             : 
     329             :                 /*init decrypter*/
     330           5 :                 cstr->crypts[0].crypt = gf_crypt_open(GF_AES_128, GF_CTR);
     331           5 :                 if (!cstr->crypts[0].crypt) return GF_IO_ERR;
     332             : 
     333             :                 memset(IV, 0, sizeof(char)*16);
     334             :                 memcpy(IV, cstr->salt, sizeof(char)*8);
     335           5 :                 e = gf_crypt_init(cstr->crypts[0].crypt, cstr->crypts[0].key, IV);
     336           5 :                 if (e) return e;
     337             : 
     338           5 :                 cstr->state = DECRYPT_STATE_PLAY;
     339             :                 return GF_OK;
     340             :         } else {
     341           0 :                 if (cstr->state != DECRYPT_STATE_PLAY)
     342             :                         return GF_SERVICE_ERROR;
     343           0 :                 if (cstr->crypts[0].crypt) gf_crypt_close(cstr->crypts[0].crypt);
     344           0 :                 cstr->crypts[0].crypt = NULL;
     345           0 :                 cstr->state = DECRYPT_STATE_SETUP;
     346             :                 return GF_OK;
     347             :         }
     348             :         return GF_BAD_PARAM;
     349             : }
     350             : 
     351         932 : static GF_Err cenc_dec_process_isma(GF_CENCDecCtx *ctx, GF_CENCDecStream *cstr, GF_FilterPacket *in_pck)
     352             : {
     353             :         u32 data_size;
     354             :         const char *in_data;
     355             :         u8 *out_data;
     356             :         u64 isma_BSO = 0;
     357             :         u32 offset=0;
     358             :         GF_FilterPacket *out_pck;
     359             :         Bool is_encrypted=GF_FALSE;
     360         932 :         if (!cstr->crypts[0].crypt)
     361             :                 return GF_SERVICE_ERROR;
     362             : 
     363         932 :         if (! gf_filter_pck_get_crypt_flags(in_pck)) {
     364           0 :                 out_pck = gf_filter_pck_new_ref(cstr->opid, 0, 0, in_pck);
     365           0 :                 if (!out_pck) return GF_OUT_OF_MEM;
     366           0 :                 gf_filter_pck_merge_properties(in_pck, out_pck);
     367           0 :                 gf_filter_pck_set_crypt_flags(out_pck, 0);
     368           0 :                 gf_filter_pck_send(out_pck);
     369             :                 return GF_OK;
     370             :         }
     371             : 
     372         932 :         in_data = gf_filter_pck_get_data(in_pck, &data_size);
     373             : 
     374         932 :         gf_bs_reassign_buffer(ctx->bs_r, in_data, data_size);
     375             :         
     376         932 :         if (cstr->selective_encryption) {
     377           0 :                 if (gf_bs_read_int(ctx->bs_r, 1)) is_encrypted=GF_TRUE;
     378           0 :                 gf_bs_read_int(ctx->bs_r, 7);
     379             :                 offset = 1;
     380             :         } else {
     381             :                 is_encrypted=GF_TRUE;
     382             :         }
     383           0 :         if (is_encrypted) {
     384         932 :                 if (cstr->IV_length != 0) {
     385         932 :                         isma_BSO = gf_bs_read_long_int(ctx->bs_r, 8*cstr->IV_length);
     386         932 :                         offset += cstr->IV_length;
     387             :                 }
     388         932 :                 if (cstr->KI_length) {
     389           0 :                         offset += cstr->KI_length;
     390             :                 }
     391             :         }
     392             : 
     393             :         /*resync IV*/
     394         932 :         if (!cstr->last_IV || (cstr->last_IV != isma_BSO)) {
     395             :                 char IV[17];
     396             :                 u64 count;
     397             :                 u32 remain;
     398             :                 GF_BitStream *bs;
     399           5 :                 count = isma_BSO / 16;
     400           5 :                 remain = (u32) (isma_BSO % 16);
     401             : 
     402             :                 /*format IV to begin of counter*/
     403           5 :                 bs = gf_bs_new(IV, 17, GF_BITSTREAM_WRITE);
     404           5 :                 gf_bs_write_u8(bs, 0);  /*begin of counter*/
     405           5 :                 gf_bs_write_data(bs, cstr->salt, 8);
     406           5 :                 gf_bs_write_u64(bs, (s64) count);
     407           5 :                 gf_bs_del(bs);
     408           5 :                 gf_crypt_set_IV(cstr->crypts[0].crypt, IV, 17);
     409             : 
     410             :                 /*decrypt remain bytes*/
     411           5 :                 if (remain) {
     412             :                         char dummy[20];
     413           0 :                         gf_crypt_decrypt(cstr->crypts[0].crypt, dummy, remain);
     414             :                 }
     415           5 :                 cstr->last_IV = isma_BSO;
     416             :         }
     417         932 :         in_data += offset;
     418         932 :         data_size -= offset;
     419             : 
     420         932 :         out_pck = gf_filter_pck_new_alloc(cstr->opid, data_size, &out_data);
     421         932 :         if (!out_pck) return GF_OUT_OF_MEM;
     422             : 
     423         932 :         memcpy(out_data, in_data, data_size);
     424             :         /*decrypt*/
     425         932 :         gf_crypt_decrypt(cstr->crypts[0].crypt, out_data, data_size);
     426         932 :         cstr->last_IV += data_size;
     427             : 
     428             :         /*replace AVC start codes (0x00000001) by nalu size*/
     429         932 :         if (cstr->is_nalu) {
     430             :                 u32 nalu_size;
     431             :                 u32 remain = data_size;
     432             :                 char *start, *end;
     433         425 :                 start = out_data;
     434         425 :                 end = start + 4;
     435      691627 :                 while (remain>4) {
     436      691202 :                         if (!end[0] && !end[1] && !end[2] && (end[3]==0x01)) {
     437        2261 :                                 nalu_size = (u32) (end - start - 4);
     438        2261 :                                 start[0] = (nalu_size>>24)&0xFF;
     439        2261 :                                 start[1] = (nalu_size>>16)&0xFF;
     440        2261 :                                 start[2] = (nalu_size>>8)&0xFF;
     441        2261 :                                 start[3] = (nalu_size)&0xFF;
     442             :                                 start = end;
     443        2261 :                                 end = start+4;
     444        2261 :                                 remain -= 4;
     445        2261 :                                 continue;
     446             :                         }
     447      688941 :                         end++;
     448      688941 :                         remain--;
     449             :                 }
     450         425 :                 nalu_size = (u32) (end - start - 4);
     451         425 :                 start[0] = (nalu_size>>24)&0xFF;
     452         425 :                 start[1] = (nalu_size>>16)&0xFF;
     453         425 :                 start[2] = (nalu_size>>8)&0xFF;
     454         425 :                 start[3] = (nalu_size)&0xFF;
     455             :         }
     456             : 
     457         932 :         gf_filter_pck_merge_properties(in_pck, out_pck);
     458         932 :         gf_filter_pck_set_crypt_flags(out_pck, 0);
     459             : 
     460         932 :         gf_filter_pck_send(out_pck);
     461             :         return GF_OK;
     462             : }
     463             : 
     464             : #ifdef OLD_KEY_FETCHERS
     465             : 
     466             : static GF_Err cenc_dec_setup_oma(GF_CENCDecCtx *ctx, GF_CENCDecStream *cstr, u32 scheme_type, u32 scheme_version, const char *scheme_uri, const char *kms_uri)
     467             : {
     468             :         const GF_PropertyValue *prop;
     469             :         GF_FilterPid *pid = cstr->ipid;
     470             : 
     471             :         cstr->state = DECRYPT_STATE_ERROR;
     472             :         if (scheme_type != GF_ISOM_OMADRM_SCHEME) return GF_NOT_SUPPORTED;
     473             :         if (scheme_version != 0x00000200) return GF_NOT_SUPPORTED;
     474             : 
     475             :         cstr->is_oma = GF_TRUE;
     476             : 
     477             :         prop = gf_filter_pid_get_property(pid, GF_PROP_PID_OMA_PREVIEW_RANGE);
     478             :         if (prop) cstr->preview_range = (u32) prop->value.longuint;
     479             : 
     480             :         /*TODO: call DRM agent, fetch keys*/
     481             :         if (!kms_uri) return GF_NON_COMPLIANT_BITSTREAM;
     482             :         cstr->state = DECRYPT_STATE_SETUP;
     483             : 
     484             :         /*we have preview*/
     485             :         if (cstr->preview_range) return GF_OK;
     486             : 
     487             :         return GF_NOT_SUPPORTED;
     488             : }
     489             : #endif
     490             : 
     491             : 
     492         276 : static GF_Err cenc_dec_load_keys(GF_CENCDecCtx *ctx, GF_CENCDecStream *cstr)
     493             : {
     494             :         bin128 blank_KID;
     495             :         const u8 *key_info;
     496             :         u32 i, j, kpos=3, nb_keys;
     497         276 :         cstr->crypt_init = GF_FALSE;
     498             : 
     499             :         //this can be NULL when set per sample and not at init
     500         276 :         if (!cstr->cenc_ki)
     501             :                 return GF_OK;
     502             : 
     503             :         memset(blank_KID, 0, 16);
     504         263 :         key_info = cstr->cenc_ki->value.data.ptr;
     505         263 :         if (key_info[0]) {
     506           6 :                 nb_keys = key_info[1];
     507           6 :                 nb_keys<<=8;
     508           6 :                 nb_keys |= key_info[2];
     509             :         } else {
     510             :                 nb_keys = 1;
     511             :         }
     512         532 :         for (i=0; i<nb_keys; i++) {
     513             :                 Bool found = GF_FALSE;
     514         269 :                 u8 iv_size = key_info[kpos];
     515         269 :                 const u8 *KID = key_info + kpos+1;
     516         269 :                 kpos += 17;
     517         269 :                 if (!iv_size) {
     518           6 :                         iv_size = key_info[kpos];
     519           6 :                         kpos += 1 + iv_size;
     520             :                 }
     521             : 
     522         269 :                 cstr->crypts[i].key_valid = GF_TRUE;
     523         269 :                 if (ctx->drop_keys.nb_items) {
     524           0 :                         for (j=0; j<ctx->drop_keys.nb_items; j++) {
     525           0 :                                 if (ctx->drop_keys.vals[j] == i+1) {
     526           0 :                                         cstr->crypts[i].key_valid = GF_FALSE;
     527           0 :                                         break;
     528             :                                 }
     529             :                         }
     530             :                 }
     531         269 :                 if (ctx->kids.nb_items) {
     532             :                         char szKID[33];
     533           0 :                         szKID[0] = 0;
     534           0 :                         for (j=0; j<16; j++) {
     535             :                                 char szC[3];
     536           0 :                                 sprintf(szC, "%02X", KID[j]);
     537             :                                 strcat(szKID, szC);
     538             :                         }
     539           0 :                         for (j=0; j<ctx->kids.nb_items; j++) {
     540           0 :                                 char *kid_d = ctx->kids.vals[j];
     541           0 :                                 if (!strncmp(kid_d, "0x", 2)) kid_d+=2;
     542             : 
     543           0 :                                 if (stricmp(szKID, kid_d)) continue;
     544             : 
     545             :                                 //no global key, disable key
     546           0 :                                 if (!ctx->keys.nb_items) {
     547           0 :                                         cstr->crypts[i].key_valid = GF_FALSE;
     548             :                                 }
     549             :                                 //use global keys
     550             :                                 else {
     551             :                                         u32 len;
     552             :                                         bin128 key;
     553           0 :                                         char *key_str = ctx->keys.vals[j];
     554           0 :                                         if (!strncmp(key_str, "0x", 2)) key_str+= 2;
     555           0 :                                         len = (u32) strlen(key_str);
     556           0 :                                         if (len!=32) {
     557           0 :                                                 cstr->crypts[i].key_valid = GF_FALSE;
     558           0 :                                                 break;
     559             :                                         }
     560           0 :                                         for (j=0; j<16; j++) {
     561             :                                                 u32 val;
     562             :                                                 char szV[3];
     563           0 :                                                 szV[0] = key_str[2*j];
     564           0 :                                                 szV[1] = key_str[2*j+1];
     565           0 :                                                 szV[2] = 0;
     566           0 :                                                 sscanf(szV, "%02X", &val);
     567           0 :                                                 key[j] = val;
     568             :                                         }
     569           0 :                                         memcpy(cstr->crypts[i].key, key, 16);
     570             :                                         found = GF_TRUE;
     571             :                                 }
     572             :                                 break;
     573             :                         }
     574             :                 }
     575         269 :                 if (!cstr->crypts[i].key_valid) continue;
     576         269 :                 if (found) continue;
     577             : 
     578         258 :                 for (j=0; j<cstr->KID_count; j++) {
     579         527 :                         if (!memcmp(KID, cstr->KIDs[j], 16) || !memcmp(blank_KID, cstr->KIDs[j], 16) ) {
     580         269 :                                 memcpy(cstr->crypts[i].key, cstr->keys[j], 16);
     581             :                                 found = GF_TRUE;
     582         269 :                                 if (ctx->decrypt==DECRYPT_SKIP) {
     583           0 :                                         cstr->crypts[i].key_valid = GF_FALSE;
     584             :                                 } else {
     585         269 :                                         cstr->crypts[i].key_valid = GF_TRUE;
     586             :                                 }
     587             :                                 break;
     588             :                         }
     589             :                 }
     590             :                 if (!found) {
     591           0 :                         if (ctx->decrypt==DECRYPT_FULL) {
     592           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Cannot locate key #%d for given KID, abprting !\n\tUse '--decrypt=nokey' to force decrypting\n", i+1));
     593           0 :                                 return cstr->key_error = GF_SERVICE_ERROR;
     594             :                         }
     595           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[CENC] Cannot locate key #%d for given KID, will leave data encrypted\n", i+1));
     596           0 :                         cstr->crypts[i].key_valid = GF_FALSE;
     597             :                 }
     598             :         }
     599             : 
     600         263 :         cstr->key_error = GF_OK;
     601         263 :         cstr->crypt_init = GF_FALSE;
     602         263 :         return GF_OK;
     603             : }
     604             : 
     605         277 : static GF_Err cenc_dec_setup_cenc(GF_CENCDecCtx *ctx, GF_CENCDecStream *cstr, u32 scheme_type, u32 scheme_version, const char *scheme_uri, const char *kms_uri)
     606             : {
     607             :         GF_Err e;
     608             :         GF_CryptInfo *cinfo=NULL;
     609             :         u32 i, nb_pssh, pssh_crc=0, ki_crc=0;
     610             :         const GF_PropertyValue *prop, *cinfo_prop, *pssh_prop;
     611         277 :         GF_FilterPid *pid = cstr->ipid;
     612         277 :         Bool is_playing = (cstr->state == DECRYPT_STATE_PLAY) ? GF_TRUE : GF_FALSE;
     613             : 
     614         277 :         cstr->state = DECRYPT_STATE_ERROR;
     615             : 
     616         554 :         if ((scheme_type != GF_ISOM_CENC_SCHEME)
     617         277 :                 && (scheme_type != GF_ISOM_CBC_SCHEME)
     618          29 :                 && (scheme_type != GF_ISOM_CENS_SCHEME)
     619          29 :                 && (scheme_type != GF_ISOM_CBCS_SCHEME)
     620           0 :                 && (scheme_type != GF_ISOM_PIFF_SCHEME)
     621             :         )
     622             :                 return GF_NOT_SUPPORTED;
     623             : 
     624         277 :         if (scheme_version != 0x00010000) {
     625           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[CENC/ISMA] Invalid scheme version %08X for scheme type %s, results might be wrong\n", scheme_version, gf_4cc_to_str(scheme_type) ));
     626             :         }
     627             : 
     628         277 :         pssh_prop = gf_filter_pid_get_property(pid, GF_PROP_PID_CENC_PSSH);
     629         277 :         if (pssh_prop) {
     630         277 :                 pssh_crc = gf_crc_32(pssh_prop->value.data.ptr, pssh_prop->value.data.size);
     631             :         }
     632             : 
     633         277 :         cstr->cenc_pattern = gf_filter_pid_get_property(pid, GF_PROP_PID_CENC_PATTERN);
     634         277 :         if (cstr->cenc_pattern && (!cstr->cenc_pattern->value.frac.num || !cstr->cenc_pattern->value.frac.den))
     635           2 :                 cstr->cenc_pattern = NULL;
     636             : 
     637             :         ki_crc = 0;
     638         277 :         if (cstr->cenc_ki) {
     639         166 :                 ki_crc = gf_crc_32(cstr->cenc_ki->value.data.ptr, cstr->cenc_ki->value.data.size);
     640             :         }
     641         277 :         prop = gf_filter_pid_get_property(pid, GF_PROP_PID_CENC_KEY_INFO);
     642         277 :         if (prop) {
     643         264 :                 cstr->cenc_ki = prop;
     644         264 :                 cstr->multikey = 0;
     645         264 :                 if (prop->value.data.ptr[0]) {
     646           6 :                         cstr->multikey = prop->value.data.ptr[1];
     647           6 :                         cstr->multikey <<= 8;
     648           6 :                         cstr->multikey |= prop->value.data.ptr[2];
     649             :                 }
     650         264 :                 u32 new_crc = gf_crc_32(cstr->cenc_ki->value.data.ptr, cstr->cenc_ki->value.data.size);
     651             : 
     652             :                 //change of key config and same pssh, setup single key
     653         264 :                 if ((new_crc != ki_crc) && (pssh_crc==cstr->pssh_crc)) {
     654         178 :                         e = cenc_dec_load_keys(ctx, cstr);
     655         178 :                         if (e) return e;
     656             :                 }
     657             :                 //if no pssh or pssh change we setup the key later
     658             :                 //and if same key/pssh nothing to do for crypto reinit
     659             :         } else {
     660          13 :                 cstr->cenc_ki = NULL;
     661             :         }
     662             : 
     663         277 :         if ((cstr->scheme_type==scheme_type) && (cstr->scheme_version==scheme_version) && (cstr->pssh_crc==pssh_crc) )
     664             :                 return GF_OK;
     665             : 
     666          98 :         cstr->scheme_version = scheme_version;
     667          98 :         cstr->scheme_type = scheme_type;
     668          98 :         cstr->pssh_crc = pssh_crc;
     669             : 
     670          98 :         if ((scheme_type == GF_ISOM_CENC_SCHEME) || (scheme_type == GF_ISOM_PIFF_SCHEME) || (scheme_type == GF_ISOM_CENS_SCHEME))
     671          79 :                 cstr->is_cenc = GF_TRUE;
     672             :         else
     673          19 :                 cstr->is_cbc = GF_TRUE;
     674             : 
     675          98 :         cstr->state = is_playing ? DECRYPT_STATE_PLAY : DECRYPT_STATE_SETUP;
     676             :         //ctx->nb_allow_play = 1;
     677             : 
     678          98 :         cinfo_prop = gf_filter_pid_get_property(cstr->ipid, GF_PROP_PID_DECRYPT_INFO);
     679          98 :         if (!cinfo_prop) cinfo_prop = gf_filter_pid_get_property(cstr->ipid, GF_PROP_PID_CRYPT_INFO);
     680             : 
     681          98 :         if (pssh_prop) {
     682          98 :                 gf_bs_reassign_buffer(ctx->bs_r, pssh_prop->value.data.ptr, pssh_prop->value.data.size);
     683          98 :                 nb_pssh = gf_bs_read_u32(ctx->bs_r);
     684             :         } else {
     685             :                 nb_pssh = 0;
     686             :         }
     687             : 
     688         172 :         for (i = 0; i < nb_pssh; i++) {
     689             :                 u32 cypherOffset;
     690             :                 char *enc_data;
     691             :                 bin128 cypherKey, cypherIV;
     692             :                 GF_Crypt *mc;
     693             :                 u32 pos, priv_len;
     694             :                 char szSystemID[33];
     695             :                 bin128 sysID;
     696             :                 u32 j, kid_count, enc_payload_len;
     697         134 :                 u8 *pssh_data = (u8 *) pssh_prop->value.data.ptr     ;
     698             : 
     699         134 :                 gf_bs_read_data(ctx->bs_r, sysID, 16);
     700         134 :                 /*version =*/ gf_bs_read_u32(ctx->bs_r);
     701         134 :                 kid_count = gf_bs_read_u32(ctx->bs_r);
     702             : 
     703             :                 memset(szSystemID, 0, 33);
     704        2144 :                 for (j=0; j<16; j++) {
     705        2144 :                         sprintf(szSystemID+j*2, "%02X", (unsigned char) sysID[j]);
     706             :                 }
     707             : 
     708             :                 /*SystemID for GPAC Player: 67706163-6365-6E63-6472-6D746F6F6C31*/
     709         134 :                 if (strcmp(szSystemID, "6770616363656E6364726D746F6F6C31")) {
     710          37 :                         if (!cinfo_prop && !ctx->cfile) {
     711           1 :                                 GF_LOG(GF_LOG_INFO, GF_LOG_AUTHOR, ("[CENC/ISMA] System ID %s not supported\n", szSystemID));
     712             :                         }
     713          37 :                         gf_bs_skip_bytes(ctx->bs_r, kid_count*16);
     714          37 :                         j=gf_bs_read_u32(ctx->bs_r);
     715          37 :                         gf_bs_skip_bytes(ctx->bs_r, j);
     716          37 :                         continue;
     717             :                 }
     718             : 
     719             :                 /*store key IDs*/
     720          97 :                 cstr->KID_count = kid_count;
     721          97 :                 pos = (u32) gf_bs_get_position(ctx->bs_r);
     722          97 :                 cstr->KIDs = (bin128 *)gf_realloc(cstr->KIDs, cstr->KID_count*sizeof(bin128));
     723          97 :                 cstr->keys = (bin128 *)gf_realloc(cstr->keys, cstr->KID_count*sizeof(bin128));
     724             : 
     725          97 :                 memmove(cstr->KIDs, pssh_data + pos, cstr->KID_count*sizeof(bin128));
     726          97 :                 gf_bs_skip_bytes(ctx->bs_r, cstr->KID_count*sizeof(bin128));
     727          97 :                 priv_len = gf_bs_read_u32(ctx->bs_r);
     728          97 :                 pos = (u32) gf_bs_get_position(ctx->bs_r);
     729             : 
     730             :                 /*GPAC DRM TEST system info, used to validate cypher offset in CENC packager
     731             :                         keyIDs as usual (before private data)
     732             :                         URL len on 8 bits
     733             :                         URL
     734             :                         keys, cyphered with our magic key :)
     735             :                 */
     736          97 :                 cypherOffset = pssh_data[pos] + 1;
     737          97 :                 gf_bin128_parse("0x6770616363656E6364726D746F6F6C31", cypherKey);
     738          97 :                 gf_bin128_parse("0x00000000000000000000000000000001", cypherIV);
     739             : 
     740          97 :                 enc_payload_len = priv_len - cypherOffset;
     741          97 :                 if ((priv_len < cypherOffset) || (enc_payload_len < (u32) (cstr->KID_count*sizeof(bin128)))) {
     742           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC/ISMA] Invalid GPAC init blob\n"));
     743          97 :                         return GF_NON_COMPLIANT_BITSTREAM;
     744             :                 }
     745             : 
     746          97 :                 mc = gf_crypt_open(GF_AES_128, GF_CTR);
     747          97 :                 if (!mc) {
     748           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC/ISMA] Cannot open AES-128 CTR\n"));
     749             :                         return GF_IO_ERR;
     750             :                 }
     751          97 :                 enc_data = gf_malloc(priv_len - cypherOffset);
     752          97 :                 memcpy(enc_data, pssh_data + pos + cypherOffset, priv_len - cypherOffset);
     753          97 :                 gf_crypt_init(mc, cypherKey, cypherIV);
     754          97 :                 gf_crypt_decrypt(mc, enc_data, priv_len - cypherOffset);
     755          97 :                 gf_crypt_close(mc);
     756             : 
     757          97 :                 memmove(cstr->keys, enc_data, cstr->KID_count*sizeof(bin128));
     758          97 :                 gf_bs_skip_bytes(ctx->bs_r, cstr->KID_count*sizeof(bin128));
     759          97 :                 gf_free(enc_data);
     760             : 
     761          97 :                 return cenc_dec_load_keys(ctx, cstr);
     762             :         }
     763             : 
     764           1 :         if (cinfo_prop) {
     765           0 :                 cinfo = gf_crypt_info_load(cinfo_prop->value.string, &e);
     766           0 :                 if (!cinfo) {
     767           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC/ISMA] Failed to open crypt info file %s\n", cinfo_prop->value.string));
     768           0 :                         return e;
     769             :                 }
     770             :         }
     771           1 :         if (!cinfo) cinfo = ctx->cinfo;
     772             : 
     773           1 :         if (cinfo) {
     774             :                 GF_TrackCryptInfo *any_tci = NULL;
     775             :                 GF_TrackCryptInfo *tci = NULL;
     776           1 :                 u32 count = gf_list_count(cinfo->tcis);
     777           1 :                 prop = gf_filter_pid_get_property(pid, GF_PROP_PID_ID);
     778           0 :                 for (i=0; i<count; i++) {
     779           1 :                         tci = gf_list_get(cinfo->tcis, i);
     780           1 :                         if (tci->trackID && prop && (tci->trackID==prop->value.uint)) {
     781             :                                 break;
     782             :                         }
     783           0 :                         if (!any_tci && !tci->trackID) any_tci = tci;
     784           0 :                         if ((cinfo != ctx->cinfo) && !any_tci) any_tci = tci;
     785             :                         tci = NULL;
     786             :                 }
     787           1 :                 if (!tci && any_tci) tci = any_tci;
     788             : 
     789           1 :                 if (tci) {
     790           1 :                         cstr->KID_count = tci->nb_keys;
     791           1 :                         cstr->KIDs = (bin128 *)gf_realloc(cstr->KIDs, tci->nb_keys*sizeof(bin128));
     792           1 :                         cstr->keys = (bin128 *)gf_realloc(cstr->keys, tci->nb_keys*sizeof(bin128));
     793           1 :                         for (i=0; i<tci->nb_keys; i++) {
     794           1 :                                 memcpy(cstr->KIDs[i], tci->keys[i].KID, sizeof(bin128));
     795           1 :                                 memcpy(cstr->keys[i], tci->keys[i].key, sizeof(bin128));
     796             :                         }
     797           1 :                         if (cinfo != ctx->cinfo)
     798           0 :                                 gf_crypt_info_del(cinfo);
     799             : 
     800           1 :                         return cenc_dec_load_keys(ctx, cstr);
     801             :                 }
     802           0 :                 if (cinfo != ctx->cinfo)
     803           0 :                         gf_crypt_info_del(cinfo);
     804             :         }
     805             : 
     806           0 :         if (ctx->keys.nb_items) {
     807             :                 return GF_OK;
     808             :         }
     809             : 
     810           0 :         if (ctx->decrypt!=DECRYPT_FULL) return GF_OK;
     811           0 :         GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[CENC/ISMA] No supported system ID, no key found, aborting!\n\tUse '--decrypt=nokey' to force decrypting\n"));
     812             :         return GF_NOT_SUPPORTED;
     813             : }
     814             : 
     815           5 : static GF_Err cenc_dec_setup_adobe(GF_CENCDecCtx *ctx, GF_CENCDecStream *cstr, u32 scheme_type, u32 scheme_version, const char *scheme_uri, const char *kms_uri)
     816             : {
     817             :         GF_CryptInfo *cinfo=NULL;
     818             :         const GF_PropertyValue *prop;
     819           5 :         GF_FilterPid *pid = cstr->ipid;
     820           5 :         Bool is_playing = (cstr->state == DECRYPT_STATE_PLAY) ? GF_TRUE : GF_FALSE;
     821             : 
     822           5 :         cstr->state = DECRYPT_STATE_ERROR;
     823             : 
     824           5 :         if (scheme_type != GF_ISOM_ADOBE_SCHEME) return GF_NOT_SUPPORTED;
     825           5 :         if (scheme_version != 1) return GF_NOT_SUPPORTED;
     826             : 
     827             : 
     828           5 :         if (cstr->KID_count) return GF_OK;
     829             : 
     830           5 :         cstr->is_adobe = GF_TRUE;
     831             : 
     832           5 :         cstr->state = is_playing ? DECRYPT_STATE_PLAY : DECRYPT_STATE_SETUP;
     833             : 
     834           5 :         prop = gf_filter_pid_get_property(cstr->ipid, GF_PROP_PID_DECRYPT_INFO);
     835           5 :         if (!prop) prop = gf_filter_pid_get_property(cstr->ipid, GF_PROP_PID_CRYPT_INFO);
     836             : 
     837           5 :         if (prop) {
     838             :                 GF_Err e;
     839           0 :                 cinfo = gf_crypt_info_load(prop->value.string, &e);
     840           0 :                 if (!cinfo) {
     841           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC/ISMA] Failed to open crypt info file %s\n", prop->value.string));
     842           0 :                         return e;
     843             :                 }
     844             :         }
     845           5 :         if (!cinfo) cinfo = ctx->cinfo;
     846             : 
     847           5 :         if (cinfo) {
     848             :                 GF_TrackCryptInfo *any_tci = NULL;
     849             :                 GF_TrackCryptInfo *tci = NULL;
     850           5 :                 u32 i, count = gf_list_count(cinfo->tcis);
     851           5 :                 prop = gf_filter_pid_get_property(pid, GF_PROP_PID_ID);
     852           0 :                 for (i=0; i<count; i++) {
     853           5 :                         tci = gf_list_get(cinfo->tcis, i);
     854           5 :                         if (tci->trackID && prop && (tci->trackID==prop->value.uint)) {
     855             :                                 break;
     856             :                         }
     857           0 :                         if (!any_tci && !tci->trackID) any_tci = tci;
     858           0 :                         if ((cinfo != ctx->cinfo) && !any_tci) any_tci = tci;
     859             :                         tci = NULL;
     860             :                 }
     861           5 :                 if (!tci && any_tci) tci = any_tci;
     862             : 
     863           5 :                 if (tci) {
     864           5 :                         cstr->KID_count = tci->nb_keys;
     865           5 :                         cstr->KIDs = (bin128 *)gf_realloc(cstr->KIDs, tci->nb_keys*sizeof(bin128));
     866           5 :                         cstr->keys = (bin128 *)gf_realloc(cstr->keys, tci->nb_keys*sizeof(bin128));
     867           5 :                         for (i=0; i<tci->nb_keys; i++) {
     868           5 :                                 memcpy(cstr->KIDs[i], tci->keys[i].KID, sizeof(bin128));
     869           5 :                                 memcpy(cstr->keys[i], tci->keys[i].key, sizeof(bin128));
     870             :                         }
     871           5 :                         if (cinfo != ctx->cinfo)
     872           0 :                                 gf_crypt_info_del(cinfo);
     873             :                         return GF_OK;
     874             :                 }
     875           0 :                 if (cinfo != ctx->cinfo)
     876           0 :                         gf_crypt_info_del(cinfo);
     877             :         }
     878           0 :         GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[CENC/ISMA] No supported system ID, no key found\n"));
     879             :         return GF_NOT_SUPPORTED;
     880             : }
     881             : 
     882          99 : static GF_Err cenc_dec_access_cenc(GF_CENCDecCtx *ctx, GF_CENCDecStream *cstr, Bool is_play)
     883             : {
     884             :         u32 i;
     885          99 :         if (is_play) {
     886          98 :                 if (cstr->state != DECRYPT_STATE_SETUP)
     887             :                         return GF_SERVICE_ERROR;
     888             : 
     889             :                 //if (!ctx->nb_allow_play) return GF_AUTHENTICATION_FAILURE;
     890             :                 //ctx->nb_allow_play--;
     891             : 
     892             :                 /*open decrypter - we do NOT initialize decrypter; it wil be done when we decrypt the first crypted sample*/
     893         101 :                 for (i=0; i<cstr->nb_crypts; i++) {
     894             :                         assert(!cstr->crypts[i].crypt);
     895         101 :                         if (cstr->is_cenc)
     896          82 :                                 cstr->crypts[i].crypt = gf_crypt_open(GF_AES_128, GF_CTR);
     897             :                         else
     898          19 :                                 cstr->crypts[i].crypt = gf_crypt_open(GF_AES_128, GF_CBC);
     899         101 :                         if (!cstr->crypts[i].crypt) return GF_IO_ERR;
     900             :                 }
     901          98 :                 cstr->state = DECRYPT_STATE_PLAY;
     902             :                 return GF_OK;
     903             :         } else {
     904           1 :                 if (cstr->state != DECRYPT_STATE_PLAY)
     905             :                         return GF_SERVICE_ERROR;
     906           1 :                 for (i=0; i<cstr->nb_crypts; i++) {
     907           1 :                         if (cstr->crypts[i].crypt) gf_crypt_close(cstr->crypts[i].crypt);
     908           1 :                         cstr->crypts[i].crypt = NULL;
     909             :                 }
     910           1 :                 cstr->state = DECRYPT_STATE_SETUP;
     911             :                 return GF_OK;
     912             :         }
     913             :         return GF_BAD_PARAM;
     914             : }
     915             : 
     916           5 : static GF_Err cenc_dec_access_adobe(GF_CENCDecCtx *ctx, GF_CENCDecStream *cstr, Bool is_play)
     917             : {
     918           5 :         if (is_play) {
     919           5 :                 if (cstr->state != DECRYPT_STATE_SETUP)
     920             :                         return GF_SERVICE_ERROR;
     921             :                 assert(!cstr->crypts[0].crypt);
     922             : 
     923           5 :                 cstr->crypts[0].crypt = gf_crypt_open(GF_AES_128, GF_CBC);
     924           5 :                 if (!cstr->crypts[0].crypt) return GF_IO_ERR;
     925             : 
     926           5 :                 cstr->state = DECRYPT_STATE_PLAY;
     927             :                 return GF_OK;
     928             :         } else {
     929           0 :                 if (cstr->state != DECRYPT_STATE_PLAY)
     930             :                         return GF_SERVICE_ERROR;
     931           0 :                 if (cstr->crypts[0].crypt) gf_crypt_close(cstr->crypts[0].crypt);
     932           0 :                 cstr->crypts[0].crypt = NULL;
     933           0 :                 cstr->state = DECRYPT_STATE_SETUP;
     934             :                 return GF_OK;
     935             :         }
     936             :         return GF_BAD_PARAM;
     937             : }
     938             : 
     939       18805 : static GF_Err denc_dec_push_iv(GF_CENCDecStream *cstr, u32 key_idx, u8 *IV, u32 iv_size, u32 const_iv_size, const u8 *const_iv)
     940             : {
     941             :         GF_Err e;
     942             : 
     943       18805 :         if (!cstr->crypt_init) {
     944         267 :                 if (const_iv) {
     945           6 :                         memcpy(IV, const_iv, const_iv_size);
     946             :                 }
     947         267 :                 e = gf_crypt_init(cstr->crypts[key_idx].crypt, cstr->crypts[key_idx].key, IV);
     948         267 :                 if (e) {
     949           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Cannot initialize AES-128 AES-128 %s (%s)\n", cstr->is_cenc ? "CTR" : "CBC", gf_error_to_string(e)) );
     950             :                         return GF_IO_ERR;
     951             :                 }
     952             :         } else {
     953             :                 //always restore IV at beginning of sample regardless of the mode (const IV or IV CBC or CTR)
     954       18538 :                 if (!cstr->is_cbc) {
     955       16241 :                         if (!iv_size)
     956             :                                 iv_size = const_iv_size;
     957             : 
     958       16241 :                         memmove(&IV[1], &IV[0], sizeof(char) * iv_size);
     959       16241 :                         IV[0] = 0;      /*begin of counter*/
     960       16241 :                         e = gf_crypt_set_IV(cstr->crypts[key_idx].crypt, IV, 17);
     961             :                 } else {
     962        2297 :                         if (const_iv) {
     963         927 :                                 memcpy(IV, const_iv, const_iv_size);
     964             :                         }
     965        2297 :                         e = gf_crypt_set_IV(cstr->crypts[key_idx].crypt, IV, 16);
     966             :                 }
     967       18538 :                 if (e) {
     968           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Cannot set key AES-128 %s (%s)\n", cstr->is_cenc ? "CTR" : "CBC", gf_error_to_string(e)) );
     969             :                         return e;
     970             :                 }
     971             :         }
     972             :         return GF_OK;
     973             : }
     974             : 
     975             : u8 key_info_get_iv_size(const u8 *key_info, u32 nb_keys, u32 idx, u8 *const_iv_size, const u8 **const_iv);
     976             : 
     977             : 
     978       18238 : static GF_Err cenc_dec_process_cenc(GF_CENCDecCtx *ctx, GF_CENCDecStream *cstr, GF_FilterPacket *in_pck)
     979             : {
     980             :         GF_Err e = GF_OK;
     981             :         u32 subsample_count;
     982             :         u32 data_size;
     983             :         u8 *out_data;
     984             :         const char *sai_payload=NULL;
     985             :         u32 saiz=0;
     986             :         u32 min_sai_size_subs = 6;
     987             :         GF_FilterPacket *out_pck;
     988             :         const GF_PropertyValue *prop;
     989             :         u32 skey_const_iv_size = 0;
     990             :         Bool has_subsamples = GF_FALSE;
     991             :         const u8 *skey_const_iv = NULL;
     992             : 
     993             :         //packet has been fetched, we now MUST have a key info
     994       18238 :         if (!cstr->cenc_ki) {
     995           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Packet encrypted but no KID info\n" ) );
     996             :                 return GF_SERVICE_ERROR;
     997             :         }
     998             : 
     999       18238 :         gf_filter_pck_get_data(in_pck, &data_size);
    1000             : 
    1001       18238 :         if (!data_size || ! gf_filter_pck_get_crypt_flags(in_pck)) {
    1002        1686 :                 out_pck = gf_filter_pck_new_ref(cstr->opid, 0, 0, in_pck);
    1003        1686 :                 if (!out_pck) return GF_OUT_OF_MEM;
    1004        1686 :                 gf_filter_pck_merge_properties(in_pck, out_pck);
    1005        1686 :                 gf_filter_pck_set_property(out_pck, GF_PROP_PCK_CENC_SAI, NULL);
    1006        1686 :                 gf_filter_pck_set_crypt_flags(out_pck, 0);
    1007        1686 :                 gf_filter_pck_send(out_pck);
    1008             :                 return GF_OK;
    1009             :         }
    1010             : 
    1011             : 
    1012       16552 :         prop = gf_filter_pck_get_property(in_pck, GF_PROP_PCK_CENC_SAI);
    1013       16552 :         if (prop) {
    1014       16222 :                 sai_payload = prop->value.data.ptr;
    1015       16222 :                 saiz = prop->value.data.size;
    1016       16222 :                 gf_bs_reassign_buffer(ctx->bs_r, sai_payload, saiz);
    1017             :         }
    1018             : 
    1019             :         //CENC can use inplace processing for decryption
    1020       16552 :         out_pck = gf_filter_pck_new_clone(cstr->opid, in_pck, &out_data);
    1021       16552 :         if (!out_pck) return GF_OUT_OF_MEM;
    1022             : 
    1023             :         subsample_count = 0;
    1024             : 
    1025       16552 :         if (cstr->multikey) {
    1026             :                 u8 IV[17];
    1027             :                 u32 k, nb_iv_init;
    1028             :                 min_sai_size_subs = 8;
    1029        2253 :                 if (!sai_payload
    1030             :                         //we need at least 2bytes for IV counts and 4 for nb_subsamples, mandatory in multikey
    1031        2253 :                         || (gf_bs_available(ctx->bs_r) < 6 )
    1032             :                 ) {
    1033           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Multikey with no associated auxiliary info !\n" ) );
    1034             :                         e = GF_NON_COMPLIANT_BITSTREAM;
    1035           0 :                         goto exit;
    1036             :                 }
    1037        2253 :                 nb_iv_init = gf_bs_read_u16(ctx->bs_r);
    1038             :                 //init all non-const IV listed
    1039        4506 :                 for (k=0; k<nb_iv_init; k++) {
    1040             :                         u8 IV_size;
    1041        4506 :                         u32 kidx = gf_bs_read_u16(ctx->bs_r);
    1042             : 
    1043        4506 :                         if (!kidx || (kidx>cstr->nb_crypts)) {
    1044           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Corrupted CENC sai, kidx %d but valid range is [1,%d]\n", kidx, cstr->nb_crypts));
    1045             :                                 e = GF_NON_COMPLIANT_BITSTREAM;
    1046             :                                 goto exit;
    1047             :                         }
    1048        4506 :                         IV_size = key_info_get_iv_size(cstr->cenc_ki->value.data.ptr, cstr->cenc_ki->value.data.size, kidx, NULL, NULL);
    1049        4506 :                         if (!IV_size) {
    1050           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[CENC] invalid SAI multikey with IV size 0\n" ));
    1051             :                                 e = GF_NON_COMPLIANT_BITSTREAM;
    1052             :                                 goto exit;
    1053             :                         }
    1054             :                         //memset to 0 in case we use <16 byte key
    1055             :                         memset(IV, 0, sizeof(u8)*17);
    1056        4506 :                         gf_bs_read_data(ctx->bs_r, IV, IV_size);
    1057             : 
    1058        4506 :                         e = denc_dec_push_iv(cstr, kidx-1, IV, IV_size, 0, NULL);
    1059        4506 :                         if (e) goto exit;
    1060             :                 }
    1061        2253 :                 if (nb_iv_init < cstr->multikey) {
    1062             :                         //init all const IV listed
    1063           0 :                         for (k=0; k<cstr->multikey; k++) {
    1064             :                                 u8 const_iv_size;
    1065           0 :                                 const u8 *const_iv=NULL;
    1066           0 :                                 u8 IV_size = key_info_get_iv_size(cstr->cenc_ki->value.data.ptr, cstr->cenc_ki->value.data.size, k+1, &const_iv_size, &const_iv);
    1067           0 :                                 if (IV_size) continue;
    1068             :                                 memset(IV, 0, sizeof(char)*17);
    1069           0 :                                 e = denc_dec_push_iv(cstr, k, IV, 0, const_iv_size, const_iv);
    1070           0 :                                 if (e) goto exit;
    1071             :                         }
    1072             :                 }
    1073             :         } else {
    1074             :                 u8 IV[17];
    1075             :                 u32 iv_size = 0;
    1076             : 
    1077             :                 //check single key IV is OK - in multikey we ALWAYS have SAI payload
    1078       14299 :                 if (sai_payload) {
    1079       13969 :                         iv_size = cstr->cenc_ki->value.data.ptr[3];
    1080             :                 }
    1081       13969 :                 if (!iv_size) {
    1082         933 :                         if (! cstr->cenc_ki->value.data.ptr[3]) {
    1083         933 :                                 skey_const_iv_size = cstr->cenc_ki->value.data.ptr[20];
    1084             :                         }
    1085             :                 }
    1086             : 
    1087       14299 :                 if (!sai_payload && !skey_const_iv_size) {
    1088           0 :                         if (ctx->decrypt == DECRYPT_SKIP) {
    1089           0 :                                 GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[CENC] Packet encrypted but no SAI info nor constant IV\n" ) );
    1090             :                                 e = GF_OK;
    1091           0 :                                 goto send_packet;
    1092             :                         }
    1093           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Packet encrypted but no SAI info nor constant IV\n" ) );
    1094           0 :                         return GF_SERVICE_ERROR;
    1095             :                 }
    1096             : 
    1097             :                 //memset to 0 in case we use <16 byte key
    1098             :                 memset(IV, 0, sizeof(char)*17);
    1099       14299 :                 if (sai_payload) {
    1100       13969 :                         if (iv_size)
    1101       13366 :                                 gf_bs_read_data(ctx->bs_r, IV, iv_size);
    1102             :                 }
    1103             : 
    1104       14299 :                 if (skey_const_iv_size)
    1105         933 :                         skey_const_iv = cstr->cenc_ki->value.data.ptr+21;
    1106             : 
    1107       14299 :                 e = denc_dec_push_iv(cstr, 0, IV, iv_size, skey_const_iv_size, skey_const_iv);
    1108       14299 :                 if (e) goto exit;
    1109             :         }
    1110       16552 :         cstr->crypt_init = GF_TRUE;
    1111             : 
    1112       16552 :         if (cstr->key_error) {
    1113             :                 e = cstr->key_error;
    1114             :                 goto exit;
    1115             :         }
    1116             : 
    1117       16552 :         if (cstr->multikey) {
    1118        2253 :                 subsample_count = gf_bs_read_u32(ctx->bs_r);
    1119             :                 has_subsamples = GF_TRUE;
    1120             :         } else {
    1121       14299 :                 if (sai_payload && gf_bs_available(ctx->bs_r)) {
    1122       10009 :                         subsample_count = gf_bs_read_u16(ctx->bs_r);
    1123             :                         has_subsamples = GF_TRUE;
    1124             :                 }
    1125             :         }
    1126       16552 :         if (has_subsamples && !subsample_count) {
    1127           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[CENC] Subsample field present but no subsamples indicated, assuming clear payload\n"));
    1128             :                 goto send_packet;
    1129             :         }
    1130             : 
    1131             :         //sub-sample encryption, always on for multikey
    1132       16552 :         if (subsample_count || cstr->multikey) {
    1133             :                 u32 cur_pos = 0;
    1134             : 
    1135       70204 :                 while (cur_pos < data_size) {
    1136       57942 :                         u8 const_iv_size=0;
    1137       57942 :                         const u8 *const_iv=NULL;
    1138             :                         u32 kidx = 0;
    1139             :                         u32 bytes_clear_data, bytes_encrypted_data;
    1140       57942 :                         if (subsample_count==0) {
    1141           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Corrupted CENC sai, not enough subsamples described\n" ));
    1142             :                                 e = GF_NON_COMPLIANT_BITSTREAM;
    1143           0 :                                 goto exit;
    1144             :                         }
    1145       57942 :                         if (gf_bs_available(ctx->bs_r) < min_sai_size_subs) {
    1146           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Corrupted CENC sai, not enough bytes in subsample info\n" ));
    1147             :                                 e = GF_NON_COMPLIANT_BITSTREAM;
    1148             :                                 goto exit;
    1149             :                         }
    1150       57942 :                         if (cstr->multikey) {
    1151       20277 :                                 kidx = gf_bs_read_u16(ctx->bs_r);
    1152             :                                 //check index is valid
    1153       20277 :                                 if (kidx>cstr->nb_crypts) {
    1154           0 :                                         GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Corrupted CENC sai key idx %d, should be in range [1, %d]\n", kidx, cstr->nb_crypts));
    1155             :                                         e = GF_NON_COMPLIANT_BITSTREAM;
    1156             :                                         goto exit;
    1157             :                                 }
    1158       20277 :                                 bytes_clear_data = gf_bs_read_u16(ctx->bs_r);
    1159       20277 :                                 bytes_encrypted_data = gf_bs_read_u32(ctx->bs_r);
    1160             : 
    1161       20277 :                                 if (kidx) {
    1162       18024 :                                         key_info_get_iv_size(cstr->cenc_ki->value.data.ptr, cstr->cenc_ki->value.data.size, kidx, &const_iv_size, &const_iv);
    1163       18024 :                                         kidx-=1;
    1164             :                                 }
    1165             :                                 //to clarify in the speck: kidx 0 should be allowed for clear subsamples
    1166        2253 :                                 else if (bytes_encrypted_data) {
    1167           0 :                                         GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Corrupted CENC sai key idx 0 but encrypted payload\n", cstr->nb_crypts));
    1168             :                                         e = GF_NON_COMPLIANT_BITSTREAM;
    1169             :                                         goto exit;
    1170             :                                 }
    1171             :                         } else {
    1172       37665 :                                 const_iv = skey_const_iv;
    1173       37665 :                                 const_iv_size = skey_const_iv_size;
    1174       37665 :                                 bytes_clear_data = gf_bs_read_u16(ctx->bs_r);
    1175       37665 :                                 bytes_encrypted_data = gf_bs_read_u32(ctx->bs_r);
    1176             :                         }
    1177             : 
    1178       57942 :                         subsample_count--;
    1179             : 
    1180             :                         //const IV is applied at each subsample
    1181       57942 :                         if (const_iv_size) {
    1182             :                                 u8 IV[17];
    1183        2895 :                                 memcpy(IV, const_iv, const_iv_size);
    1184        2895 :                                 if (const_iv_size == 8)
    1185             :                                         memset(IV+8, 0, sizeof(char)*8);
    1186        2895 :                                 gf_crypt_set_IV(cstr->crypts[kidx].crypt, IV, 16);
    1187             :                         }
    1188       57942 :                         if (cur_pos + bytes_clear_data + bytes_encrypted_data > data_size) {
    1189           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Corrupted CENC sai, subsample info describe more bytes (%d) than in packet (%d)\n", cur_pos + bytes_clear_data + bytes_encrypted_data , data_size ));
    1190             :                                 e = GF_NON_COMPLIANT_BITSTREAM;
    1191             :                                 goto exit;
    1192             :                         }
    1193             :                         /*skip clear data*/
    1194             :                         cur_pos += bytes_clear_data;
    1195             : 
    1196       57942 :                         if (!cstr->crypts[kidx].key_valid) {
    1197             :                                 cur_pos += bytes_encrypted_data;
    1198           0 :                                 continue;
    1199             :                         }
    1200             : 
    1201             :                         //pattern decryption
    1202       57942 :                         if (cstr->cenc_pattern) {
    1203             :                                 u32 pos = cur_pos;
    1204             :                                 u32 res = bytes_encrypted_data;
    1205       11679 :                                 u32 cryp_block = 16 * cstr->cenc_pattern->value.frac.den;
    1206       11679 :                                 u32 full_block = 16 * (cstr->cenc_pattern->value.frac.den + cstr->cenc_pattern->value.frac.num);
    1207             : 
    1208       11679 :                                 if (cstr->is_cbc) {
    1209             :                                         u32 clear_trailing = res % 16;
    1210             :                                         res -= clear_trailing;
    1211             :                                 }
    1212             : 
    1213       24605 :                                 while (res) {
    1214       22350 :                                         gf_crypt_decrypt(cstr->crypts[kidx].crypt, out_data + pos, (res >= cryp_block) ? cryp_block : res);
    1215       22350 :                                         if (res >= full_block) {
    1216       12926 :                                                 pos += full_block;
    1217             :                                                 assert(res>=full_block);
    1218       12926 :                                                 res -= full_block;
    1219             :                                         } else {
    1220             :                                                 res = 0;
    1221             :                                         }
    1222             :                                 }
    1223             :                         }
    1224             :                         //full subsample decryption
    1225             :                         else {
    1226       46263 :                                 gf_crypt_decrypt(cstr->crypts[kidx].crypt, out_data+cur_pos, bytes_encrypted_data);
    1227             :                         }
    1228             :                         cur_pos += bytes_encrypted_data;
    1229             :                 }
    1230             :         }
    1231             :         //full sample encryption in single key mode
    1232             :         else {
    1233        4290 :                 if (cstr->is_cenc) {
    1234        3300 :                         gf_crypt_decrypt(cstr->crypts[0].crypt, out_data, data_size);
    1235             :                 } else {
    1236         990 :                         u32 ret = data_size % 16;
    1237         990 :                         if (data_size >= 16) {
    1238         990 :                                 gf_crypt_decrypt(cstr->crypts[0].crypt, out_data, data_size-ret);
    1239             :                         }
    1240             :                 }
    1241             :         }
    1242             : 
    1243       16552 : send_packet:
    1244       16552 :         gf_filter_pck_merge_properties(in_pck, out_pck);
    1245       16552 :         gf_filter_pck_set_property(out_pck, GF_PROP_PCK_CENC_SAI, NULL);
    1246       16552 :         gf_filter_pck_set_crypt_flags(out_pck, 0);
    1247             : 
    1248       16552 :         gf_filter_pck_send(out_pck);
    1249             : 
    1250       16552 : exit:
    1251       16552 :         if (e && out_pck) {
    1252           0 :                 gf_filter_pck_discard(out_pck);
    1253             :         }
    1254             :         return e;
    1255             : }
    1256             : 
    1257             : 
    1258         932 : static GF_Err cenc_dec_process_adobe(GF_CENCDecCtx *ctx, GF_CENCDecStream *cstr, GF_FilterPacket *in_pck)
    1259             : {
    1260             :         u32 data_size;
    1261             :         const u8 *in_data;
    1262             :         u8 *out_data;
    1263             :         GF_FilterPacket *out_pck;
    1264             :         GF_Err e;
    1265             :         u32 offset, size;
    1266             :         Bool encrypted_au;
    1267             : 
    1268         932 :         if (!cstr->crypts[0].crypt)
    1269             :                 return GF_SERVICE_ERROR;
    1270             : 
    1271         932 :         in_data = gf_filter_pck_get_data(in_pck, &data_size);
    1272         932 :         out_pck = gf_filter_pck_new_alloc(cstr->opid, data_size, &out_data);
    1273         932 :         if (!out_pck) return GF_OUT_OF_MEM;
    1274             : 
    1275         932 :         memcpy(out_data, in_data, data_size);
    1276             : 
    1277             :         offset=0;
    1278         932 :         size = data_size;
    1279         932 :         encrypted_au = out_data[0] ? GF_TRUE : GF_FALSE;
    1280         932 :         if (encrypted_au) {
    1281             :                 u32 trim_bytes;
    1282             :                 char IV[17];
    1283         346 :                 if (size<17) {
    1284           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[ADOBE] Error in sample size, %d bytes remain but at least 17 are required\n", size ) );
    1285           0 :                         return GF_NON_COMPLIANT_BITSTREAM;
    1286             :                 }
    1287             :                 memmove(IV, out_data+1, 16);
    1288         346 :                 if (!cstr->crypt_init) {
    1289           5 :                         e = gf_crypt_init(cstr->crypts[0].crypt, cstr->keys[0], IV);
    1290           5 :                         if (e) {
    1291           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[ADOBE] Cannot initialize AES-128 CBC (%s)\n", gf_error_to_string(e)) );
    1292             :                                 return GF_IO_ERR;
    1293             :                         }
    1294           5 :                         cstr->crypt_init = GF_TRUE;
    1295             :                 } else {
    1296         341 :                         e = gf_crypt_set_IV(cstr->crypts[0].crypt, IV, GF_AES_128_KEYSIZE);
    1297         341 :                         if (e) {
    1298           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[ADOBE] Cannot set state AES-128 CBC (%s)\n", gf_error_to_string(e)) );
    1299             :                                 return GF_IO_ERR;
    1300             :                         }
    1301             :                 }
    1302             :                 offset += 17;
    1303         346 :                 size -= 17;
    1304             : 
    1305         346 :                 gf_crypt_decrypt(cstr->crypts[0].crypt, out_data+offset, size);
    1306         346 :                 trim_bytes = out_data[offset + size - 1];
    1307         346 :                 size -= trim_bytes;
    1308             :         } else {
    1309             :                 offset += 1;
    1310         586 :                 size -= 1;
    1311             :         }
    1312         932 :         memmove(out_data, out_data+offset, size);
    1313         932 :         gf_filter_pck_truncate(out_pck, size);
    1314         932 :         gf_filter_pck_merge_properties(in_pck, out_pck);
    1315             : 
    1316         932 :         gf_filter_pck_send(out_pck);
    1317             :         return GF_OK;
    1318             : }
    1319             : 
    1320         108 : static void cenc_dec_stream_del(GF_CENCDecStream *cstr)
    1321             : {
    1322         108 :         if (cstr->crypts) {
    1323             :                 u32 i;
    1324         114 :                 for (i=0; i<cstr->nb_crypts; i++) {
    1325         114 :                         if (cstr->crypts[i].crypt) gf_crypt_close(cstr->crypts[i].crypt);
    1326             :                 }
    1327         108 :                 gf_free(cstr->crypts);
    1328             :         }
    1329         108 :         if (cstr->KIDs) gf_free(cstr->KIDs);
    1330         108 :         if (cstr->keys) gf_free(cstr->keys);
    1331             : 
    1332             : 
    1333         108 :         gf_free(cstr);
    1334         108 : }
    1335             : 
    1336         287 : static GF_Err cenc_dec_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
    1337             : {
    1338             :         const GF_PropertyValue *prop;
    1339             :         GF_Err e = GF_OK;
    1340             :         u32 scheme_type = 0;
    1341             :         u32 scheme_version = 0;
    1342             :         const char *scheme_uri = NULL;
    1343             :         const char *kms_uri = NULL;
    1344             :         u32 nb_keys;
    1345             :         GF_CENCDecStream *cstr;
    1346         287 :         GF_CENCDecCtx *ctx = (GF_CENCDecCtx *)gf_filter_get_udta(filter);
    1347             :         u32 i;
    1348             : 
    1349         287 :         prop = gf_filter_pid_get_property(pid, GF_PROP_PID_PROTECTION_SCHEME_TYPE);
    1350         287 :         if (prop) scheme_type = prop->value.uint;
    1351             : 
    1352         287 :         if (is_remove) {
    1353           0 :                 cstr = gf_filter_pid_get_udta(pid);
    1354           0 :                 if (cstr->opid) {
    1355           0 :                         gf_filter_pid_remove(cstr->opid);
    1356             :                 }
    1357           0 :                 gf_list_del_item(ctx->streams, cstr);
    1358           0 :                 cenc_dec_stream_del(cstr);
    1359           0 :                 return GF_OK;
    1360             :         }
    1361             : 
    1362         287 :         if (! gf_filter_pid_check_caps(pid))
    1363             :                 return GF_NOT_SUPPORTED;
    1364             : 
    1365         287 :         cstr = gf_filter_pid_get_udta(pid);
    1366         287 :         if (!cstr) {
    1367         108 :                 GF_SAFEALLOC(cstr, GF_CENCDecStream);
    1368         108 :                 if (!cstr) return GF_OUT_OF_MEM;
    1369         108 :                 cstr->opid = gf_filter_pid_new(filter);
    1370         108 :                 cstr->ipid = pid;
    1371         108 :                 gf_list_add(ctx->streams, cstr);
    1372         108 :                 gf_filter_pid_set_udta(pid, cstr);
    1373         108 :                 gf_filter_pid_set_udta(cstr->opid, cstr);
    1374             :                 //we need full sample
    1375         108 :                 gf_filter_pid_set_framing_mode(pid, GF_TRUE);
    1376             : 
    1377             :         }
    1378             : 
    1379         287 :         prop = gf_filter_pid_get_property(pid, GF_PROP_PID_PROTECTION_SCHEME_VERSION);
    1380         287 :         if (prop) scheme_version = prop->value.uint;
    1381         287 :         prop = gf_filter_pid_get_property(pid, GF_PROP_PID_PROTECTION_SCHEME_URI);
    1382         287 :         if (prop) scheme_uri = prop->value.string;
    1383         287 :         prop = gf_filter_pid_get_property(pid, GF_PROP_PID_PROTECTION_KMS_URI);
    1384         287 :         if (prop) kms_uri = prop->value.string;
    1385             : 
    1386         287 :         if (ctx->cinfo) {
    1387             :                 u32 stream_id=0;
    1388         276 :                 u32 count = gf_list_count(ctx->cinfo->tcis);
    1389         276 :                 prop = gf_filter_pid_get_property(pid, GF_PROP_PID_ID);
    1390         276 :                 if (!prop) prop = gf_filter_pid_get_property(pid, GF_PROP_PID_ESID);
    1391         276 :                 if (prop) stream_id = prop->value.uint;
    1392             : 
    1393         276 :                 for (i=0; i<count; i++) {
    1394         276 :                         GF_TrackCryptInfo *tci = (GF_TrackCryptInfo *) gf_list_get(ctx->cinfo->tcis, i);
    1395         276 :                         if ((ctx->cinfo->has_common_key && !tci->trackID) || (tci->trackID == stream_id) ) {
    1396         276 :                                 if (tci->force_type) scheme_type = tci->scheme_type;
    1397             :                                 break;
    1398             :                         }
    1399             :                 }
    1400             :         }
    1401             : 
    1402             :         nb_keys = 1;
    1403         287 :         prop = gf_filter_pid_get_property(pid, GF_PROP_PID_CENC_KEY_INFO);
    1404         287 :         if (prop && prop->value.data.ptr && prop->value.data.ptr[0]) {
    1405           6 :                 nb_keys = prop->value.data.ptr[1];
    1406           6 :                 nb_keys<<=8;
    1407           6 :                 nb_keys |= prop->value.data.ptr[2];
    1408             :         }
    1409         287 :         if (nb_keys > cstr->nb_crypts) {
    1410         111 :                 cstr->crypts = gf_realloc(cstr->crypts, sizeof(CENCDecKey) * nb_keys);
    1411         111 :                 memset(&cstr->crypts[cstr->nb_crypts], 0, sizeof(CENCDecKey) * (nb_keys-cstr->nb_crypts) );
    1412             : 
    1413         111 :                 if (cstr->crypts[0].crypt) {
    1414           6 :                         for (i=cstr->nb_crypts; i<nb_keys; i++) {
    1415           3 :                                 if (cstr->is_cenc)
    1416           3 :                                         cstr->crypts[i].crypt = gf_crypt_open(GF_AES_128, GF_CTR);
    1417             :                                 else
    1418           0 :                                         cstr->crypts[i].crypt = gf_crypt_open(GF_AES_128, GF_CBC);
    1419           3 :                                 if (!cstr->crypts[i].crypt) return GF_IO_ERR;
    1420             :                         }
    1421             :                 }
    1422         111 :                 cstr->nb_crypts = nb_keys;
    1423             :         }
    1424             :         //resetup, check decrypter
    1425         287 :         if (cstr->state==DECRYPT_STATE_PLAY) {
    1426          22 :                 for (i=0; i<cstr->nb_crypts; i++) {
    1427          22 :                         if (!cstr->crypts[i].crypt) {
    1428             :                                 return GF_SERVICE_ERROR;
    1429             :                         }
    1430             :                 }
    1431             :         }
    1432             : 
    1433         287 :         switch (scheme_type) {
    1434           5 :         case GF_ISOM_ISMACRYP_SCHEME:
    1435           5 :                 e = cenc_dec_setup_isma(ctx, cstr, scheme_type, scheme_version, scheme_uri, kms_uri);
    1436           5 :                 break;
    1437             :         case GF_ISOM_OMADRM_SCHEME:
    1438             : #ifdef OLD_KEY_FETCHERS
    1439             :                 e = cenc_dec_setup_oma(ctx, cstr, scheme_type, scheme_version, scheme_uri, kms_uri);
    1440             : #else
    1441             :                 e = GF_NOT_SUPPORTED;
    1442             : #endif
    1443             :                 break;
    1444         277 :         case GF_ISOM_CENC_SCHEME:
    1445             :         case GF_ISOM_PIFF_SCHEME:
    1446             :         case GF_ISOM_CBC_SCHEME:
    1447             :         case GF_ISOM_CENS_SCHEME:
    1448             :         case GF_ISOM_CBCS_SCHEME:
    1449         277 :                 e = cenc_dec_setup_cenc(ctx, cstr, scheme_type, scheme_version, scheme_uri, kms_uri);
    1450         277 :                 break;
    1451           5 :         case GF_ISOM_ADOBE_SCHEME:
    1452           5 :                 e = cenc_dec_setup_adobe(ctx, cstr, scheme_type, scheme_version, scheme_uri, kms_uri);
    1453           5 :                 break;
    1454           0 :         default:
    1455           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[CENC/ISMA] Protection scheme type %s not supported\n", gf_4cc_to_str(scheme_type) ) );
    1456             :                 return GF_SERVICE_ERROR;
    1457             :         }
    1458         287 :         if (e) {
    1459           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[CENC/ISMA] Error setting up protection scheme type %s\n", gf_4cc_to_str(scheme_type) ) );
    1460             :                 return e;
    1461             :         }
    1462             : 
    1463             :         //copy properties at init or reconfig
    1464         287 :         gf_filter_pid_copy_properties(cstr->opid, pid);
    1465             : 
    1466         287 :         prop = gf_filter_pid_get_property(pid, GF_PROP_PID_ORIG_STREAM_TYPE);
    1467         287 :         if (prop) {
    1468         287 :                 gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_STREAM_TYPE, & PROP_UINT(prop->value.uint) );
    1469         287 :                 gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_ORIG_STREAM_TYPE, NULL);
    1470             :         }
    1471             :         //remove all cenc properties on output
    1472         287 :         gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_PROTECTION_SCHEME_TYPE, NULL);
    1473         287 :         gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_PROTECTION_SCHEME_VERSION, NULL);
    1474         287 :         gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_PROTECTION_SCHEME_URI, NULL);
    1475         287 :         gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_PROTECTION_KMS_URI, NULL);
    1476         287 :         gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_OMA_PREVIEW_RANGE, NULL);
    1477         287 :         gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_CENC_PSSH, NULL);
    1478         287 :         gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_ENCRYPTED, NULL);
    1479         287 :         gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_CENC_KEY_INFO, NULL);
    1480         287 :         gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_CENC_PATTERN, NULL);
    1481         287 :         gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_HLS_KMS, NULL);
    1482             : 
    1483         287 :         cstr->is_nalu = GF_FALSE;;
    1484         287 :         prop = gf_filter_pid_get_property(pid, GF_PROP_PID_CODECID);
    1485         287 :         if (prop) {
    1486         287 :                 switch (prop->value.uint) {
    1487         128 :                 case GF_CODECID_AVC:
    1488             :                 case GF_CODECID_SVC:
    1489             :                 case GF_CODECID_MVC:
    1490             :                 case GF_CODECID_HEVC:
    1491             :                 case GF_CODECID_HEVC_TILES:
    1492             :                 case GF_CODECID_LHVC:
    1493         128 :                         cstr->is_nalu = GF_TRUE;;
    1494         128 :                         break;
    1495             :                 }
    1496             :         }
    1497             :         return e;
    1498             : }
    1499             : 
    1500             : 
    1501         111 : static Bool cenc_dec_process_event(GF_Filter *filter, const GF_FilterEvent *evt)
    1502             : {
    1503             :         GF_FilterPid *ipid;
    1504             :         GF_CENCDecStream *cstr;
    1505             :         Bool is_play = GF_FALSE;
    1506         111 :         GF_CENCDecCtx *ctx = (GF_CENCDecCtx *)gf_filter_get_udta(filter);
    1507             : 
    1508         111 :         ipid = evt->base.on_pid;
    1509         111 :         if (!ipid) return GF_FALSE;
    1510         111 :         cstr = gf_filter_pid_get_udta(ipid);
    1511         111 :         if (!cstr) return GF_FALSE;
    1512             : 
    1513         111 :         switch (evt->base.type) {
    1514         108 :         case GF_FEVT_PLAY:
    1515             :                 is_play = GF_TRUE;
    1516         109 :         case GF_FEVT_STOP:
    1517         109 :                 if (cstr->is_cenc || cstr->is_cbc) {
    1518          99 :                         cenc_dec_access_cenc(ctx, cstr, is_play);
    1519          10 :                 } else if (cstr->is_adobe) {
    1520           5 :                         cenc_dec_access_adobe(ctx, cstr, is_play);
    1521           5 :                 } else if (cstr->is_oma) {
    1522           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_MEDIA, ("[CENC/ISMA] OMA not supported, canceling filter event\n") );
    1523             :                         return GF_TRUE;
    1524             :                 } else {
    1525           5 :                         cenc_dec_access_isma(ctx, cstr, is_play);
    1526             :                 }
    1527             :                 break;
    1528             :         default:
    1529             :                 break;
    1530             :         }
    1531             :         return GF_FALSE;
    1532             : }
    1533       20209 : static GF_Err cenc_dec_process(GF_Filter *filter)
    1534             : {
    1535       20209 :         GF_CENCDecCtx *ctx = (GF_CENCDecCtx *)gf_filter_get_udta(filter);
    1536       20209 :         u32 i, nb_eos, count = gf_list_count(ctx->streams);
    1537             : 
    1538             :         nb_eos = 0;
    1539       40418 :         for (i=0; i<count; i++) {
    1540             :                 GF_Err e;
    1541       20209 :                 GF_CENCDecStream *cstr = gf_list_get(ctx->streams, i);
    1542       20209 :                 GF_FilterPacket *pck = gf_filter_pid_get_packet(cstr->ipid);
    1543       20209 :                 if (!pck) {
    1544         107 :                         if (gf_filter_pid_is_eos(cstr->ipid)) {
    1545         107 :                                 nb_eos++;
    1546         107 :                                 gf_filter_pid_set_eos(cstr->opid);
    1547             :                         }
    1548         107 :                         continue;
    1549             :                 }
    1550             : 
    1551       20102 :                 if (cstr->is_cenc || cstr->is_cbc) {
    1552       18238 :                         e = cenc_dec_process_cenc(ctx, cstr, pck);
    1553        1864 :                 } else if (cstr->is_oma) {
    1554             :                         e = GF_NOT_SUPPORTED;
    1555        1864 :                 } else if (cstr->is_adobe) {
    1556         932 :                         e = cenc_dec_process_adobe(ctx, cstr, pck);
    1557             :                 } else {
    1558         932 :                         e = cenc_dec_process_isma(ctx, cstr, pck);
    1559             :                 }
    1560       20102 :                 gf_filter_pid_drop_packet(cstr->ipid);
    1561       20102 :                 if (e) return e;
    1562             :         }
    1563       20209 :         if (nb_eos && (nb_eos==count)) return GF_EOS;
    1564       20102 :         return GF_OK;
    1565             : }
    1566             : 
    1567         108 : static GF_Err cenc_dec_initialize(GF_Filter *filter)
    1568             : {
    1569         108 :         GF_CENCDecCtx *ctx = (GF_CENCDecCtx *)gf_filter_get_udta(filter);
    1570             : 
    1571         108 :         if (ctx->keys.nb_items) {
    1572           0 :                 if (ctx->keys.nb_items != ctx->kids.nb_items) {
    1573           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENCCrypt] Number of defined keys (%d) must be the same as number of defined KIDs (%d)\n", ctx->keys.nb_items, ctx->kids.nb_items ));
    1574             :                         return GF_BAD_PARAM;
    1575             :                 }
    1576             :         }
    1577         108 :         ctx->streams = gf_list_new();
    1578         108 :         if (!ctx->streams) return GF_OUT_OF_MEM;
    1579             : 
    1580         108 :         if (ctx->cfile) {
    1581             :                 GF_Err e;
    1582         100 :                 ctx->cinfo = gf_crypt_info_load(ctx->cfile, &e);
    1583         100 :                 if (!ctx->cinfo) {
    1584           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENCCrypt] Cannot load config file %s\n", ctx->cfile ));
    1585           0 :                         return e;
    1586             :                 }
    1587             :         }
    1588         108 :         ctx->bs_r = gf_bs_new((char *) ctx, 1, GF_BITSTREAM_READ);
    1589         108 :         return GF_OK;
    1590             : }
    1591             : 
    1592         108 : static void cenc_dec_finalize(GF_Filter *filter)
    1593             : {
    1594         108 :         GF_CENCDecCtx *ctx = (GF_CENCDecCtx *)gf_filter_get_udta(filter);
    1595             : 
    1596         324 :         while (gf_list_count(ctx->streams)) {
    1597         108 :                 GF_CENCDecStream *cstr = gf_list_pop_back(ctx->streams);
    1598         108 :                 cenc_dec_stream_del(cstr);
    1599             :         }
    1600         108 :         gf_list_del(ctx->streams);
    1601             : 
    1602         108 :         if (ctx->bs_r) gf_bs_del(ctx->bs_r);
    1603         108 :         if (ctx->cinfo) gf_crypt_info_del(ctx->cinfo);
    1604         108 : }
    1605             : 
    1606             : 
    1607             : static const GF_FilterCapability CENCDecCaps[] =
    1608             : {
    1609             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_ENCRYPTED),
    1610             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED,  GF_PROP_PID_UNFRAMED, GF_TRUE),
    1611             :         CAP_4CC(GF_CAPS_INPUT,GF_PROP_PID_PROTECTION_SCHEME_TYPE, GF_ISOM_ISMACRYP_SCHEME),
    1612             :         CAP_4CC(GF_CAPS_INPUT,GF_PROP_PID_PROTECTION_SCHEME_TYPE, GF_ISOM_OMADRM_SCHEME),
    1613             :         CAP_4CC(GF_CAPS_INPUT,GF_PROP_PID_PROTECTION_SCHEME_TYPE, GF_ISOM_CENC_SCHEME),
    1614             :         CAP_4CC(GF_CAPS_INPUT,GF_PROP_PID_PROTECTION_SCHEME_TYPE, GF_ISOM_CENS_SCHEME),
    1615             :         CAP_4CC(GF_CAPS_INPUT,GF_PROP_PID_PROTECTION_SCHEME_TYPE, GF_ISOM_CBC_SCHEME),
    1616             :         CAP_4CC(GF_CAPS_INPUT,GF_PROP_PID_PROTECTION_SCHEME_TYPE, GF_ISOM_CBCS_SCHEME),
    1617             :         CAP_4CC(GF_CAPS_INPUT,GF_PROP_PID_PROTECTION_SCHEME_TYPE, GF_ISOM_ADOBE_SCHEME),
    1618             :         CAP_4CC(GF_CAPS_INPUT,GF_PROP_PID_PROTECTION_SCHEME_TYPE, GF_ISOM_PIFF_SCHEME),
    1619             : 
    1620             :         CAP_UINT(GF_CAPS_OUTPUT_EXCLUDED, GF_PROP_PID_STREAM_TYPE, GF_STREAM_ENCRYPTED),
    1621             :         CAP_UINT(GF_CAPS_OUTPUT_EXCLUDED, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    1622             :         CAP_UINT(GF_CAPS_OUTPUT_EXCLUDED, GF_PROP_PID_CODECID, GF_CODECID_RAW),
    1623             :         //CAP_UINT(GF_CAPS_OUTPUT_STATIC_EXCLUDED, GF_PROP_PID_UNFRAMED, GF_TRUE),
    1624             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_UNFRAMED, GF_FALSE),
    1625             : };
    1626             : 
    1627             : 
    1628             : #define OFFS(_n)        #_n, offsetof(GF_CENCDecCtx, _n)
    1629             : static const GF_FilterArgs GF_CENCDecArgs[] =
    1630             : {
    1631             :         { OFFS(cfile), "crypt file location - see filter help", GF_PROP_STRING, NULL, NULL, 0},
    1632             :         { OFFS(decrypt), "decrypt mode (CENC only)\n"
    1633             :                 "- full: decrypt everything, throwing error if keys are not found\n"
    1634             :                 "- nokey: decrypt everything for which a key is found, skip decryption otherwise\n"
    1635             :                 "- skip: decrypt nothing"
    1636             :                 , GF_PROP_UINT, "full", "full|nokey|skip", GF_ARG_HINT_ADVANCED},
    1637             :         { OFFS(drop_keys), "consider keys with given 1-based indexes as not available (multi-key debug)", GF_PROP_UINT_LIST, NULL, NULL, GF_ARG_HINT_EXPERT},
    1638             :         { OFFS(kids), "define KIDs. If `keys` is empty, consider keys with given KID (as hex string) as not available (debug)", GF_PROP_STRING_LIST, NULL, NULL, GF_ARG_HINT_EXPERT},
    1639             :         { OFFS(keys), "define key values for each of the specified KID", GF_PROP_STRING_LIST, NULL, NULL, GF_ARG_HINT_EXPERT},
    1640             :         {0}
    1641             : };
    1642             : 
    1643             : GF_FilterRegister CENCDecRegister = {
    1644             :         .name = "cdcrypt",
    1645             :         GF_FS_SET_DESCRIPTION("CENC decryptor")
    1646             :         GF_FS_SET_HELP("The CENC decryptor supports decrypting CENC, ISMA and Adobe streams. It uses a configuration file for retrieving keys.\n"
    1647             :         "The syntax is available at https://wiki.gpac.io/Common-Encryption\n"
    1648             :         "The file can be set per PID using the property `DecryptInfo` (highest priority), `CryptInfo` (lower priority) "
    1649             :         "or set at the filter level using [-cfile]() (lowest priority).\n"
    1650             :         "When the file is set per PID, the first `CryptInfo` with the same ID is used, otherwise the first `CryptInfo` is used.")
    1651             :         .private_size = sizeof(GF_CENCDecCtx),
    1652             :         .max_extra_pids=-1,
    1653             :         .args = GF_CENCDecArgs,
    1654             :         SETCAPS(CENCDecCaps),
    1655             :         .configure_pid = cenc_dec_configure_pid,
    1656             :         .initialize = cenc_dec_initialize,
    1657             :         .finalize = cenc_dec_finalize,
    1658             :         .process = cenc_dec_process,
    1659             :         .process_event = cenc_dec_process_event
    1660             :         //for now only one PID per CENC decryptor instance, could be further optimized
    1661             : };
    1662             : 
    1663             : #endif /*GPAC_DISABLE_CRYPTO*/
    1664             : 
    1665        2877 : const GF_FilterRegister *cenc_decrypt_register(GF_FilterSession *session)
    1666             : {
    1667             : #ifndef GPAC_DISABLE_CRYPTO
    1668        2877 :         return &CENCDecRegister;
    1669             : #else
    1670             :         return NULL;
    1671             : #endif
    1672             : }

Generated by: LCOV version 1.13