|
|
|
@@ -6198,6 +6198,114 @@ static int mov_read_saio(MOVContext *c, AVIOContext *pb, MOVAtom atom) |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int mov_read_pssh(MOVContext *c, AVIOContext *pb, MOVAtom atom) |
|
|
|
{ |
|
|
|
AVEncryptionInitInfo *info, *old_init_info; |
|
|
|
uint8_t **key_ids; |
|
|
|
AVStream *st; |
|
|
|
uint8_t *side_data, *extra_data, *old_side_data; |
|
|
|
size_t side_data_size; |
|
|
|
int ret = 0, old_side_data_size; |
|
|
|
unsigned int version, kid_count, extra_data_size, alloc_size = 0; |
|
|
|
|
|
|
|
if (c->fc->nb_streams < 1) |
|
|
|
return 0; |
|
|
|
st = c->fc->streams[c->fc->nb_streams-1]; |
|
|
|
|
|
|
|
version = avio_r8(pb); /* version */ |
|
|
|
avio_rb24(pb); /* flags */ |
|
|
|
|
|
|
|
info = av_encryption_init_info_alloc(/* system_id_size */ 16, /* num_key_ids */ 0, |
|
|
|
/* key_id_size */ 16, /* data_size */ 0); |
|
|
|
if (!info) |
|
|
|
return AVERROR(ENOMEM); |
|
|
|
|
|
|
|
if (avio_read(pb, info->system_id, 16) != 16) { |
|
|
|
av_log(c->fc, AV_LOG_ERROR, "Failed to read the system id\n"); |
|
|
|
ret = AVERROR_INVALIDDATA; |
|
|
|
goto finish; |
|
|
|
} |
|
|
|
|
|
|
|
if (version > 0) { |
|
|
|
kid_count = avio_rb32(pb); |
|
|
|
if (kid_count >= INT_MAX / sizeof(*key_ids)) |
|
|
|
return AVERROR(ENOMEM); |
|
|
|
|
|
|
|
for (unsigned int i = 0; i < kid_count && !pb->eof_reached; i++) { |
|
|
|
unsigned int min_kid_count = FFMIN(FFMAX(i + 1, 1024), kid_count); |
|
|
|
key_ids = av_fast_realloc(info->key_ids, &alloc_size, |
|
|
|
min_kid_count * sizeof(*key_ids)); |
|
|
|
if (!key_ids) { |
|
|
|
ret = AVERROR(ENOMEM); |
|
|
|
goto finish; |
|
|
|
} |
|
|
|
info->key_ids = key_ids; |
|
|
|
|
|
|
|
info->key_ids[i] = av_mallocz(16); |
|
|
|
if (!info->key_ids[i]) { |
|
|
|
ret = AVERROR(ENOMEM); |
|
|
|
goto finish; |
|
|
|
} |
|
|
|
info->num_key_ids = i + 1; |
|
|
|
|
|
|
|
if (avio_read(pb, info->key_ids[i], 16) != 16) { |
|
|
|
av_log(c->fc, AV_LOG_ERROR, "Failed to read the key id\n"); |
|
|
|
ret = AVERROR_INVALIDDATA; |
|
|
|
goto finish; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (pb->eof_reached) { |
|
|
|
av_log(c->fc, AV_LOG_ERROR, "Hit EOF while reading pssh\n"); |
|
|
|
ret = AVERROR_INVALIDDATA; |
|
|
|
goto finish; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
extra_data_size = avio_rb32(pb); |
|
|
|
ret = mov_try_read_block(pb, extra_data_size, &extra_data); |
|
|
|
if (ret < 0) |
|
|
|
goto finish; |
|
|
|
|
|
|
|
av_freep(&info->data); // malloc(0) may still allocate something. |
|
|
|
info->data = extra_data; |
|
|
|
info->data_size = extra_data_size; |
|
|
|
|
|
|
|
// If there is existing initialization data, append to the list. |
|
|
|
old_side_data = av_stream_get_side_data(st, AV_PKT_DATA_ENCRYPTION_INIT_INFO, &old_side_data_size); |
|
|
|
if (old_side_data) { |
|
|
|
old_init_info = av_encryption_init_info_get_side_data(old_side_data, old_side_data_size); |
|
|
|
if (old_init_info) { |
|
|
|
// Append to the end of the list. |
|
|
|
for (AVEncryptionInitInfo *cur = old_init_info;; cur = cur->next) { |
|
|
|
if (!cur->next) { |
|
|
|
cur->next = info; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
info = old_init_info; |
|
|
|
} else { |
|
|
|
// Assume existing side-data will be valid, so the only error we could get is OOM. |
|
|
|
ret = AVERROR(ENOMEM); |
|
|
|
goto finish; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
side_data = av_encryption_init_info_add_side_data(info, &side_data_size); |
|
|
|
if (!side_data) { |
|
|
|
ret = AVERROR(ENOMEM); |
|
|
|
goto finish; |
|
|
|
} |
|
|
|
ret = av_stream_add_side_data(st, AV_PKT_DATA_ENCRYPTION_INIT_INFO, |
|
|
|
side_data, side_data_size); |
|
|
|
if (ret < 0) |
|
|
|
av_free(side_data); |
|
|
|
|
|
|
|
finish: |
|
|
|
av_encryption_init_info_free(info); |
|
|
|
return ret; |
|
|
|
} |
|
|
|
|
|
|
|
static int mov_read_schm(MOVContext *c, AVIOContext *pb, MOVAtom atom) |
|
|
|
{ |
|
|
|
AVStream *st; |
|
|
|
@@ -6398,7 +6506,7 @@ static int cenc_filter(MOVContext *mov, MOVStreamContext *sc, AVPacket *pkt, int |
|
|
|
MOVFragmentStreamInfo *frag_stream_info; |
|
|
|
MOVEncryptionIndex *encryption_index; |
|
|
|
AVEncryptionInfo *encrypted_sample; |
|
|
|
int encrypted_index; |
|
|
|
int encrypted_index, ret; |
|
|
|
|
|
|
|
frag_stream_info = get_current_frag_stream_info(&mov->frag_index); |
|
|
|
encrypted_index = current_index; |
|
|
|
@@ -6442,6 +6550,15 @@ static int cenc_filter(MOVContext *mov, MOVStreamContext *sc, AVPacket *pkt, int |
|
|
|
|
|
|
|
if (mov->decryption_key) { |
|
|
|
return cenc_decrypt(mov, sc, encrypted_sample, pkt->data, pkt->size); |
|
|
|
} else { |
|
|
|
size_t size; |
|
|
|
uint8_t *side_data = av_encryption_info_add_side_data(encrypted_sample, &size); |
|
|
|
if (!side_data) |
|
|
|
return AVERROR(ENOMEM); |
|
|
|
ret = av_packet_add_side_data(pkt, AV_PKT_DATA_ENCRYPTION_INFO, side_data, size); |
|
|
|
if (ret < 0) |
|
|
|
av_free(side_data); |
|
|
|
return ret; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@@ -6575,6 +6692,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = { |
|
|
|
{ MKTAG('s','e','n','c'), mov_read_senc }, |
|
|
|
{ MKTAG('s','a','i','z'), mov_read_saiz }, |
|
|
|
{ MKTAG('s','a','i','o'), mov_read_saio }, |
|
|
|
{ MKTAG('p','s','s','h'), mov_read_pssh }, |
|
|
|
{ MKTAG('s','c','h','m'), mov_read_schm }, |
|
|
|
{ MKTAG('s','c','h','i'), mov_read_default }, |
|
|
|
{ MKTAG('t','e','n','c'), mov_read_tenc }, |
|
|
|
|