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 : }
|