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 encrypt module
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 : #include <gpac/xml.h>
33 : #include <gpac/internal/isomedia_dev.h>
34 :
35 : #include <gpac/internal/media_dev.h>
36 :
37 : #ifndef GPAC_DISABLE_CRYPTO
38 :
39 :
40 : enum
41 : {
42 : ISMAEA_STATE_ERROR,
43 : ISMAEA_STATE_SETUP,
44 : ISMAEA_STATE_PLAY,
45 : };
46 :
47 :
48 : typedef enum {
49 : CENC_FULL_SAMPLE,
50 :
51 : /*below types may have several ranges (clear/encrypted) per sample*/
52 : CENC_AVC, /*AVC, nalu-based*/
53 : CENC_HEVC, /*HEVC, nalu-based*/
54 : CENC_AV1, /*AV1, OBU-based*/
55 : CENC_VPX, /*VPX, custom, see https://www.webmproject.org/vp9/mp4/ */
56 : } CENCCodecMode;
57 :
58 : typedef struct
59 : {
60 : GF_Crypt *crypt;
61 : char IV[16];
62 : bin128 key;
63 : u32 IV_size;
64 : } CENC_MKey;
65 :
66 : typedef struct
67 : {
68 : Bool passthrough;
69 :
70 : GF_CryptInfo *cinfo;
71 :
72 : GF_FilterPid *ipid;
73 : GF_FilterPid *opid;
74 : GF_TrackCryptInfo *tci;
75 :
76 : //active keys (for multikey support)
77 : u32 nb_keys;
78 : CENC_MKey *keys;
79 : Bool multi_key;
80 : u32 codec_id;
81 :
82 : u32 nb_pck;
83 :
84 : //ISMA/OMA var
85 : u32 nalu_size_length;
86 : u32 dsi_crc;
87 : Bool isma_oma;
88 : u64 BSO;
89 : u64 range_end;
90 : Bool prev_pck_encryped;
91 : u32 KI_length;
92 : u32 isma_IV_size;
93 : Bool has_crypted_pck;
94 :
95 : Bool is_adobe;
96 :
97 : CENCCodecMode cenc_codec;
98 :
99 : u32 bytes_in_nal_hdr;
100 : Bool use_subsamples;
101 : Bool cenc_init;
102 : u32 nb_pck_encrypted, kidx;
103 :
104 : //true if using AES-CTR mode, false if using AES-CBC mode
105 : Bool ctr_mode;
106 :
107 : Bool rap_roll;
108 :
109 : #ifndef GPAC_DISABLE_AV_PARSERS
110 : AVCState avc;
111 : #ifndef GPAC_DISABLE_HEVC
112 : HEVCState hevc;
113 : #endif
114 : AV1State av1;
115 : #endif
116 : Bool slice_header_clear;
117 :
118 : GF_PropUIntList mkey_indices;
119 : } GF_CENCStream;
120 :
121 : typedef struct
122 : {
123 : //options
124 : const char *cfile;
125 : Bool allc;
126 :
127 : //internal
128 : GF_CryptInfo *cinfo;
129 :
130 : GF_List *streams;
131 : GF_BitStream *bs_w, *bs_r;
132 : } GF_CENCEncCtx;
133 :
134 :
135 6 : static GF_Err isma_enc_configure(GF_CENCEncCtx *ctx, GF_CENCStream *cstr, Bool is_isma, const char *scheme_uri, const char *kms_uri)
136 : {
137 : GF_Err e;
138 : bin128 IV;
139 : const GF_PropertyValue *p;
140 6 : p = gf_filter_pid_get_property(cstr->ipid, GF_PROP_PID_DECODER_CONFIG);
141 6 : if (!p) p = gf_filter_pid_get_property(cstr->ipid, GF_PROP_PID_DECODER_CONFIG_ENHANCEMENT);
142 :
143 6 : switch (cstr->codec_id) {
144 1 : case GF_CODECID_AVC:
145 : case GF_CODECID_SVC:
146 : case GF_CODECID_MVC:
147 1 : if (p) {
148 1 : GF_AVCConfig *avcc = gf_odf_avc_cfg_read(p->value.data.ptr, p->value.data.size);
149 1 : cstr->nalu_size_length = avcc ? avcc->nal_unit_size : 0;
150 1 : if (avcc) gf_odf_avc_cfg_del(avcc);
151 : }
152 1 : if (!cstr->nalu_size_length) {
153 0 : cstr->nalu_size_length = 4;
154 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_MEDIA, ("[ISMACrypt] Missing NALU length size, assuming 4\n") );
155 : }
156 : break;
157 1 : case GF_CODECID_HEVC:
158 : case GF_CODECID_LHVC:
159 1 : if (p) {
160 1 : GF_HEVCConfig *hvcc = gf_odf_hevc_cfg_read(p->value.data.ptr, p->value.data.size, (cstr->codec_id==GF_CODECID_LHVC) ? GF_TRUE : GF_FALSE);
161 1 : cstr->nalu_size_length = hvcc ? hvcc->nal_unit_size : 0;
162 1 : if (hvcc) gf_odf_hevc_cfg_del(hvcc);
163 : }
164 1 : if (!cstr->nalu_size_length) {
165 0 : cstr->nalu_size_length = 4;
166 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_MEDIA, ("[ISMACrypt] Missing NALU length size, assuming 4\n") );
167 : }
168 : break;
169 : }
170 :
171 6 : if (!scheme_uri || !strlen(scheme_uri)) scheme_uri = "urn:gpac:isma:encryption_scheme";
172 :
173 6 : if (cstr->tci && ((cstr->tci->sel_enc_type==GF_CRYPT_SELENC_RAND) || (cstr->tci->sel_enc_type==GF_CRYPT_SELENC_RAND_RANGE)) ) {
174 0 : gf_rand_init(GF_TRUE);
175 : }
176 :
177 6 : cstr->isma_IV_size = 0;
178 6 : if (!is_isma) {
179 : /*128 bit IV in OMA*/
180 0 : cstr->isma_IV_size = 16;
181 : } else {
182 6 : p = gf_filter_pid_get_property(cstr->ipid, GF_PROP_PID_ISMA_IV_LENGTH);
183 6 : if (p) {
184 0 : cstr->isma_IV_size = p->value.uint;
185 : } else {
186 6 : p = gf_filter_pid_get_property(cstr->ipid, GF_PROP_PID_MEDIA_DATA_SIZE);
187 6 : if (p) {
188 6 : u64 BSO = p->value.longuint;
189 :
190 6 : if (BSO<0xFFFF) cstr->isma_IV_size = 2;
191 2 : else if (BSO<0xFFFFFFFF) cstr->isma_IV_size = 4;
192 0 : else cstr->isma_IV_size = 8;
193 : }
194 : }
195 6 : if (!cstr->isma_IV_size || (cstr->isma_IV_size > 8)) cstr->isma_IV_size = 8;
196 : }
197 :
198 6 : if (!cstr->tci || !cstr->tci->nb_keys) {
199 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[ISMACrypt] No keys specified for ISMA\n"));
200 : return GF_BAD_PARAM;
201 : }
202 :
203 : /*init crypto*/
204 : memset(IV, 0, sizeof(char)*16);
205 6 : memcpy(IV, cstr->tci->keys[0].IV, sizeof(char)*8);
206 6 : if (cstr->keys[0].crypt) gf_crypt_close(cstr->keys[0].crypt);
207 6 : cstr->keys[0].crypt = gf_crypt_open(GF_AES_128, GF_CTR);
208 6 : if (!cstr->keys[0].crypt) {
209 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[ISMACrypt] Cannot open AES-128 CTR\n"));
210 : return GF_IO_ERR;
211 : }
212 :
213 6 : e = gf_crypt_init(cstr->keys[0].crypt, cstr->tci->keys[0].key, IV);
214 6 : if (e) {
215 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[ISMACrypt] Cannot initialize AES-128 CTR (%s)\n", gf_error_to_string(e)) );
216 : return GF_IO_ERR;
217 : }
218 :
219 6 : GF_LOG(GF_LOG_INFO, GF_LOG_AUTHOR, ("[ISMACrypt] Encrypting stream %s - KMS: %s%s\n", gf_filter_pid_get_name(cstr->ipid), cstr->tci->KMS_URI, cstr->tci->sel_enc_type ? " - Selective Encryption" : ""));
220 :
221 6 : if (!stricmp(kms_uri, "self")) {
222 : char Data[100], d64[100];
223 : u32 size_b64;
224 6 : memcpy(Data, cstr->tci->keys[0].key, sizeof(char)*16);
225 : memcpy(Data+16, cstr->tci->keys[0].IV, sizeof(char)*8);
226 6 : size_b64 = gf_base64_encode(Data, 24, d64, 100);
227 6 : d64[size_b64] = 0;
228 6 : cstr->tci->KMS_URI = gf_realloc(cstr->tci->KMS_URI, size_b64+6);
229 6 : strcpy(cstr->tci->KMS_URI, "(key)");
230 6 : strcat(cstr->tci->KMS_URI, d64);
231 6 : kms_uri = cstr->tci->KMS_URI;
232 : }
233 :
234 : /*create ISMA protection*/
235 6 : gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_PROTECTION_SCHEME_VERSION, &PROP_UINT(1) );
236 6 : gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_PROTECTION_KMS_URI, kms_uri ? &PROP_STRING(kms_uri) : NULL);
237 6 : gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_ISMA_SELECTIVE_ENC, &PROP_BOOL( (cstr->tci->sel_enc_type!=0) ? GF_TRUE : GF_FALSE) );
238 6 : gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_ISMA_IV_LENGTH, &PROP_UINT(cstr->isma_IV_size) );
239 :
240 6 : if (is_isma) {
241 6 : gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_PROTECTION_SCHEME_URI, scheme_uri ? &PROP_STRING(scheme_uri) : NULL );
242 : } else {
243 0 : if ((cstr->tci->sel_enc_type==GF_CRYPT_SELENC_PREVIEW) && cstr->tci->sel_enc_range) {
244 : char szSTR[100];
245 : u32 len;
246 : char *szPreview;
247 :
248 : sprintf(szSTR, "PreviewRange:%d", cstr->tci->sel_enc_range);
249 0 : len = (u32) strlen(szSTR) + ( cstr->tci->TextualHeaders ? (u32) strlen(cstr->tci->TextualHeaders) : 0 ) + 1;
250 0 : szPreview = gf_malloc(sizeof(char) * len);
251 0 : strcpy(szPreview, cstr->tci->TextualHeaders ? cstr->tci->TextualHeaders : "");
252 : strcat(szPreview, szSTR);
253 :
254 0 : gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_OMA_TXT_HDR, &PROP_STRING_NO_COPY(szPreview));
255 : } else {
256 0 : gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_OMA_TXT_HDR, cstr->tci->TextualHeaders ? &PROP_STRING(cstr->tci->TextualHeaders) : NULL);
257 : }
258 :
259 0 : gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_OMA_CID, scheme_uri ? &PROP_STRING(scheme_uri) : NULL );
260 :
261 0 : gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_OMA_CRYPT_TYPE, &PROP_UINT(cstr->tci->encryption));
262 0 : gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_OMA_CLEAR_LEN, &PROP_LONGUINT(cstr->tci->sel_enc_range) );
263 0 : gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_ISMA_KI_LENGTH, &PROP_UINT(0) );
264 : }
265 :
266 6 : cstr->range_end = 0;
267 6 : if (cstr->tci->sel_enc_type==GF_CRYPT_SELENC_PREVIEW) {
268 0 : p = gf_filter_pid_get_property(cstr->ipid, GF_PROP_PID_TIMESCALE);
269 0 : if (p)
270 0 : cstr->range_end = p->value.uint *cstr->tci->sel_enc_range;
271 : }
272 :
273 6 : cstr->isma_oma = GF_TRUE;
274 6 : cstr->prev_pck_encryped = GF_TRUE;
275 6 : cstr->has_crypted_pck = GF_FALSE;
276 :
277 : //we drop IPMPX support for now
278 : #if GPAC_DEPRECTAED
279 : /*format as IPMP(X) - note that the ISMACryp spec is broken since it always uses IPMPPointers to a
280 : single desc which would assume the same protection (eg key & salt) for all streams using it...*/
281 : if (!tci->ipmp_type) return GF_OK;
282 :
283 : ipmpdp = (GF_IPMPPtr*)gf_odf_desc_new(GF_ODF_IPMP_PTR_TAG);
284 : if (!tci->ipmp_desc_id) tci->ipmp_desc_id = track;
285 : if (tci->ipmp_type==2) {
286 : ipmpdp->IPMP_DescriptorID = 0xFF;
287 : ipmpdp->IPMP_DescriptorIDEx = tci->ipmp_desc_id;
288 : } else {
289 : ipmpdp->IPMP_DescriptorID = tci->ipmp_desc_id;
290 : }
291 : gf_isom_add_desc_to_description(mp4, track, 1, (GF_Descriptor *)ipmpdp);
292 : gf_odf_desc_del((GF_Descriptor*)ipmpdp);
293 :
294 : ipmpdU = (GF_IPMPUpdate*)gf_odf_com_new(GF_ODF_IPMP_UPDATE_TAG);
295 : /*format IPMPD*/
296 : ipmpd = (GF_IPMP_Descriptor*)gf_odf_desc_new(GF_ODF_IPMP_TAG);
297 : if (tci->ipmp_type==2) {
298 : #ifndef GPAC_MINIMAL_ODF
299 : ipmpd->IPMP_DescriptorID = 0xFF;
300 : ipmpd->IPMP_DescriptorIDEx = tci->ipmp_desc_id;
301 : ipmpd->IPMPS_Type = 0xFFFF;
302 : ipmpd->IPMP_ToolID[14] = 0x49;
303 : ipmpd->IPMP_ToolID[15] = 0x53;
304 : ipmpd->control_point = 1;
305 : ipmpd->cp_sequence_code = 0x80;
306 : /*format IPMPXData*/
307 : ismac = (GF_IPMPX_ISMACryp *) gf_ipmpx_data_new(GF_IPMPX_ISMACRYP_TAG);
308 : ismac->cryptoSuite = 1; /*default ISMA AESCTR128*/
309 : ismac->IV_length = IV_size;
310 : ismac->key_indicator_length = 0;
311 : ismac->use_selective_encryption = (tci->sel_enc_type!=0)? 1 : 0;
312 : gf_list_add(ipmpd->ipmpx_data, ismac);
313 : #endif
314 : } else {
315 : ipmpd->IPMP_DescriptorID = tci->ipmp_desc_id;
316 : }
317 : gf_list_add(ipmpdU->IPMPDescList, ipmpd);
318 :
319 : for (i=0; i<gf_isom_get_track_count(mp4); i++) {
320 : GF_ODCodec *cod;
321 : if (gf_isom_get_media_type(mp4, i+1) != GF_ISOM_MEDIA_OD) continue;
322 :
323 : /*add com*/
324 : samp = gf_isom_get_sample(mp4, i+1, 1, &di);
325 : cod = gf_odf_codec_new();
326 : gf_odf_codec_set_au(cod, samp->data, samp->dataLength);
327 : gf_odf_codec_decode(cod);
328 : gf_odf_codec_add_com(cod, (GF_ODCom *) ipmpdU);
329 : gf_free(samp->data);
330 : samp->data = NULL;
331 : samp->dataLength = 0;
332 : gf_odf_codec_encode(cod, 1);
333 : gf_odf_codec_get_au(cod, &samp->data, &samp->dataLength);
334 : ipmpdU = NULL;
335 : gf_odf_codec_del(cod);
336 : gf_isom_update_sample(mp4, i+1, 1, samp, 1);
337 : gf_isom_sample_del(&samp);
338 :
339 : if (tci->ipmp_type==2) {
340 : GF_IPMP_ToolList*ipmptl = (GF_IPMP_ToolList*)gf_odf_desc_new(GF_ODF_IPMP_TL_TAG);
341 : GF_IPMP_Tool *ipmpt = (GF_IPMP_Tool*)gf_odf_desc_new(GF_ODF_IPMP_TOOL_TAG);
342 : gf_list_add(ipmptl->ipmp_tools, ipmpt);
343 : ipmpt->IPMP_ToolID[14] = 0x49;
344 : ipmpt->IPMP_ToolID[15] = 0x53;
345 : gf_isom_add_desc_to_root_od(mp4, (GF_Descriptor *)ipmptl);
346 : gf_odf_desc_del((GF_Descriptor *)ipmptl);
347 : }
348 : break;
349 : }
350 : #endif
351 : return GF_OK;
352 : }
353 :
354 5 : static GF_Err adobe_enc_configure(GF_CENCEncCtx *ctx, GF_CENCStream *cstr)
355 : {
356 5 : if (cstr->keys[0].crypt) gf_crypt_close(cstr->keys[0].crypt);
357 5 : cstr->keys[0].crypt = gf_crypt_open(GF_AES_128, GF_CBC);
358 5 : if (!cstr->keys[0].crypt) {
359 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[Adobe] Cannot open AES-128 CBC \n"));
360 : return GF_IO_ERR;
361 : }
362 :
363 : /*Adobe's protection scheme does not support selective key*/
364 5 : memcpy(cstr->keys[0].key, cstr->tci->keys[0].key, 16);
365 :
366 5 : if (cstr->tci->metadata)
367 5 : gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_ADOBE_CRYPT_META, &PROP_DATA(cstr->tci->metadata, (u32) strlen(cstr->tci->metadata) ) );
368 :
369 5 : cstr->is_adobe = GF_TRUE;
370 :
371 : return GF_OK;
372 : }
373 :
374 155 : static GF_Err cenc_parse_pssh(GF_CENCEncCtx *ctx, GF_CENCStream *cstr, const char *cfile_name)
375 : {
376 : GF_DOMParser *parser;
377 : GF_XMLNode *root, *node;
378 : u32 i;
379 : GF_Err e;
380 : u32 nb_pssh=0;
381 : GF_BitStream *pssh_bs=NULL;
382 :
383 155 : parser = gf_xml_dom_new();
384 155 : e = gf_xml_dom_parse(parser, cfile_name, NULL, NULL);
385 155 : if (e) {
386 0 : gf_xml_dom_del(parser);
387 : return e;
388 : }
389 155 : root = gf_xml_dom_get_root(parser);
390 155 : if (!root) {
391 0 : gf_xml_dom_del(parser);
392 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC/ISMA] Cannot open or validate xml file %s\n", ctx->cfile));
393 : return GF_NOT_SUPPORTED;
394 : }
395 155 : pssh_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
396 155 : gf_bs_write_u32(pssh_bs, 0);
397 :
398 155 : i=0;
399 1223 : while ((node = (GF_XMLNode *) gf_list_enum(root->content, &i))) {
400 : Bool is_pssh;
401 : u32 version, cypherMode, specInfoSize, len, KID_count, j;
402 : bin128 cypherKey, cypherIV, systemID;
403 : GF_XMLAttribute *att;
404 : u8 *data, *specInfo;
405 : GF_BitStream *bs;
406 : bin128 *KIDs;
407 : s32 cypherOffset = -1;
408 : Bool has_key = GF_FALSE, has_IV = GF_FALSE;
409 :
410 1935 : if (strcmp(node->name, "DRMInfo")) continue;
411 :
412 201 : j = 0;
413 : is_pssh = GF_FALSE;
414 : version = cypherMode = 0;
415 201 : data = specInfo = NULL;
416 : bs = NULL;
417 :
418 1068 : while ( (att = (GF_XMLAttribute *)gf_list_enum(node->attributes, &j))) {
419 867 : if (!strcmp(att->name, "type")) {
420 201 : if (!strcmp(att->value, "pssh"))
421 : is_pssh = GF_TRUE;
422 666 : } else if (!strcmp(att->name, "version")) {
423 402 : version = atoi(att->value);
424 465 : } else if (!strcmp(att->name, "cypherMode")) {
425 : /*cypher-mode: 0: ctr (default mode) - 1: cbc - 2: clear*/
426 0 : if (!strcmp(att->value, "yes"))
427 : cypherMode = 0;
428 0 : else if (!strcmp(att->value, "no"))
429 : cypherMode = 1;
430 465 : } else if (!strcmp(att->name, "cypherKey")) {
431 155 : e = gf_bin128_parse(att->value, cypherKey);
432 155 : if (e != GF_OK) {
433 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Cannnot parse cypherKey\n"));
434 0 : return e;
435 : }
436 : has_key = GF_TRUE;
437 310 : } else if (!strcmp(att->name, "cypherIV")) {
438 155 : e = gf_bin128_parse(att->value, cypherIV);
439 155 : if (e != GF_OK) {
440 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Cannnot parse cypherIV\n"));
441 : return e;
442 : }
443 : has_IV = GF_TRUE;
444 155 : } else if (!strcmp(att->name, "cypherOffset")) {
445 155 : cypherOffset = atoi(att->value);
446 : }
447 : }
448 :
449 201 : if (!is_pssh) {
450 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[CENC/ISMA] Not a Protection System Specific Header Box - skipping\n"));
451 0 : continue;
452 : }
453 :
454 201 : e = gf_xml_parse_bit_sequence(node, cfile_name, &specInfo, &specInfoSize);
455 201 : if (e) {
456 0 : if (specInfo) gf_free(specInfo);
457 0 : gf_xml_dom_del(parser);
458 : return e;
459 : }
460 :
461 201 : bs = gf_bs_new(specInfo, specInfoSize, GF_BITSTREAM_READ);
462 201 : gf_bs_read_data(bs, (char *)systemID, 16);
463 201 : if (version) {
464 155 : KID_count = gf_bs_read_u32(bs);
465 155 : KIDs = (bin128 *)gf_malloc(KID_count*sizeof(bin128));
466 342 : for (j = 0; j < KID_count; j++) {
467 187 : gf_bs_read_data(bs, (char *)KIDs[j], 16);
468 : }
469 : }
470 : else {
471 : KID_count = 0;
472 : KIDs = NULL;
473 : }
474 201 : if (specInfoSize < 16 + (version ? 4 + 16*KID_count : 0)) {
475 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[CENC/ISMA] Invalid PSSH blob in version %d: size %d key count %d - ignoring PSSH\n", version, specInfoSize, KID_count));
476 0 : continue;
477 : }
478 201 : len = specInfoSize - 16 - (version ? 4 + 16*KID_count : 0);
479 201 : data = (char *)gf_malloc(len*sizeof(char));
480 201 : gf_bs_read_data(bs, data, len);
481 :
482 201 : if (has_key && has_IV && (cypherOffset >= 0) && (cypherMode != 1)) {
483 155 : GF_Crypt *gc = gf_crypt_open(GF_AES_128, GF_CTR);
484 155 : if (!gc) {
485 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC/ISMA] Cannot open AES-128 CTR\n"));
486 : return GF_IO_ERR;
487 : }
488 155 : e = gf_crypt_init(gc, cypherKey, cypherIV);
489 155 : gf_crypt_encrypt(gc, data+cypherOffset, len-cypherOffset);
490 155 : gf_crypt_close(gc);
491 : }
492 201 : if (!e) {
493 201 : nb_pssh++;
494 201 : gf_bs_write_data(pssh_bs, systemID, 16);
495 201 : gf_bs_write_u32(pssh_bs, version);
496 201 : gf_bs_write_u32(pssh_bs, KID_count);
497 388 : for (j=0; j<KID_count; j++) {
498 187 : gf_bs_write_data(pssh_bs, KIDs[j], 16);
499 : }
500 201 : gf_bs_write_u32(pssh_bs, len);
501 201 : gf_bs_write_data(pssh_bs, data, len);
502 : }
503 :
504 201 : if (specInfo) gf_free(specInfo);
505 201 : if (data) gf_free(data);
506 201 : if (KIDs) gf_free(KIDs);
507 201 : if (bs) gf_bs_del(bs);
508 201 : if (e) break;
509 : }
510 :
511 155 : gf_xml_dom_del(parser);
512 :
513 155 : if (nb_pssh) {
514 155 : u8 *pssh=NULL;
515 155 : u32 pssh_size=0;
516 155 : u32 pos = (u32) gf_bs_get_position(pssh_bs);
517 155 : gf_bs_seek(pssh_bs, 0);
518 155 : gf_bs_write_u32(pssh_bs, nb_pssh);
519 155 : gf_bs_seek(pssh_bs, pos);
520 155 : gf_bs_get_content(pssh_bs, &pssh, &pssh_size);
521 155 : gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_CENC_PSSH, &PROP_DATA_NO_COPY(pssh, pssh_size));
522 : }
523 155 : gf_bs_del(pssh_bs);
524 :
525 : return e;
526 : }
527 :
528 :
529 155 : static GF_Err cenc_enc_configure(GF_CENCEncCtx *ctx, GF_CENCStream *cstr, const char *cfile_name)
530 : {
531 : #if !defined(GPAC_DISABLE_AV_PARSERS)
532 : u32 i;
533 : #endif
534 : u32 dsi_crc=0;
535 : Bool is_reinit=GF_FALSE;
536 : GF_AVCConfig *avccfg;
537 : GF_HEVCConfig *hevccfg;
538 : const GF_PropertyValue *p;
539 :
540 155 : p = gf_filter_pid_get_property(cstr->ipid, GF_PROP_PID_DECODER_CONFIG);
541 155 : if (!p) p = gf_filter_pid_get_property(cstr->ipid, GF_PROP_PID_DECODER_CONFIG_ENHANCEMENT);
542 :
543 155 : if (p) {
544 155 : dsi_crc = gf_crc_32(p->value.data.ptr, p->value.data.size);
545 : }
546 155 : if (dsi_crc != cstr->dsi_crc)
547 : is_reinit = GF_TRUE;
548 18 : else if (!dsi_crc && !cstr->keys[0].crypt)
549 : is_reinit = GF_TRUE;
550 :
551 137 : cstr->dsi_crc = dsi_crc;
552 :
553 : if (is_reinit) {
554 : const GF_PropertyValue *p2;
555 137 : cstr->nalu_size_length = 0;
556 137 : cstr->cenc_codec = CENC_FULL_SAMPLE;
557 137 : switch (cstr->codec_id) {
558 64 : case GF_CODECID_AVC:
559 : case GF_CODECID_SVC:
560 : case GF_CODECID_MVC:
561 64 : if (!p)
562 : return GF_OK;
563 :
564 64 : avccfg = gf_odf_avc_cfg_read(p->value.data.ptr, p->value.data.size);
565 64 : if (avccfg) cstr->nalu_size_length = avccfg->nal_unit_size;
566 :
567 64 : cstr->cenc_codec = CENC_AVC;
568 :
569 64 : p2 = gf_filter_pid_get_property(cstr->ipid, GF_PROP_PID_ISOM_SUBTYPE);
570 64 : if (p2 && (p2->value.uint==GF_ISOM_BOX_TYPE_AVC1)) {
571 52 : if (!cstr->tci->allow_encrypted_slice_header) {
572 49 : cstr->slice_header_clear = GF_TRUE;
573 3 : } else if (cstr->tci->scheme_type==GF_CRYPT_TYPE_CBCS) {
574 0 : cstr->slice_header_clear = GF_TRUE;
575 : }
576 : } else {
577 12 : cstr->slice_header_clear = GF_TRUE;
578 : }
579 : #ifndef GPAC_DISABLE_AV_PARSERS
580 64 : if (avccfg) {
581 64 : for (i=0; i<gf_list_count(avccfg->sequenceParameterSets); i++) {
582 64 : GF_NALUFFParam *slc = gf_list_get(avccfg->sequenceParameterSets, i);
583 64 : gf_avc_read_sps(slc->data, slc->size, &cstr->avc, 0, NULL);
584 : }
585 64 : for (i=0; i<gf_list_count(avccfg->pictureParameterSets); i++) {
586 64 : GF_NALUFFParam *slc = gf_list_get(avccfg->pictureParameterSets, i);
587 64 : gf_avc_read_pps(slc->data, slc->size, &cstr->avc);
588 : }
589 :
590 64 : gf_odf_avc_cfg_del(avccfg);
591 : }
592 : #else
593 : if (avccfg) gf_odf_avc_cfg_del(avccfg);
594 : #endif
595 64 : cstr->bytes_in_nal_hdr = 1;
596 :
597 64 : if (!cstr->slice_header_clear && cstr->tci->clear_bytes)
598 1 : cstr->bytes_in_nal_hdr = cstr->tci->clear_bytes;
599 :
600 64 : if (!cstr->nalu_size_length) {
601 0 : cstr->nalu_size_length = 4;
602 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_MEDIA, ("[CENCCrypt] Missing NALU length size, assuming 4\n") );
603 : }
604 : break;
605 17 : case GF_CODECID_HEVC:
606 : case GF_CODECID_LHVC:
607 17 : if (!p)
608 : return GF_OK;
609 :
610 17 : hevccfg = gf_odf_hevc_cfg_read(p->value.data.ptr, p->value.data.size, (cstr->codec_id==GF_CODECID_LHVC) ? GF_TRUE : GF_FALSE);
611 17 : if (hevccfg) cstr->nalu_size_length = hevccfg->nal_unit_size;
612 :
613 : #if !defined(GPAC_DISABLE_AV_PARSERS) && !defined(GPAC_DISABLE_HEVC)
614 17 : gf_hevc_parse_ps(hevccfg, &cstr->hevc, GF_HEVC_NALU_VID_PARAM);
615 17 : gf_hevc_parse_ps(hevccfg, &cstr->hevc, GF_HEVC_NALU_SEQ_PARAM);
616 17 : gf_hevc_parse_ps(hevccfg, &cstr->hevc, GF_HEVC_NALU_PIC_PARAM);
617 : #endif
618 :
619 : //mandatory for HEVC
620 17 : cstr->slice_header_clear = GF_TRUE;
621 :
622 17 : cstr->cenc_codec = CENC_HEVC;
623 :
624 17 : if (hevccfg) gf_odf_hevc_cfg_del(hevccfg);
625 17 : cstr->bytes_in_nal_hdr = 2;
626 :
627 17 : if (!cstr->nalu_size_length) {
628 0 : cstr->nalu_size_length = 4;
629 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_MEDIA, ("[CENCCrypt] Missing NALU length size, assuming 4\n") );
630 : }
631 : break;
632 26 : case GF_CODECID_AV1:
633 26 : if (!p)
634 : return GF_OK;
635 :
636 : #if !defined(GPAC_DISABLE_AV_PARSERS) && !defined(GPAC_DISABLE_AV1)
637 26 : cstr->av1.config = gf_odf_av1_cfg_read(p->value.data.ptr, p->value.data.size);
638 26 : cstr->cenc_codec = CENC_AV1;
639 26 : cstr->bytes_in_nal_hdr = 2;
640 : #endif
641 : //mandatory for AV1
642 26 : cstr->slice_header_clear = GF_TRUE;
643 26 : break;
644 8 : case GF_CODECID_VP8:
645 : case GF_CODECID_VP9:
646 8 : if (p) {
647 8 : cstr->cenc_codec = CENC_VPX;
648 8 : cstr->bytes_in_nal_hdr = 2;
649 : }
650 : break;
651 : }
652 : }
653 :
654 155 : if (((cstr->tci->scheme_type == GF_CRYPT_TYPE_CENS) || (cstr->tci->scheme_type == GF_CRYPT_TYPE_CBCS) ) && (cstr->cenc_codec>CENC_FULL_SAMPLE) && (cstr->cenc_codec<=CENC_AV1)
655 : ) {
656 28 : if (!cstr->tci->crypt_byte_block || !cstr->tci->skip_byte_block) {
657 16 : if (cstr->tci->crypt_byte_block || cstr->tci->skip_byte_block) {
658 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[CENC] Using pattern mode, crypt_byte_block and skip_byte_block shall be 0 only for track other than video, using 1 crypt + 9 skip\n"));
659 : }
660 16 : cstr->tci->crypt_byte_block = 1;
661 16 : cstr->tci->skip_byte_block = 9;
662 : }
663 : }
664 :
665 155 : if ( (cstr->cenc_codec==CENC_VPX) && (cstr->tci->scheme_type != GF_CRYPT_TYPE_CENC) ) {
666 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Encryption mode %s is not supported with VP8/VP9, only cenc is\n", gf_4cc_to_str(cstr->tci->scheme_type) ));
667 : return GF_NOT_SUPPORTED;
668 : }
669 :
670 :
671 155 : cstr->use_subsamples = GF_FALSE;
672 155 : if (cstr->cenc_codec != CENC_FULL_SAMPLE) cstr->use_subsamples = GF_TRUE;
673 : //CBCS mode with skip byte block may be used for any track, in which case we need subsamples
674 22 : else if (cstr->tci->scheme_type == GF_CRYPT_TYPE_CBCS) {
675 2 : if (cstr->tci->skip_byte_block) {
676 0 : cstr->use_subsamples = GF_TRUE;
677 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("\n[CENC] Using cbcs pattern mode on non NAL video track, this may not be supported by most devices; consider setting skip_byte_block to 0\n\n"));
678 : //cbcs allows bytes of clear data
679 0 : cstr->bytes_in_nal_hdr = cstr->tci->clear_bytes;
680 : }
681 : //This is not clear in the spec, setting skip and crypt to 0 means no pattern, in which case tenc version shall be 0
682 : //but cbcs asks for 1 - needs further clarification
683 : #if 0
684 : //setup defaults
685 : else if (!cstr->crypt_byte_block) {
686 : cstr->tci->crypt_byte_block = 1;
687 : }
688 : #else
689 : else {
690 2 : cstr->tci->crypt_byte_block = 0;
691 : }
692 : #endif
693 : }
694 20 : else if (cstr->tci->scheme_type == GF_CRYPT_TYPE_CENS) {
695 2 : if (cstr->tci->skip_byte_block) {
696 2 : GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[CENC] Using cens pattern mode on non NAL video track not allowed, forcing skip_byte_block to 0\n"));
697 2 : cstr->tci->skip_byte_block = 0;
698 2 : if (!cstr->tci->crypt_byte_block) {
699 0 : cstr->tci->crypt_byte_block = 1;
700 : }
701 : }
702 : }
703 :
704 : //setup crypto context, disabling multikey if the stream doesn't use subsample
705 155 : if (!cstr->keys) {
706 3 : if (!cstr->use_subsamples)
707 0 : cstr->multi_key = GF_FALSE;
708 :
709 3 : if (cstr->multi_key) {
710 3 : cstr->nb_keys = cstr->tci->nb_keys;
711 : } else {
712 0 : cstr->nb_keys = 1;
713 : }
714 3 : cstr->keys = gf_malloc(sizeof(CENC_MKey) * cstr->nb_keys);
715 3 : if (!cstr->keys) return GF_OUT_OF_MEM;
716 3 : memset(cstr->keys, 0, sizeof(CENC_MKey) * cstr->nb_keys);
717 : }
718 : //init rand
719 310 : if ((cstr->tci->sel_enc_type==GF_CRYPT_SELENC_RAND)
720 155 : || (cstr->tci->sel_enc_type==GF_CRYPT_SELENC_RAND_RANGE)
721 155 : || cstr->tci->subs_rand
722 : ) {
723 0 : gf_rand_init(GF_TRUE);
724 : }
725 :
726 : //configure roll rap
727 155 : if (cstr->tci->roll_rap) {
728 0 : cstr->rap_roll = GF_TRUE;
729 : //if no subsample, only use key roll "rap" if codec has sync point
730 0 : if (!cstr->use_subsamples) {
731 0 : p = gf_filter_pid_get_property(cstr->ipid, GF_PROP_PID_HAS_SYNC);
732 0 : if (p && p->value.uint) {
733 0 : cstr->rap_roll = GF_TRUE;
734 : } else {
735 0 : switch (cstr->codec_id) {
736 0 : case GF_CODECID_USAC:
737 0 : cstr->rap_roll = GF_TRUE;
738 0 : break;
739 : }
740 : }
741 : } else {
742 : cstr->rap_roll = GF_TRUE;
743 : }
744 : }
745 155 : if (cstr->multi_key && !cstr->mkey_indices.nb_items && cstr->tci->mkey_subs) {
746 1 : GF_PropertyValue pval = gf_props_parse_value(GF_PROP_UINT_LIST, "subs", cstr->tci->mkey_subs, NULL, ',');
747 1 : cstr->mkey_indices = pval.value.uint_list;
748 : }
749 :
750 155 : if (is_reinit) {
751 : u32 nb_keys;
752 :
753 : /*select key*/
754 137 : if (!cstr->tci->keys) {
755 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] No key specified\n"));
756 : return GF_BAD_PARAM;
757 : }
758 :
759 137 : nb_keys = cstr->multi_key ? cstr->tci->nb_keys : 1;
760 277 : for (i=0; i<nb_keys; i++) {
761 :
762 140 : if (cstr->keys[i].crypt) gf_crypt_close(cstr->keys[i].crypt);
763 140 : if (cstr->ctr_mode) {
764 114 : cstr->keys[i].crypt = gf_crypt_open(GF_AES_128, GF_CTR);
765 : }
766 : else {
767 26 : cstr->keys[i].crypt = gf_crypt_open(GF_AES_128, GF_CBC);
768 : }
769 140 : if (!cstr->keys[i].crypt) {
770 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Cannot open AES-128 %s\n", cstr->ctr_mode ? "CTR" : "CBC"));
771 : return GF_IO_ERR;
772 : }
773 :
774 140 : if (nb_keys>1) {
775 6 : memcpy(cstr->keys[i].key, cstr->tci->keys[i].key, 16);
776 6 : cstr->kidx = 0;
777 : } else {
778 134 : if (cstr->tci->defaultKeyIdx && (cstr->tci->defaultKeyIdx < cstr->tci->nb_keys)) {
779 0 : cstr->kidx = cstr->tci->defaultKeyIdx;
780 : } else {
781 134 : cstr->kidx = 0;
782 : }
783 134 : memcpy(cstr->keys[0].key, cstr->tci->keys[cstr->kidx].key, 16);
784 : }
785 : }
786 :
787 137 : cstr->prev_pck_encryped = cstr->tci->IsEncrypted;
788 : }
789 :
790 : /*set CENC protection properties*/
791 :
792 155 : gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_PROTECTION_SCHEME_VERSION, &PROP_UINT(0x00010000) );
793 155 : gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_ENCRYPTED, &PROP_BOOL(cstr->tci->IsEncrypted ? GF_TRUE : GF_FALSE) );
794 :
795 : u8 *data;
796 : u32 size;
797 155 : GF_BitStream *bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
798 155 : if (cstr->multi_key) {
799 3 : gf_bs_write_u8(bs, 1);
800 3 : gf_bs_write_u16(bs, cstr->tci->nb_keys);
801 :
802 9 : for (i=0; i<cstr->tci->nb_keys; i++) {
803 6 : GF_CryptKeyInfo *ki = &cstr->tci->keys[i];
804 6 : gf_bs_write_u8(bs, ki->constant_IV_size ? 0 : ki->IV_size);
805 6 : gf_bs_write_data(bs, ki->KID, 16);
806 6 : if (ki->constant_IV_size) {
807 0 : gf_bs_write_u8(bs, ki->constant_IV_size);
808 0 : gf_bs_write_data(bs, ki->IV, ki->constant_IV_size);
809 : }
810 : }
811 : } else {
812 152 : GF_CryptKeyInfo *ki = &cstr->tci->keys[cstr->kidx];
813 152 : gf_bs_write_u8(bs, 0);
814 152 : gf_bs_write_u16(bs, 0);
815 152 : gf_bs_write_u8(bs, ki->constant_IV_size ? 0 : ki->IV_size);
816 152 : gf_bs_write_data(bs, ki->KID, 16);
817 152 : if (ki->constant_IV_size) {
818 9 : gf_bs_write_u8(bs, ki->constant_IV_size);
819 9 : gf_bs_write_data(bs, ki->IV, ki->constant_IV_size);
820 : }
821 : }
822 155 : gf_bs_get_content(bs, &data, &size);
823 155 : gf_bs_del(bs);
824 155 : gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_CENC_KEY_INFO, &PROP_DATA_NO_COPY(data, size) );
825 :
826 155 : if (!cstr->multi_key) {
827 152 : char *hls_info = cstr->tci->keys[0].hls_info;
828 152 : gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_HLS_KMS, hls_info ? &PROP_STRING(hls_info) : NULL);
829 : }
830 :
831 155 : if (cstr->tci->skip_byte_block || cstr->tci->crypt_byte_block) {
832 30 : gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_CENC_PATTERN, &PROP_FRAC_INT(cstr->tci->skip_byte_block, cstr->tci->crypt_byte_block ) );
833 : } else {
834 125 : gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_CENC_PATTERN, NULL);
835 : }
836 :
837 : //if constantIV and not using CENC subsample, no CENC auxiliary info
838 155 : if (!cstr->tci->keys[0].constant_IV_size || cstr->use_subsamples) {
839 154 : gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_CENC_STORE, &PROP_4CC(cstr->tci->sai_saved_box_type) );
840 : }
841 :
842 : //parse pssh even if reinit since we need to reassign pssh property
843 155 : return cenc_parse_pssh(ctx, cstr, cfile_name);
844 : }
845 :
846 149 : static void cenc_free_pid_context(GF_CENCStream *cstr)
847 : {
848 : u32 i;
849 300 : for (i=0; i<cstr->nb_keys; i++) {
850 151 : if (cstr->keys[i].crypt) gf_crypt_close(cstr->keys[i].crypt);
851 : }
852 149 : gf_free(cstr->keys);
853 149 : if (cstr->cinfo) gf_crypt_info_del(cstr->cinfo);
854 : #ifndef GPAC_DISABLE_AV_PARSERS
855 149 : if (cstr->av1.config) gf_odf_av1_cfg_del(cstr->av1.config);
856 : #endif
857 :
858 149 : if (cstr->mkey_indices.vals) gf_free(cstr->mkey_indices.vals);
859 149 : gf_free(cstr);
860 149 : }
861 :
862 167 : static GF_Err cenc_enc_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
863 : {
864 : const GF_PropertyValue *prop;
865 167 : GF_Err e = GF_OK;
866 : u32 scheme_type = 0;
867 : GF_TrackCryptInfo *tci = NULL;
868 : const char *scheme_uri = NULL;
869 : const char *kms_uri = NULL;
870 : GF_CryptInfo *cinfo = NULL;
871 : GF_CENCStream *cstr;
872 167 : GF_CENCEncCtx *ctx = (GF_CENCEncCtx *)gf_filter_get_udta(filter);
873 167 : const char *cfile_name = ctx->cfile;
874 : GF_TrackCryptInfo *tci_any = NULL;
875 : u32 i, count;
876 :
877 :
878 167 : if (is_remove) {
879 0 : cstr = gf_filter_pid_get_udta(pid);
880 0 : if (cstr) {
881 0 : gf_list_del_item(ctx->streams, cstr);
882 0 : if (cstr->opid)
883 0 : gf_filter_pid_remove(cstr->opid);
884 :
885 0 : cenc_free_pid_context(cstr);
886 : }
887 : return GF_OK;
888 : }
889 :
890 167 : if (! gf_filter_pid_check_caps(pid))
891 : return GF_NOT_SUPPORTED;
892 :
893 167 : prop = gf_filter_pid_get_property(pid, GF_PROP_PID_CRYPT_INFO);
894 167 : if (prop) {
895 0 : cinfo = gf_crypt_info_load(prop->value.string, &e);
896 0 : if (!cinfo) {
897 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[CENCrypt] failed to load crypt info file %s for pid %s\n", prop->value.string, gf_filter_pid_get_name(pid) ) );
898 0 : return e;
899 : }
900 0 : cfile_name = prop->value.string;
901 : }
902 167 : if (!cinfo) cinfo = ctx->cinfo;
903 :
904 :
905 167 : if (cinfo) {
906 167 : prop = gf_filter_pid_get_property(pid, GF_PROP_PID_ID);
907 167 : count = gf_list_count(cinfo->tcis);
908 168 : for (i=0; i<count; i++) {
909 167 : tci = gf_list_get(cinfo->tcis, i);
910 167 : if (prop && tci->trackID && (tci->trackID==prop->value.uint)) break;
911 1 : if (!tci_any && !tci->trackID) tci_any = tci;
912 1 : if ((cinfo != ctx->cinfo) && !tci_any) tci_any = tci;
913 : tci = NULL;
914 : }
915 167 : if (!tci) tci = tci_any;
916 0 : } else if (ctx->allc) {
917 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[CENCrypt] Missing DRM config file\n") );
918 : return GF_NOT_SUPPORTED;
919 : }
920 :
921 167 : if (!tci) {
922 1 : if (cinfo) {
923 1 : GF_LOG(GF_LOG_WARNING, GF_LOG_MEDIA, ("[CENCrypt] Missing track crypt info in DRM config file, PID will not be crypted\n") );
924 : }
925 : } else {
926 166 : scheme_type = tci->scheme_type;
927 :
928 166 : switch (scheme_type) {
929 : case GF_CRYPT_TYPE_ISMA:
930 : case GF_CRYPT_TYPE_OMA:
931 : case GF_CRYPT_TYPE_ADOBE:
932 : case GF_CRYPT_TYPE_CENC:
933 : case GF_CRYPT_TYPE_CBC1:
934 : case GF_CRYPT_TYPE_CENS:
935 : case GF_CRYPT_TYPE_CBCS:
936 : case GF_CRYPT_TYPE_PIFF:
937 : break;
938 0 : default:
939 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[CENCrypt] Unsupported scheme type %s\n", gf_4cc_to_str(scheme_type) ));
940 0 : if (cinfo != ctx->cinfo) gf_crypt_info_del(cinfo);
941 : return GF_NOT_SUPPORTED;
942 : }
943 : }
944 :
945 167 : cstr = gf_filter_pid_get_udta(pid);
946 167 : if (!cstr) {
947 149 : GF_SAFEALLOC(cstr, GF_CENCStream);
948 149 : if (!cstr) return GF_OUT_OF_MEM;
949 149 : cstr->ipid = pid;
950 149 : cstr->opid = gf_filter_pid_new(filter);
951 149 : cstr->tci = tci;
952 149 : gf_list_add(ctx->streams, cstr);
953 149 : gf_filter_pid_set_udta(pid, cstr);
954 : //we need full sample
955 149 : gf_filter_pid_set_framing_mode(pid, GF_TRUE);
956 : }
957 167 : if (cstr->cinfo) gf_crypt_info_del(cstr->cinfo);
958 167 : cstr->cinfo = (cinfo != ctx->cinfo) ? cinfo : NULL;
959 167 : cstr->tci = tci;
960 167 : cstr->passthrough = tci ? GF_FALSE : GF_TRUE;
961 :
962 : //copy properties at init or reconfig
963 167 : gf_filter_pid_copy_properties(cstr->opid, pid);
964 :
965 167 : prop = gf_filter_pid_get_property(pid, GF_PROP_PID_CODECID);
966 167 : if (prop) cstr->codec_id = prop->value.uint;
967 :
968 167 : if (cstr->tci) {
969 166 : gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_PROTECTION_SCHEME_TYPE, &PROP_4CC(scheme_type) );
970 :
971 :
972 166 : prop = gf_filter_pid_get_property(pid, GF_PROP_PID_STREAM_TYPE);
973 166 : if (prop) {
974 166 : switch (prop->value.uint) {
975 166 : case GF_STREAM_VISUAL:
976 : case GF_STREAM_AUDIO:
977 : case GF_STREAM_SCENE:
978 : case GF_STREAM_FONT:
979 : case GF_STREAM_TEXT:
980 166 : gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_ORIG_STREAM_TYPE, & PROP_UINT(prop->value.uint) );
981 166 : break;
982 0 : default:
983 0 : GF_LOG(GF_LOG_INFO, GF_LOG_AUTHOR, ("[CENCrypt] Stream type %s cannot be encrypted, using passthrough\n", gf_stream_type_name(prop->value.uint) ));
984 0 : cstr->passthrough = GF_TRUE;
985 0 : break;
986 : }
987 0 : }
988 166 : gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_CENC_STSD_MODE, &PROP_UINT(tci->force_clear_stsd_idx) );
989 : }
990 :
991 167 : if (cstr->passthrough) return GF_OK;
992 :
993 166 : gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_STREAM_TYPE, &PROP_UINT(GF_STREAM_ENCRYPTED) );
994 :
995 166 : scheme_uri = cstr->tci->Scheme_URI;
996 166 : kms_uri = cstr->tci->KMS_URI;
997 :
998 : /*default to FILE uri*/
999 166 : if (!kms_uri || !strlen(kms_uri) ) {
1000 : kms_uri = cfile_name;
1001 : }
1002 :
1003 166 : if (!cstr->keys) {
1004 148 : cstr->multi_key = cstr->tci->multi_key;
1005 148 : if (cstr->multi_key) {
1006 3 : switch (scheme_type) {
1007 : case GF_CRYPT_TYPE_CENC:
1008 : case GF_CRYPT_TYPE_CENS:
1009 : case GF_CRYPT_TYPE_PIFF:
1010 : case GF_CRYPT_TYPE_CBC1:
1011 : case GF_CRYPT_TYPE_CBCS:
1012 : break;
1013 0 : default:
1014 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[ISMACrypt] Multi-key not possible with scheme %s, ignoring\n", gf_4cc_to_str(scheme_type) ));
1015 0 : cstr->multi_key = 0;
1016 0 : break;
1017 : }
1018 145 : }
1019 148 : if (!cstr->multi_key) {
1020 145 : cstr->nb_keys = 1;
1021 145 : cstr->keys = gf_malloc(sizeof(CENC_MKey) * cstr->nb_keys);
1022 145 : if (!cstr->keys) return GF_OUT_OF_MEM;
1023 145 : memset(cstr->keys, 0, sizeof(CENC_MKey) * cstr->nb_keys);
1024 : }
1025 : }
1026 :
1027 166 : cstr->ctr_mode = GF_FALSE;
1028 :
1029 166 : switch (scheme_type) {
1030 6 : case GF_CRYPT_TYPE_ISMA:
1031 6 : cstr->ctr_mode = GF_TRUE;
1032 6 : return isma_enc_configure(ctx, cstr, GF_TRUE, scheme_uri, kms_uri);
1033 0 : case GF_CRYPT_TYPE_OMA:
1034 0 : return isma_enc_configure(ctx, cstr, GF_FALSE, scheme_uri, kms_uri);
1035 5 : case GF_CRYPT_TYPE_ADOBE:
1036 5 : return adobe_enc_configure(ctx, cstr);
1037 129 : case GF_CRYPT_TYPE_CENC:
1038 : case GF_CRYPT_TYPE_CENS:
1039 : case GF_CRYPT_TYPE_PIFF:
1040 129 : cstr->ctr_mode = GF_TRUE;
1041 155 : case GF_CRYPT_TYPE_CBC1:
1042 : case GF_CRYPT_TYPE_CBCS:
1043 155 : return cenc_enc_configure(ctx, cstr, cfile_name);
1044 : default:
1045 : return GF_NOT_SUPPORTED;
1046 : }
1047 :
1048 : return e;
1049 : }
1050 :
1051 :
1052 979 : static GF_Err isma_process(GF_CENCEncCtx *ctx, GF_CENCStream *cstr, GF_FilterPacket *pck)
1053 : {
1054 : u32 isma_hdr_size=0;
1055 : GF_FilterPacket *dst_pck;
1056 : const u8 *data;
1057 : u8 *output;
1058 : u32 size, rand, flags;
1059 979 : u64 cts = gf_filter_pck_get_cts(pck);
1060 979 : u8 sap = gf_filter_pck_get_sap(pck);
1061 :
1062 :
1063 : flags = 0;
1064 :
1065 979 : switch (cstr->tci->sel_enc_type) {
1066 0 : case GF_CRYPT_SELENC_RAP:
1067 0 : if (sap) flags |= GF_ISOM_ISMA_IS_ENCRYPTED;
1068 : break;
1069 0 : case GF_CRYPT_SELENC_NON_RAP:
1070 0 : if (!sap) flags |= GF_ISOM_ISMA_IS_ENCRYPTED;
1071 : break;
1072 : /*random*/
1073 0 : case GF_CRYPT_SELENC_RAND:
1074 0 : rand = gf_rand();
1075 0 : if (rand%2) flags |= GF_ISOM_ISMA_IS_ENCRYPTED;
1076 : break;
1077 : /*random every sel_freq samples*/
1078 0 : case GF_CRYPT_SELENC_RAND_RANGE:
1079 0 : if (! (cstr->nb_pck % cstr->tci->sel_enc_range) ) cstr->has_crypted_pck = 0;
1080 0 : if (! cstr->has_crypted_pck) {
1081 0 : rand = gf_rand();
1082 0 : if (!(rand % cstr->tci->sel_enc_range)) flags |= GF_ISOM_ISMA_IS_ENCRYPTED;
1083 :
1084 0 : if (!(flags & GF_ISOM_ISMA_IS_ENCRYPTED) && !( (1+cstr->nb_pck) % cstr->tci->sel_enc_range)) {
1085 : flags |= GF_ISOM_ISMA_IS_ENCRYPTED;
1086 : }
1087 0 : cstr->has_crypted_pck = (flags & GF_ISOM_ISMA_IS_ENCRYPTED);
1088 : }
1089 : break;
1090 : /*every sel_freq samples*/
1091 0 : case GF_CRYPT_SELENC_RANGE:
1092 0 : if (!(cstr->nb_pck % cstr->tci->sel_enc_type)) flags |= GF_ISOM_ISMA_IS_ENCRYPTED;
1093 : break;
1094 0 : case GF_CRYPT_SELENC_PREVIEW:
1095 0 : if (cts >= cstr->range_end)
1096 : flags |= GF_ISOM_ISMA_IS_ENCRYPTED;
1097 : break;
1098 979 : case 0:
1099 : flags |= GF_ISOM_ISMA_IS_ENCRYPTED;
1100 : break;
1101 : default:
1102 : break;
1103 : }
1104 :
1105 979 : if (cstr->tci->sel_enc_type) flags |= GF_ISOM_ISMA_USE_SEL_ENC;
1106 :
1107 979 : if (flags & GF_ISOM_ISMA_USE_SEL_ENC) isma_hdr_size = 1;
1108 979 : if (flags & GF_ISOM_ISMA_IS_ENCRYPTED) isma_hdr_size += cstr->isma_IV_size + cstr->KI_length;
1109 :
1110 979 : data = gf_filter_pck_get_data(pck, &size);
1111 979 : if (!data) {
1112 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[ISMACrypt] No data associated with packet\n" ));
1113 : return GF_OK;
1114 : }
1115 979 : dst_pck = gf_filter_pck_new_alloc(cstr->opid, size+isma_hdr_size, &output);
1116 979 : if (!dst_pck) return GF_OUT_OF_MEM;
1117 :
1118 979 : memcpy(output+isma_hdr_size, data, sizeof(char)*size);
1119 979 : gf_filter_pck_merge_properties(pck, dst_pck);
1120 :
1121 :
1122 : /*isma e&a stores AVC1 in AVC/H264 annex B bitstream fashion, with 0x00000001 start codes*/
1123 979 : if (cstr->nalu_size_length) {
1124 : u32 done = 0;
1125 425 : u8 *d = (u8*) output+isma_hdr_size;
1126 3111 : while (done < size) {
1127 2686 : u32 nal_size = GF_4CC(d[0], d[1], d[2], d[3]);
1128 2686 : d[0] = d[1] = d[2] = 0;
1129 2686 : d[3] = 1;
1130 2686 : d += 4 + nal_size;
1131 2686 : done += 4 + nal_size;
1132 : }
1133 : }
1134 :
1135 : //encrypt
1136 979 : if (flags & GF_ISOM_ISMA_IS_ENCRYPTED) {
1137 : /*resync IV*/
1138 979 : if (!cstr->prev_pck_encryped) {
1139 : char IV[17];
1140 : u64 count;
1141 : u32 remain;
1142 : GF_BitStream *bs;
1143 0 : count = cstr->BSO / 16;
1144 0 : remain = (u32) (cstr->BSO % 16);
1145 :
1146 : /*format IV to begin of counter*/
1147 0 : bs = gf_bs_new(IV, 17, GF_BITSTREAM_WRITE);
1148 0 : gf_bs_write_u8(bs, 0); /*begin of counter*/
1149 0 : gf_bs_write_data(bs, cstr->tci->keys[0].IV, 8);
1150 0 : gf_bs_write_u64(bs, (s64) count);
1151 0 : gf_bs_del(bs);
1152 0 : gf_crypt_set_IV(cstr->keys[0].crypt, IV, GF_AES_128_KEYSIZE+1);
1153 :
1154 : /*decrypt remain bytes*/
1155 0 : if (remain) {
1156 : char dummy[20];
1157 0 : gf_crypt_decrypt(cstr->keys[0].crypt, dummy, remain);
1158 : }
1159 : }
1160 979 : gf_crypt_encrypt(cstr->keys[0].crypt, output+isma_hdr_size, size);
1161 979 : cstr->prev_pck_encryped = GF_TRUE;
1162 : } else {
1163 0 : cstr->prev_pck_encryped = GF_FALSE;
1164 : }
1165 :
1166 : //rewrite ISMA header
1167 979 : if (!ctx->bs_w) ctx->bs_w = gf_bs_new(output, isma_hdr_size, GF_BITSTREAM_WRITE);
1168 973 : else gf_bs_reassign_buffer(ctx->bs_w, output, isma_hdr_size);
1169 :
1170 979 : if (flags & GF_ISOM_ISMA_USE_SEL_ENC) {
1171 0 : gf_bs_write_int(ctx->bs_w, (flags & GF_ISOM_ISMA_IS_ENCRYPTED) ? 1 : 0, 1);
1172 0 : gf_bs_write_int(ctx->bs_w, 0, 7);
1173 : }
1174 979 : if (flags & GF_ISOM_ISMA_IS_ENCRYPTED) {
1175 979 : if (cstr->isma_IV_size) gf_bs_write_long_int(ctx->bs_w, (s64) cstr->BSO, 8*cstr->isma_IV_size);
1176 : //not yet implemented
1177 : // if (cstr->KI_length) gf_bs_write_data(ctx->bs_w, (char*) key_indicator, cstr->KI_length);
1178 : }
1179 :
1180 979 : cstr->BSO += size;
1181 :
1182 979 : gf_filter_pck_send(dst_pck);
1183 : return GF_OK;
1184 : }
1185 :
1186 932 : static GF_Err adobe_process(GF_CENCEncCtx *ctx, GF_CENCStream *cstr, GF_FilterPacket *pck)
1187 : {
1188 : Bool is_encrypted = GF_TRUE;
1189 : GF_FilterPacket *dst_pck;
1190 : const u8 *data;
1191 : u8 *output;
1192 : GF_Err e;
1193 : bin128 IV;
1194 : u32 size, adobe_hdr_size;
1195 : u32 len, padding_bytes;
1196 932 : u8 sap = gf_filter_pck_get_sap(pck);
1197 :
1198 932 : switch (cstr->tci->sel_enc_type) {
1199 932 : case GF_CRYPT_SELENC_RAP:
1200 932 : if (!sap) is_encrypted = GF_FALSE;
1201 : break;
1202 0 : case GF_CRYPT_SELENC_NON_RAP:
1203 0 : if (sap) is_encrypted = GF_FALSE;
1204 : break;
1205 : default:
1206 : break;
1207 : }
1208 :
1209 : adobe_hdr_size = 1;
1210 : if (is_encrypted) adobe_hdr_size += 16;
1211 :
1212 932 : data = gf_filter_pck_get_data(pck, &size);
1213 932 : if (!data) {
1214 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[ISMACrypt] No data associated with packet\n" ));
1215 : return GF_OK;
1216 : }
1217 : padding_bytes = 0;
1218 932 : len = size;
1219 932 : if (is_encrypted) {
1220 346 : padding_bytes = 16 - len % 16;
1221 346 : len += padding_bytes;
1222 : }
1223 932 : dst_pck = gf_filter_pck_new_alloc(cstr->opid, len + adobe_hdr_size, &output);
1224 932 : if (!dst_pck) return GF_OUT_OF_MEM;
1225 932 : memcpy(output+adobe_hdr_size, data, sizeof(char)*size);
1226 932 : gf_filter_pck_merge_properties(pck, dst_pck);
1227 :
1228 :
1229 932 : if (is_encrypted) {
1230 346 : if (!cstr->prev_pck_encryped) {
1231 5 : memcpy(IV, cstr->tci->keys[0].IV, sizeof(char)*16);
1232 5 : e = gf_crypt_init(cstr->keys[0].crypt, cstr->keys[0].key, IV);
1233 5 : cstr->prev_pck_encryped = GF_TRUE;
1234 : } else {
1235 341 : cstr->isma_IV_size = 16;
1236 341 : e = gf_crypt_get_IV(cstr->keys[0].crypt, IV, &cstr->isma_IV_size);
1237 : }
1238 :
1239 346 : if (e) {
1240 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[ADOBE] Cannot initialize AES-128 CBC (%s)\n", gf_error_to_string(e)) );
1241 0 : gf_filter_pck_discard(dst_pck);
1242 : return GF_IO_ERR;
1243 : }
1244 :
1245 346 : memset(output+adobe_hdr_size+size, padding_bytes, sizeof(char)*padding_bytes);
1246 :
1247 346 : gf_crypt_encrypt(cstr->keys[0].crypt, output+adobe_hdr_size, len);
1248 :
1249 : /*write encrypted AU header*/
1250 346 : output[0] = 0x10;
1251 346 : memcpy(output+1, (char *) IV, sizeof(char) * 16);
1252 : } else {
1253 : /*write encrypted AU header*/
1254 586 : output[0] = 0x0;
1255 : }
1256 :
1257 932 : gf_filter_pck_send(dst_pck);
1258 : return GF_OK;
1259 : }
1260 :
1261 :
1262 : /*Common Encryption*/
1263 : static void increase_counter(char *x, int x_size) {
1264 : register int i;
1265 :
1266 12827 : for (i=x_size-1; i>=0; i--) {
1267 : register int y=0;
1268 7732 : if ((u8) x[i] == 0xFF) {
1269 32 : x[i] = 0;
1270 : y = 1;
1271 7700 : } else x[i]++;
1272 :
1273 : if (y==0) break;
1274 : }
1275 :
1276 : return;
1277 : }
1278 :
1279 21117 : static void cenc_resync_IV(GF_Crypt *mc, char IV[16], u8 IV_size)
1280 : {
1281 : char next_IV[17];
1282 21117 : u32 size = 17;
1283 :
1284 21117 : gf_crypt_get_IV(mc, (u8 *) next_IV, &size);
1285 : /*
1286 : NOTE 1: the next_IV returned by get_state has 17 bytes, the first byte being the current counter position in the following 16 bytes.
1287 : If this index is 0, this means that we are at the beginning of a new block and we can use it as IV for next sample,
1288 : otherwise we must discard unused bytes in the counter (next sample shall begin with counter at 0)
1289 : if less than 16 blocks were cyphered, we must force increasing the next IV for next sample, not doing so would produce the same IV for the next bytes cyphered,
1290 : which is forbidden by CENC (unique IV per sample). In GPAC, we ALWAYS force counter increase
1291 :
1292 : NOTE 2: in case where IV_size is 8, because the cypher block is treated as 16 bytes while processing,
1293 : we need to increment manually the 8-bytes IV (bytes 0 to 7) for the next sample, otherwise we would likely use the same IV (eg unless we had cyphered 16 * 2^64 - 1
1294 : bytes in the last sample , quite unlikely !)
1295 :
1296 : NOTE 3: Bytes 8 to 15 are set to 0 when forcing a new IV for 8-bytes IVs.
1297 :
1298 : NOTE 4: Since CENC forces declaration of a unique, potentially random, IV per sample, we could increase the IV counter at each sample start
1299 : but this is currently not done
1300 : */
1301 21117 : if (IV_size == 8) {
1302 : /*cf note 2*/
1303 : increase_counter(&next_IV[1], IV_size);
1304 2637 : next_IV[0] = 0;
1305 : /*cf note 3*/
1306 : memset(&next_IV[9], 0, 8*sizeof(char));
1307 18480 : } else if (next_IV[0]) {
1308 : /*cf note 1*/
1309 5063 : increase_counter(&next_IV[1], IV_size);
1310 5063 : next_IV[0] = 0;
1311 : }
1312 :
1313 21117 : gf_crypt_set_IV(mc, next_IV, size);
1314 :
1315 : memset(IV, 0, 16*sizeof(char));
1316 : memcpy(IV, next_IV+1, 16*sizeof(char));
1317 21117 : }
1318 :
1319 : #ifndef GPAC_DISABLE_AV_PARSERS
1320 : //parses slice header and returns its size
1321 65729 : static u32 cenc_get_clear_bytes(GF_CENCStream *cstr, GF_BitStream *plaintext_bs, char *samp_data, u32 nal_size, u32 bytes_in_nalhr)
1322 : {
1323 : u32 clear_bytes = 0;
1324 65729 : if (cstr->slice_header_clear) {
1325 65207 : u32 nal_start = (u32) gf_bs_get_position(plaintext_bs);
1326 65207 : if (cstr->cenc_codec==CENC_AVC) {
1327 : u32 ntype;
1328 7349 : gf_avc_parse_nalu(plaintext_bs, &cstr->avc);
1329 7349 : ntype = cstr->avc.last_nal_type_parsed;
1330 : switch (ntype) {
1331 7280 : case GF_AVC_NALU_NON_IDR_SLICE:
1332 : case GF_AVC_NALU_DP_A_SLICE:
1333 : case GF_AVC_NALU_DP_B_SLICE:
1334 : case GF_AVC_NALU_DP_C_SLICE:
1335 : case GF_AVC_NALU_IDR_SLICE:
1336 : case GF_AVC_NALU_SLICE_AUX:
1337 : case GF_AVC_NALU_SVC_SLICE:
1338 7280 : gf_bs_align(plaintext_bs);
1339 7280 : clear_bytes = (u32) gf_bs_get_position(plaintext_bs) - nal_start;
1340 7280 : break;
1341 : default:
1342 : clear_bytes = nal_size;
1343 : break;
1344 : }
1345 : } else {
1346 : #if !defined(GPAC_DISABLE_HEVC)
1347 : u8 ntype, ntid, nlid;
1348 57858 : cstr->hevc.full_slice_header_parse = GF_TRUE;
1349 57858 : gf_hevc_parse_nalu (samp_data + nal_start, nal_size, &cstr->hevc, &ntype, &ntid, &nlid);
1350 57858 : if (ntype<=GF_HEVC_NALU_SLICE_CRA) {
1351 52058 : clear_bytes = cstr->hevc.s_info.payload_start_offset;
1352 : } else {
1353 : clear_bytes = nal_size;
1354 : }
1355 : #endif
1356 : }
1357 65207 : gf_bs_seek(plaintext_bs, nal_start);
1358 : } else {
1359 : clear_bytes = bytes_in_nalhr;
1360 : }
1361 65729 : gf_bs_enable_emulation_byte_removal(plaintext_bs, GF_FALSE);
1362 65729 : return clear_bytes;
1363 : }
1364 : #endif
1365 :
1366 23159 : static GF_Err cenc_encrypt_packet(GF_CENCEncCtx *ctx, GF_CENCStream *cstr, GF_FilterPacket *pck)
1367 : {
1368 : GF_BitStream *sai_bs;
1369 : u32 prev_entry_bytes_clear=0;
1370 : u32 prev_entry_bytes_crypt=0;
1371 : u32 prev_entry_mkey_idx=0;
1372 : u32 pck_size;
1373 : GF_FilterPacket *dst_pck;
1374 : const u8 *data;
1375 : u8 *output;
1376 : u32 sai_size;
1377 : u32 i, nb_iv_init=0, nb_keys, nb_subsamples_bits, sai_size_sub, nb_subsamples=0;
1378 : u32 key_idx = 0;
1379 : u32 subsample_idx = 0;
1380 : u32 nb_subs_crypted = 0;
1381 : u32 nb_sub_offset;
1382 : Bool multi_key;
1383 :
1384 23159 : if (cstr->multi_key) {
1385 2250 : nb_keys = cstr->tci->nb_keys;
1386 : multi_key = GF_TRUE;
1387 : nb_subsamples_bits = 32;
1388 : sai_size_sub = 8;
1389 : } else {
1390 : nb_keys = 1;
1391 : multi_key = GF_FALSE;
1392 : nb_subsamples_bits = 16;
1393 : sai_size_sub = 6;
1394 : }
1395 25409 : for (i=0; i<nb_keys; i++) {
1396 25409 : if (cstr->tci->keys[i].IV_size) {
1397 : //in cbcs scheme, if Per_Sample_IV_size is not 0 (no constant IV), fetch current IV
1398 23376 : if (!cstr->ctr_mode) {
1399 2259 : u32 IV_size = 16;
1400 2259 : gf_crypt_get_IV(cstr->keys[i].crypt, cstr->keys[i].IV, &IV_size);
1401 : }
1402 23376 : nb_iv_init++;
1403 : }
1404 : }
1405 :
1406 23159 : data = gf_filter_pck_get_data(pck, &pck_size);
1407 :
1408 : //CENC can use inplace processing for decryption
1409 23159 : dst_pck = gf_filter_pck_new_clone(cstr->opid, pck, &output);
1410 23159 : if (!dst_pck) return GF_OUT_OF_MEM;
1411 :
1412 23159 : gf_filter_pck_merge_properties(pck, dst_pck);
1413 23159 : gf_filter_pck_set_crypt_flags(dst_pck, GF_FILTER_PCK_CRYPT);
1414 :
1415 23159 : if (!ctx->bs_r) ctx->bs_r = gf_bs_new(data, pck_size, GF_BITSTREAM_READ);
1416 23042 : else gf_bs_reassign_buffer(ctx->bs_r, data, pck_size);
1417 :
1418 23159 : sai_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
1419 :
1420 23159 : if (multi_key) {
1421 2250 : gf_bs_write_u16(sai_bs, nb_iv_init);
1422 4500 : for (i=0; i<nb_keys; i++) {
1423 : //for now we use all our keys in one sample
1424 4500 : if (cstr->tci->keys[i].IV_size) {
1425 4500 : gf_bs_write_u16(sai_bs, i+1);
1426 4500 : gf_bs_write_data(sai_bs, cstr->keys[i].IV, cstr->tci->keys[i].IV_size);
1427 : }
1428 : }
1429 : nb_subsamples_bits = 32;
1430 : } else {
1431 20909 : gf_bs_write_data(sai_bs, cstr->keys[0].IV, cstr->tci->keys[0].IV_size);
1432 : }
1433 23159 : sai_size = nb_sub_offset = (u32) gf_bs_get_position(sai_bs);
1434 :
1435 98927 : while (gf_bs_available(ctx->bs_r)) {
1436 : GF_Err e=GF_OK;
1437 :
1438 75768 : if (cstr->use_subsamples) {
1439 : #ifndef GPAC_DISABLE_AV_PARSERS
1440 : ObuType obut;
1441 69930 : u32 num_frames_in_superframe = 0, superframe_index_size = 0;
1442 : u32 frame_sizes[VP9_MAX_FRAMES_IN_SUPERFRAME];
1443 : struct {
1444 : int clear, encrypted;
1445 : } ranges[AV1_MAX_TILE_ROWS * AV1_MAX_TILE_COLS];
1446 : u64 obu_size;
1447 : u32 hdr_size;
1448 : #else
1449 : struct {
1450 : int clear, encrypted;
1451 : } ranges[1];
1452 : #endif
1453 : u64 pos;
1454 : u32 clear_bytes_at_end = 0;
1455 : u32 clear_bytes = 0;
1456 : u32 nb_ranges = 1;
1457 : u32 range_idx = 0;
1458 : u32 nalu_size = 0;
1459 :
1460 : #ifndef GPAC_DISABLE_AV_PARSERS
1461 69930 : switch (cstr->cenc_codec) {
1462 65729 : case CENC_AVC:
1463 : case CENC_HEVC:
1464 65729 : nalu_size = gf_bs_read_int(ctx->bs_r, 8*cstr->nalu_size_length);
1465 65729 : if (nalu_size == 0) {
1466 0 : continue;
1467 : }
1468 65729 : clear_bytes = cenc_get_clear_bytes(cstr, ctx->bs_r, (char *) data, nalu_size, cstr->bytes_in_nal_hdr);
1469 : break;
1470 :
1471 2426 : case CENC_AV1:
1472 2426 : pos = gf_bs_get_position(ctx->bs_r);
1473 2426 : e = gf_av1_parse_obu(ctx->bs_r, &obut, &obu_size, &hdr_size, &cstr->av1);
1474 2426 : if (e) {
1475 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Failed to parse OBU\n" ));
1476 0 : return e;
1477 : }
1478 2426 : gf_bs_seek(ctx->bs_r, pos);
1479 :
1480 2426 : nalu_size = (u32)obu_size;
1481 2426 : switch (obut) {
1482 : //we only encrypt frame and tile group
1483 2328 : case OBU_FRAME:
1484 : case OBU_TILE_GROUP:
1485 2328 : if (!cstr->av1.frame_state.nb_tiles_in_obu) {
1486 : clear_bytes = (u32) obu_size;
1487 : } else {
1488 : nb_ranges = cstr->av1.frame_state.nb_tiles_in_obu;
1489 :
1490 2328 : ranges[0].clear = cstr->av1.frame_state.tiles[0].obu_start_offset;
1491 2328 : ranges[0].encrypted = cstr->av1.frame_state.tiles[0].size;
1492 0 : for (i = 1; i < nb_ranges; ++i) {
1493 0 : ranges[i].clear = cstr->av1.frame_state.tiles[i].obu_start_offset - (cstr->av1.frame_state.tiles[i - 1].obu_start_offset + cstr->av1.frame_state.tiles[i - 1].size);
1494 0 : ranges[i].encrypted = cstr->av1.frame_state.tiles[i].size;
1495 : }
1496 2328 : clear_bytes = ranges[0].clear;
1497 2328 : nalu_size = clear_bytes + ranges[0].encrypted;
1498 :
1499 : /* A subsample SHALL be created for each tile even if less than 16 bytes
1500 : see https://github.com/AOMediaCodec/av1-isobmff/pull/116#discussion_r340176740
1501 :
1502 : If previous range had encrypted bytes, create a new one, otherwise merge in prev
1503 : */
1504 2328 : if (prev_entry_bytes_crypt) {
1505 346 : if (!nb_subsamples) gf_bs_write_int(sai_bs, 0, nb_subsamples_bits);
1506 346 : nb_subsamples++;
1507 346 : if (multi_key)
1508 0 : gf_bs_write_u16(sai_bs, prev_entry_bytes_crypt ? (prev_entry_mkey_idx+1) : 0);
1509 346 : gf_bs_write_u16(sai_bs, prev_entry_bytes_clear);
1510 346 : gf_bs_write_u32(sai_bs, prev_entry_bytes_crypt);
1511 346 : sai_size += sai_size_sub;
1512 :
1513 : prev_entry_bytes_crypt = 0;
1514 : prev_entry_bytes_clear = 0;
1515 : prev_entry_mkey_idx = 0;
1516 : }
1517 : }
1518 : break;
1519 : default:
1520 : clear_bytes = (u32) obu_size;
1521 : break;
1522 : }
1523 : break;
1524 1775 : case CENC_VPX:
1525 1775 : if (cstr->tci->block_align != 2) {
1526 7 : GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[CENC] VP9 mandates that blockAlign=\"always\". Forcing value.\n"));
1527 7 : cstr->tci->block_align = 2;
1528 : }
1529 :
1530 1775 : pos = gf_bs_get_position(ctx->bs_r);
1531 1775 : e = gf_media_vp9_parse_superframe(ctx->bs_r, pck_size, &num_frames_in_superframe, frame_sizes, &superframe_index_size);
1532 1775 : if (e || !num_frames_in_superframe) return e;
1533 1775 : gf_bs_seek(ctx->bs_r, pos);
1534 :
1535 1775 : nb_ranges = num_frames_in_superframe;
1536 :
1537 1775 : for (i = 0; i < num_frames_in_superframe; ++i) {
1538 : Bool key_frame;
1539 1775 : u32 width = 0, height = 0, renderWidth = 0, renderHeight = 0;
1540 1775 : GF_VPConfig *vp9_cfg = gf_odf_vp_cfg_new();
1541 1775 : u64 pos2 = gf_bs_get_position(ctx->bs_r);
1542 1775 : e = gf_media_vp9_parse_sample(ctx->bs_r, vp9_cfg, &key_frame, &width, &height, &renderWidth, &renderHeight);
1543 1775 : gf_odf_vp_cfg_del(vp9_cfg);
1544 1775 : if (e) {
1545 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[CENC] Error parsing VP9 frame at DTS "LLU"\n", gf_filter_pck_get_dts(pck) ));
1546 0 : return e;
1547 : }
1548 :
1549 1775 : ranges[i].clear = (int)(gf_bs_get_position(ctx->bs_r) - pos2);
1550 1775 : ranges[i].encrypted = frame_sizes[i] - ranges[i].clear;
1551 :
1552 1775 : gf_bs_seek(ctx->bs_r, pos2 + frame_sizes[i]);
1553 : }
1554 1775 : if (gf_bs_get_position(ctx->bs_r) + superframe_index_size != pos + pck_size) {
1555 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[CENC] Inconsistent VP9 size %u (parsed "LLU") at DTS "LLU". Re-import raw VP9/IVF for more details.\n",
1556 : pck_size, gf_bs_get_position(ctx->bs_r) + superframe_index_size - pos, gf_filter_pck_get_dts(pck)));
1557 : }
1558 1775 : gf_bs_seek(ctx->bs_r, pos);
1559 :
1560 1775 : clear_bytes = ranges[0].clear;
1561 : assert(frame_sizes[0] == ranges[0].clear + ranges[0].encrypted);
1562 1775 : nalu_size = frame_sizes[0];
1563 :
1564 : //final superframe index must be in clear
1565 1775 : if (superframe_index_size > 0) {
1566 0 : ranges[nb_ranges].clear = superframe_index_size;
1567 0 : ranges[nb_ranges].encrypted = 0;
1568 0 : nb_ranges++;
1569 : }
1570 :
1571 : //not clearly defined in the spec (so we do the same as in AV1 which is more clearly defined):
1572 1775 : if (frame_sizes[0] - clear_bytes >= 16) {
1573 : //A subsample SHALL be created for each tile >= 16 bytes. If previous range had encrypted bytes, create a new one, otherwise merge in prev
1574 1775 : if (prev_entry_bytes_crypt) {
1575 0 : if (!nb_subsamples) gf_bs_write_int(sai_bs, 0, nb_subsamples_bits);
1576 0 : nb_subsamples++;
1577 0 : if (multi_key)
1578 0 : gf_bs_write_u16(sai_bs, prev_entry_bytes_crypt ? (prev_entry_mkey_idx+1) : 0);
1579 0 : gf_bs_write_u16(sai_bs, prev_entry_bytes_clear);
1580 0 : gf_bs_write_u32(sai_bs, prev_entry_bytes_crypt);
1581 0 : sai_size += sai_size_sub;
1582 :
1583 : prev_entry_bytes_crypt = 0;
1584 : prev_entry_bytes_clear = 0;
1585 : prev_entry_mkey_idx = 0;
1586 : }
1587 : } else {
1588 : clear_bytes = nalu_size;
1589 : }
1590 : break;
1591 69930 : default:
1592 : assert(0);
1593 : }
1594 : #else
1595 : clear_bytes = nalu_size;
1596 : #endif
1597 :
1598 : //VCL subsample, check out settings to decide if we leave it in the clear
1599 133893 : if ((nalu_size > clear_bytes) &&
1600 121176 : (cstr->tci->subs_crypt || cstr->tci->subs_rand || cstr->multi_key)
1601 : ) {
1602 : Bool do_crypt = GF_TRUE;
1603 :
1604 27000 : if (cstr->mkey_indices.nb_items) {
1605 6750 : if (subsample_idx>=cstr->mkey_indices.nb_items)
1606 : do_crypt = GF_FALSE;
1607 : else {
1608 6750 : key_idx = cstr->mkey_indices.vals[subsample_idx];
1609 6750 : if (!key_idx || (key_idx>cstr->nb_keys))
1610 : do_crypt = GF_FALSE;
1611 : else
1612 4500 : key_idx-=1;
1613 : }
1614 : }
1615 27000 : subsample_idx++;
1616 27000 : if (do_crypt && cstr->tci->subs_crypt) {
1617 : char szSub[20], *sep;
1618 : sprintf(szSub, "%d", subsample_idx);
1619 6750 : sep = strstr(cstr->tci->subs_crypt, szSub);
1620 6750 : if (sep) {
1621 2250 : u32 len = (u32) strlen(szSub);
1622 2250 : if ((sep[len]!=',') && sep[len])
1623 : do_crypt = GF_FALSE;
1624 : } else {
1625 : do_crypt = GF_FALSE;
1626 : }
1627 : }
1628 22500 : if (do_crypt && cstr->tci->subs_rand) {
1629 0 : u32 rndm = gf_rand() % cstr->tci->subs_rand;
1630 0 : if (rndm)
1631 : do_crypt = GF_FALSE;
1632 : }
1633 :
1634 27000 : if (!do_crypt) {
1635 : clear_bytes = nalu_size;
1636 : } else {
1637 20250 : nb_subs_crypted++;
1638 : }
1639 : }
1640 :
1641 69930 : while (nb_ranges) {
1642 69930 : if (cstr->ctr_mode) {
1643 :
1644 : // adjust so that encrypted bytes are a multiple of 16 bytes: cenc SHOULD, cens SHALL, we always do it
1645 61880 : if (nalu_size > clear_bytes) {
1646 49735 : u32 ret = (nalu_size - clear_bytes) % 16;
1647 : //in AV1 always enforced
1648 49735 : if (cstr->cenc_codec==CENC_AV1) {
1649 1899 : clear_bytes += ret;
1650 : }
1651 : //for CENC (should),
1652 47836 : else if ((cstr->tci->scheme_type == GF_CRYPT_TYPE_CENC) || (cstr->tci->scheme_type == GF_CRYPT_TYPE_PIFF)) {
1653 : //do it if not disabled by user
1654 42622 : if (cstr->tci->block_align != 1) {
1655 : //always align even if sample is not encrypted in the end
1656 39841 : if (cstr->tci->block_align==2) {
1657 4382 : clear_bytes += ret;
1658 : }
1659 : //or if we don't end up with sample in the clear
1660 35459 : else if (nalu_size > clear_bytes + ret) {
1661 : clear_bytes += ret;
1662 : }
1663 : }
1664 : } else {
1665 5214 : clear_bytes += ret;
1666 : }
1667 : }
1668 : } else {
1669 : //in cbcs, we don't adjust bytes_encrypted_data to be a multiple of 16 bytes and leave the last block unencrypted
1670 : //except in VPX, where BytesOfProtectedData SHALL end on the last byte of the decode_tile structure
1671 8050 : if ((cstr->cenc_codec != CENC_VPX) && (cstr->tci->scheme_type == GF_CRYPT_TYPE_CBCS)) {
1672 7887 : u32 ret = (nalu_size - clear_bytes) % 16;
1673 : clear_bytes_at_end = ret;
1674 : }
1675 : //in cbc1 or cbcs+VPX, we adjust bytes_encrypted_data to be a multiple of 16 bytes
1676 : else {
1677 163 : u32 ret = (nalu_size - clear_bytes) % 16;
1678 163 : clear_bytes += ret;
1679 : clear_bytes_at_end = 0;
1680 : }
1681 :
1682 : }
1683 :
1684 : /*skip bytes of clear data*/
1685 69930 : gf_bs_skip_bytes(ctx->bs_r, clear_bytes);
1686 :
1687 : //read data to encrypt
1688 69930 : if (nalu_size > clear_bytes) {
1689 : /*get encrypted data start*/
1690 56023 : u32 cur_pos = (u32) gf_bs_get_position(ctx->bs_r);
1691 :
1692 : /*skip bytes of encrypted data*/
1693 56023 : gf_bs_skip_bytes(ctx->bs_r, nalu_size - clear_bytes);
1694 :
1695 : //cbcs scheme with constant IV, reinit at each sub sample,
1696 56023 : if (!cstr->ctr_mode && !cstr->tci->keys[key_idx].IV_size)
1697 3744 : gf_crypt_set_IV(cstr->keys[key_idx].crypt, cstr->keys[key_idx].IV, 16);
1698 :
1699 : //pattern encryption
1700 56023 : if (cstr->tci->crypt_byte_block && cstr->tci->skip_byte_block) {
1701 12545 : u32 res = nalu_size - clear_bytes - clear_bytes_at_end;
1702 : pos = cur_pos;
1703 : assert((res % 16) == 0);
1704 :
1705 47725 : while (res) {
1706 35180 : e = gf_crypt_encrypt(cstr->keys[key_idx].crypt, output+pos, res >= (u32) (16*cstr->tci->crypt_byte_block) ? 16*cstr->tci->crypt_byte_block : res);
1707 35180 : if (res >= (u32) (16 * (cstr->tci->crypt_byte_block + cstr->tci->skip_byte_block))) {
1708 23866 : pos += 16 * (cstr->tci->crypt_byte_block + cstr->tci->skip_byte_block);
1709 23866 : res -= 16 * (cstr->tci->crypt_byte_block + cstr->tci->skip_byte_block);
1710 : } else {
1711 : res = 0;
1712 : }
1713 : }
1714 : }
1715 : //full subsample encryption
1716 : else {
1717 43478 : e = gf_crypt_encrypt(cstr->keys[key_idx].crypt, output+cur_pos, nalu_size - clear_bytes);
1718 : }
1719 : }
1720 :
1721 :
1722 : //prev entry is not a VCL, append this NAL
1723 69930 : if (!prev_entry_bytes_crypt) {
1724 24619 : prev_entry_bytes_clear += cstr->nalu_size_length + clear_bytes;
1725 24619 : prev_entry_bytes_crypt += nalu_size - clear_bytes;
1726 24619 : if (prev_entry_bytes_crypt)
1727 : prev_entry_mkey_idx = key_idx;
1728 : } else {
1729 : //store current
1730 45311 : if (!nb_subsamples) gf_bs_write_int(sai_bs, 0, nb_subsamples_bits);
1731 45311 : nb_subsamples++;
1732 45311 : if (multi_key)
1733 18000 : gf_bs_write_u16(sai_bs, prev_entry_bytes_crypt ? (prev_entry_mkey_idx+1) : 0);
1734 45311 : gf_bs_write_u16(sai_bs, prev_entry_bytes_clear);
1735 45311 : gf_bs_write_u32(sai_bs, prev_entry_bytes_crypt);
1736 45311 : sai_size += sai_size_sub;
1737 :
1738 45311 : prev_entry_bytes_clear = cstr->nalu_size_length + clear_bytes;
1739 45311 : prev_entry_bytes_crypt = nalu_size - clear_bytes;
1740 : prev_entry_mkey_idx = key_idx;
1741 : }
1742 :
1743 : //subsample was a possible encryption target, apply key roll
1744 69930 : if (multi_key && prev_entry_bytes_crypt && !cstr->mkey_indices.nb_items) {
1745 : Bool change_key = GF_FALSE;
1746 13500 : if (!cstr->tci->mkey_roll_plus_one) {
1747 : change_key = GF_TRUE;
1748 6750 : } else if (cstr->tci->mkey_roll_plus_one>1) {
1749 6750 : if (nb_subs_crypted + 1 == cstr->tci->mkey_roll_plus_one) {
1750 : change_key = GF_TRUE;
1751 : nb_subs_crypted = 0;
1752 : }
1753 : }
1754 : if (change_key) {
1755 9750 : key_idx++;
1756 9750 : if (key_idx==cstr->nb_keys)
1757 : key_idx = 0;
1758 : }
1759 : }
1760 :
1761 : //check bytes of clear is not larger than 16bits
1762 69930 : while (prev_entry_bytes_clear > 0xFFFF) {
1763 : //store current
1764 0 : if (!nb_subsamples) gf_bs_write_int(sai_bs, 0, nb_subsamples_bits);
1765 0 : nb_subsamples++;
1766 0 : if (multi_key)
1767 0 : gf_bs_write_u16(sai_bs, 0);
1768 0 : gf_bs_write_u16(sai_bs, 0xFFFF);
1769 0 : gf_bs_write_u32(sai_bs, 0);
1770 0 : sai_size += sai_size_sub;
1771 :
1772 0 : prev_entry_bytes_clear -= 0xFFFF;
1773 : }
1774 :
1775 :
1776 69930 : nb_ranges--;
1777 69930 : if (!nb_ranges) break;
1778 :
1779 0 : range_idx++;
1780 0 : if (range_idx >= AV1_MAX_TILE_ROWS * AV1_MAX_TILE_COLS) {
1781 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] More ranges than tiles allowed spec, bitstream error ?\n"));
1782 : return GF_BAD_PARAM;
1783 : }
1784 0 : switch (cstr->cenc_codec) {
1785 0 : case CENC_AV1:
1786 0 : clear_bytes = ranges[range_idx].clear;
1787 0 : nalu_size = clear_bytes + ranges[range_idx].encrypted;
1788 : break;
1789 0 : case CENC_VPX:
1790 0 : if (nb_ranges > 1) {
1791 0 : clear_bytes = ranges[range_idx].clear;
1792 0 : nalu_size = clear_bytes + ranges[range_idx].encrypted;
1793 : } else { /*last*/
1794 0 : nalu_size = clear_bytes = ranges[range_idx].clear;
1795 : assert(ranges[range_idx].encrypted == 0);
1796 : }
1797 : break;
1798 0 : default:
1799 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Unexpected subrange for sample format, only allowed for VPX and AV1\n"));
1800 : return GF_BAD_PARAM;
1801 : }
1802 : }
1803 : }
1804 : //the other cases are NOT multi-key
1805 : //CTR full sample
1806 5838 : else if (cstr->ctr_mode) {
1807 4848 : gf_bs_skip_bytes(ctx->bs_r, pck_size);
1808 4848 : e = gf_crypt_encrypt(cstr->keys[0].crypt, output, pck_size);
1809 : }
1810 : //CBC full sample with padding
1811 : else {
1812 : u32 clear_trailing;
1813 :
1814 990 : clear_trailing = pck_size % 16;
1815 :
1816 : //cbcs scheme with constant IV, reinit at each sample,
1817 990 : if (!cstr->tci->keys[0].IV_size)
1818 330 : gf_crypt_set_IV(cstr->keys[0].crypt, cstr->keys[0].IV, 16);
1819 :
1820 990 : if (pck_size >= 16) {
1821 990 : gf_crypt_encrypt(cstr->keys[0].crypt, output, pck_size - clear_trailing);
1822 : }
1823 990 : gf_bs_skip_bytes(ctx->bs_r, pck_size);
1824 : }
1825 :
1826 75768 : if (e) {
1827 0 : gf_filter_pck_discard(dst_pck);
1828 : return e;
1829 : }
1830 : }
1831 :
1832 23159 : if (prev_entry_bytes_clear || prev_entry_bytes_crypt) {
1833 17321 : if (!nb_subsamples) gf_bs_write_int(sai_bs, 0, nb_subsamples_bits);
1834 17321 : nb_subsamples++;
1835 17321 : if (multi_key)
1836 2250 : gf_bs_write_u16(sai_bs, prev_entry_bytes_crypt ? (prev_entry_mkey_idx+1) : 0);
1837 17321 : gf_bs_write_u16(sai_bs, prev_entry_bytes_clear);
1838 17321 : gf_bs_write_u32(sai_bs, prev_entry_bytes_crypt);
1839 17321 : sai_size += sai_size_sub;
1840 : }
1841 23159 : if (cstr->ctr_mode) {
1842 21117 : for (i=0; i<nb_keys; i++) {
1843 21117 : cenc_resync_IV(cstr->keys[i].crypt, cstr->keys[i].IV, cstr->tci->keys[i].IV_size);
1844 : }
1845 : }
1846 :
1847 23159 : if (sai_size) {
1848 22829 : u8 *sai=NULL;
1849 22829 : if (cstr->use_subsamples) {
1850 17321 : sai_size = (u32) gf_bs_get_position(sai_bs);
1851 17321 : gf_bs_seek(sai_bs, nb_sub_offset);
1852 17321 : gf_bs_write_int(sai_bs, nb_subsamples, nb_subsamples_bits);
1853 17321 : gf_bs_seek(sai_bs, sai_size);
1854 : }
1855 22829 : sai_size = 0;
1856 22829 : gf_bs_get_content(sai_bs, &sai, &sai_size);
1857 :
1858 22829 : gf_filter_pck_set_property(dst_pck, GF_PROP_PCK_CENC_SAI, &PROP_DATA_NO_COPY(sai, sai_size) );
1859 : }
1860 23159 : gf_bs_del(sai_bs);
1861 :
1862 23159 : gf_filter_pck_send(dst_pck);
1863 : return GF_OK;
1864 : }
1865 :
1866 25786 : static GF_Err cenc_process(GF_CENCEncCtx *ctx, GF_CENCStream *cstr, GF_FilterPacket *pck)
1867 : {
1868 : Bool is_encrypted = GF_TRUE;
1869 : const u8 *data;
1870 : GF_Err e;
1871 : Bool all_rap=GF_FALSE;
1872 : u32 pck_size;
1873 : Bool force_clear = GF_FALSE;
1874 25786 : u8 sap = gf_filter_pck_get_sap(pck);
1875 :
1876 25786 : data = gf_filter_pck_get_data(pck, &pck_size);
1877 25786 : if (!data) {
1878 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[ISMACrypt] No data associated with packet\n" ));
1879 : return GF_OK;
1880 : }
1881 :
1882 25786 : if (!ctx->bs_w) ctx->bs_w = gf_bs_new((char *) &sap, 1, GF_BITSTREAM_WRITE);
1883 :
1884 25786 : switch (cstr->tci->sel_enc_type) {
1885 3040 : case GF_CRYPT_SELENC_RAP:
1886 3040 : if (!sap && !all_rap) {
1887 : is_encrypted = GF_FALSE;
1888 : }
1889 : break;
1890 0 : case GF_CRYPT_SELENC_NON_RAP:
1891 0 : if (sap || all_rap) {
1892 : is_encrypted = GF_FALSE;
1893 : }
1894 : break;
1895 : case GF_CRYPT_SELENC_CLEAR:
1896 : is_encrypted = GF_FALSE;
1897 : break;
1898 323 : case GF_CRYPT_SELENC_CLEAR_FORCED:
1899 : is_encrypted = GF_FALSE;
1900 323 : if (!cstr->multi_key) {
1901 : force_clear = GF_TRUE;
1902 323 : if (cstr->tci->sel_enc_range && (cstr->nb_pck+1 >= cstr->tci->sel_enc_range)) {
1903 3 : cstr->tci->sel_enc_type = GF_CRYPT_SELENC_NONE;
1904 : }
1905 : }
1906 : break;
1907 : default:
1908 : break;
1909 : }
1910 :
1911 : if (!is_encrypted) {
1912 2627 : u8 *sai=NULL;
1913 2627 : u32 i, sai_size = 0;
1914 : Bool signal_sai = GF_FALSE;
1915 : GF_FilterPacket *dst_pck;
1916 2627 : dst_pck = gf_filter_pck_new_ref(cstr->opid, 0, 0, pck);
1917 2627 : if (!dst_pck) return GF_OUT_OF_MEM;
1918 :
1919 2627 : gf_filter_pck_merge_properties(pck, dst_pck);
1920 :
1921 2627 : if (force_clear && !cstr->tci->force_clear_stsd_idx)
1922 : signal_sai = GF_TRUE;
1923 : //format NULL bitstream only for forced clear mode
1924 2627 : if (cstr->use_subsamples && signal_sai) {
1925 : GF_BitStream *bs;
1926 : u32 subsample_count = 1;
1927 50 : u32 olen = pck_size;
1928 100 : while (olen>0xFFFF) {
1929 0 : olen -= 0xFFFF;
1930 0 : subsample_count ++;
1931 : }
1932 50 : bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
1933 50 : if (force_clear) {
1934 : bin128 NULL_IV;
1935 : memset(NULL_IV, 0, 16);
1936 : memcpy(NULL_IV, (char *) &cstr->nb_pck, 4);
1937 50 : gf_bs_write_data(bs, NULL_IV, cstr->tci->keys[0].IV_size);
1938 : }
1939 50 : gf_bs_write_u16(bs, subsample_count);
1940 50 : olen = pck_size;
1941 100 : for (i = 0; i < subsample_count; i++) {
1942 50 : if (olen<0xFFFF) {
1943 50 : gf_bs_write_u16(bs, olen);
1944 : } else {
1945 0 : gf_bs_write_u16(bs, 0xFFFF);
1946 0 : olen -= 0xFFFF;
1947 : }
1948 50 : gf_bs_write_u32(bs, 0);
1949 : }
1950 50 : gf_bs_get_content(bs, &sai, &sai_size);
1951 50 : gf_bs_del(bs);
1952 : }
1953 2627 : if (sai)
1954 50 : gf_filter_pck_set_property(dst_pck, GF_PROP_PCK_CENC_SAI, &PROP_DATA_NO_COPY(sai, sai_size) );
1955 :
1956 2627 : gf_filter_pck_set_crypt_flags(dst_pck, signal_sai ? GF_FILTER_PCK_CRYPT : 0);
1957 2627 : gf_filter_pck_send(dst_pck);
1958 2627 : return GF_OK;
1959 : }
1960 :
1961 : /*load initialization vector for the first sample in track ... */
1962 23159 : if (!cstr->cenc_init) {
1963 135 : u32 i, nb_keys = cstr->multi_key ? cstr->tci->nb_keys : 1;
1964 :
1965 273 : for (i=0; i<nb_keys; i++) {
1966 : //memset IV to 0, and copy from start (0-padding at the end)
1967 138 : memset(cstr->keys[i].IV, 0, sizeof(char)*16);
1968 : //IV
1969 138 : if ((cstr->tci->keys[i].IV_size == 8) || (cstr->tci->keys[i].IV_size == 16)) {
1970 129 : memcpy(cstr->keys[i].IV, cstr->tci->keys[i].IV, sizeof(char) * cstr->tci->keys[i].IV_size);
1971 : }
1972 : //const IV
1973 9 : else if (!cstr->tci->keys[i].IV_size) {
1974 9 : if ((cstr->tci->keys[i].constant_IV_size == 8) || (cstr->tci->keys[i].constant_IV_size == 16)) {
1975 9 : memcpy(cstr->keys[i].IV, cstr->tci->keys[i].IV, sizeof(char) * cstr->tci->keys[i].constant_IV_size);
1976 : } else {
1977 : return GF_NOT_SUPPORTED;
1978 : }
1979 : } else {
1980 : return GF_NOT_SUPPORTED;
1981 : }
1982 :
1983 138 : e = gf_crypt_init(cstr->keys[i].crypt, cstr->keys[i].key, cstr->keys[i].IV);
1984 138 : if (e) {
1985 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Cannot initialize AES-128 %s (%s)\n", cstr->ctr_mode ? "CTR" : "CBC", gf_error_to_string(e)) );
1986 : return GF_IO_ERR;
1987 : }
1988 : }
1989 135 : cstr->cenc_init = GF_TRUE;
1990 23024 : } else if (!cstr->multi_key) {
1991 20777 : u32 new_idx = cstr->kidx;
1992 : Bool key_changed = GF_FALSE;
1993 :
1994 20777 : if (cstr->tci->keyRoll) {
1995 1354 : new_idx = (cstr->nb_pck_encrypted / cstr->tci->keyRoll) % cstr->tci->nb_keys;
1996 19423 : } else if (cstr->rap_roll) {
1997 0 : if ((sap==GF_FILTER_SAP_1) || (sap==GF_FILTER_SAP_2)) {
1998 0 : new_idx = (new_idx + 1) % cstr->tci->nb_keys;
1999 : }
2000 : }
2001 20777 : if (cstr->kidx != new_idx) {
2002 172 : cstr->kidx = new_idx;
2003 172 : memcpy(cstr->keys[0].key, cstr->tci->keys[cstr->kidx].key, 16);
2004 : key_changed = GF_TRUE;
2005 172 : e = gf_crypt_set_key(cstr->keys[0].crypt, cstr->keys[0].key);
2006 172 : if (e) {
2007 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Cannot set key AES-128 %s (%s)\n", cstr->ctr_mode ? "CTR" : "CBC", gf_error_to_string(e)) );
2008 : return e;
2009 : }
2010 : }
2011 :
2012 : if (key_changed) {
2013 : char *hls_info;
2014 172 : GF_CryptKeyInfo *ki = &cstr->tci->keys[cstr->kidx];
2015 : u8 key_info[40];
2016 : u32 key_info_size = 20;
2017 172 : key_info[0] = 0;
2018 172 : key_info[1] = 0;
2019 172 : key_info[2] = 0;
2020 172 : key_info[3] = ki->IV_size;
2021 : memcpy(key_info+4, ki->KID, 16);
2022 172 : if (!ki->IV_size) {
2023 7 : key_info[20] = ki->constant_IV_size;
2024 7 : memcpy(key_info+21, ki->IV, ki->constant_IV_size);
2025 7 : key_info_size += ki->constant_IV_size + 1;
2026 : }
2027 :
2028 172 : gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_CENC_KEY_INFO, &PROP_DATA( key_info, key_info_size ) );
2029 :
2030 172 : hls_info = cstr->tci->keys[cstr->kidx].hls_info;
2031 172 : gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_HLS_KMS, hls_info ? &PROP_STRING(hls_info) : NULL);
2032 : }
2033 : }
2034 :
2035 23159 : e = cenc_encrypt_packet(ctx, cstr, pck);
2036 23159 : if (e) {
2037 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Error encrypting packet %d in PID %s: %s\n", cstr->nb_pck, gf_filter_pid_get_name(cstr->ipid), gf_error_to_string(e)) );
2038 : return e;
2039 : }
2040 :
2041 23159 : cstr->nb_pck_encrypted++;
2042 23159 : return GF_OK;
2043 : }
2044 :
2045 29680 : static GF_Err cenc_enc_process(GF_Filter *filter)
2046 : {
2047 29680 : GF_CENCEncCtx *ctx = (GF_CENCEncCtx *)gf_filter_get_udta(filter);
2048 29680 : u32 i, nb_eos, count = gf_list_count(ctx->streams);
2049 :
2050 : nb_eos = 0;
2051 63821 : for (i=0; i<count; i++) {
2052 : GF_Err e = GF_OK;;
2053 34141 : GF_CENCStream *cstr = gf_list_get(ctx->streams, i);
2054 34141 : GF_FilterPacket *pck = gf_filter_pid_get_packet(cstr->ipid);
2055 34141 : if (!pck) {
2056 5152 : if (gf_filter_pid_is_eos(cstr->ipid)) {
2057 1990 : gf_filter_pid_set_eos(cstr->opid);
2058 1990 : nb_eos++;
2059 : }
2060 5152 : continue;
2061 : }
2062 :
2063 28989 : if (cstr->passthrough) {
2064 1292 : gf_filter_pck_forward(pck, cstr->opid);
2065 : }
2066 27697 : else if (cstr->isma_oma) {
2067 979 : e = isma_process(ctx, cstr, pck);
2068 26718 : } else if (cstr->is_adobe) {
2069 932 : e = adobe_process(ctx, cstr, pck);
2070 : } else {
2071 25786 : e = cenc_process(ctx, cstr, pck);
2072 : }
2073 28989 : gf_filter_pid_drop_packet(cstr->ipid);
2074 28989 : cstr->nb_pck++;
2075 :
2076 28989 : if (e) return e;
2077 : }
2078 29680 : if (nb_eos==count) return GF_EOS;
2079 :
2080 29547 : return GF_OK;
2081 : }
2082 :
2083 130 : static GF_Err cenc_enc_initialize(GF_Filter *filter)
2084 : {
2085 130 : GF_CENCEncCtx *ctx = (GF_CENCEncCtx *)gf_filter_get_udta(filter);
2086 :
2087 130 : if (ctx->cfile) {
2088 : GF_Err e;
2089 130 : ctx->cinfo = gf_crypt_info_load(ctx->cfile, &e);
2090 130 : if (!ctx->cinfo) {
2091 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENCCrypt] Cannot load config file %s\n", ctx->cfile ));
2092 0 : return GF_BAD_PARAM;
2093 : }
2094 : }
2095 :
2096 130 : ctx->streams = gf_list_new();
2097 130 : return GF_OK;
2098 : }
2099 :
2100 130 : static void cenc_enc_finalize(GF_Filter *filter)
2101 : {
2102 130 : GF_CENCEncCtx *ctx = (GF_CENCEncCtx *)gf_filter_get_udta(filter);
2103 130 : if (ctx->cinfo) gf_crypt_info_del(ctx->cinfo);
2104 279 : while (gf_list_count(ctx->streams)) {
2105 149 : GF_CENCStream *s = gf_list_pop_back(ctx->streams);
2106 149 : cenc_free_pid_context(s);
2107 : }
2108 130 : gf_list_del(ctx->streams);
2109 130 : if (ctx->bs_w) gf_bs_del(ctx->bs_w);
2110 130 : if (ctx->bs_r) gf_bs_del(ctx->bs_r);
2111 130 : }
2112 :
2113 :
2114 : static const GF_FilterCapability CENCEncCaps[] =
2115 : {
2116 : CAP_UINT(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_STREAM_TYPE, GF_STREAM_ENCRYPTED),
2117 : CAP_UINT(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
2118 : CAP_UINT(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_CODECID, GF_CODECID_RAW),
2119 : CAP_UINT(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_UNFRAMED, GF_TRUE),
2120 :
2121 : CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_ENCRYPTED),
2122 : CAP_UINT(GF_CAPS_OUTPUT_EXCLUDED, GF_PROP_PID_CODECID, GF_CODECID_RAW),
2123 : // CAP_UINT(GF_CAPS_OUTPUT_STATIC_EXCLUDED, GF_PROP_PID_UNFRAMED, GF_TRUE),
2124 : };
2125 :
2126 : #define OFFS(_n) #_n, offsetof(GF_CENCEncCtx, _n)
2127 : static const GF_FilterArgs GF_CENCEncArgs[] =
2128 : {
2129 : { OFFS(cfile), "crypt file location - see filter help", GF_PROP_STRING, NULL, NULL, 0},
2130 : { OFFS(allc), "throw error if no DRM config file is found for a PID - see filter help", GF_PROP_STRING, NULL, NULL, 0},
2131 : {0}
2132 : };
2133 :
2134 : GF_FilterRegister CENCEncRegister = {
2135 : .name = "cecrypt",
2136 : GF_FS_SET_DESCRIPTION("CENC encryptor")
2137 : GF_FS_SET_HELP("The CENC encryptor supports CENC, ISMA and Adobe encryption. It uses a DRM config file for declaring keys.\n"
2138 : "The syntax is available at https://wiki.gpac.io/Common-Encryption\n"
2139 : "The DRM config file can be set per PID using the property `CryptInfo`, or set at the filter level using [-cfile]().\n"
2140 : "When the DRM config file is set per PID, the first `CrypTrack` in the DRM config file with the same ID is used, otherwise the first `CrypTrack` is used.\n"
2141 : "If no DRM config file is defined for a given PID, this PID will not be encrypted, or an error will be thrown if [-allc]() is specified.\n"
2142 : )
2143 : .private_size = sizeof(GF_CENCEncCtx),
2144 : .max_extra_pids=-1,
2145 : //encryptor shall be explicitly loaded
2146 : .flags = GF_FS_REG_EXPLICIT_ONLY,
2147 : .args = GF_CENCEncArgs,
2148 : SETCAPS(CENCEncCaps),
2149 : .configure_pid = cenc_enc_configure_pid,
2150 : .initialize = cenc_enc_initialize,
2151 : .finalize = cenc_enc_finalize,
2152 : .process = cenc_enc_process
2153 :
2154 : };
2155 :
2156 : #endif /*GPAC_DISABLE_CRYPTO*/
2157 :
2158 2877 : const GF_FilterRegister *cenc_encrypt_register(GF_FilterSession *session)
2159 : {
2160 : #ifndef GPAC_DISABLE_CRYPTO
2161 2877 : return &CENCEncRegister;
2162 : #else
2163 : return NULL;
2164 : #endif
2165 : }
|