summaryrefslogtreecommitdiffstats
path: root/libavutil
diff options
context:
space:
mode:
authorJacob Trimble <modmaker@google.com>2018-04-23 10:33:58 -0700
committerMichael Niedermayer <michael@niedermayer.cc>2018-06-23 01:06:29 +0200
commitb86c5757a2bf2a589b3982d6b85401165deb4958 (patch)
treed50ac7414405af0bef424201b2f0ee5cfad11960 /libavutil
parenta790813739a880a0a86084ec8c4e2d5a6a79c11d (diff)
downloadffmpeg-streaming-b86c5757a2bf2a589b3982d6b85401165deb4958.zip
ffmpeg-streaming-b86c5757a2bf2a589b3982d6b85401165deb4958.tar.gz
libavutil/encryption_info: Allow multiple init info.
It is possible for there to be multiple encryption init info structure. For example, to support multiple key systems or in key rotation. This changes the AVEncryptionInitInfo struct to be a linked list so there can be multiple structs without breaking ABI. Signed-off-by: Jacob Trimble <modmaker@google.com> Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
Diffstat (limited to 'libavutil')
-rw-r--r--libavutil/encryption_info.c146
-rw-r--r--libavutil/encryption_info.h5
2 files changed, 100 insertions, 51 deletions
diff --git a/libavutil/encryption_info.c b/libavutil/encryption_info.c
index 20a752d..3b7e16c 100644
--- a/libavutil/encryption_info.c
+++ b/libavutil/encryption_info.c
@@ -160,13 +160,16 @@ uint8_t *av_encryption_info_add_side_data(const AVEncryptionInfo *info, size_t *
}
// The format of the AVEncryptionInitInfo side data:
-// u32be system_id_size
-// u32be num_key_ids
-// u32be key_id_size
-// u32be data_size
-// u8[system_id_size] system_id
-// u8[key_id_size][num_key_id] key_ids
-// u8[data_size] data
+// u32be init_info_count
+// {
+// u32be system_id_size
+// u32be num_key_ids
+// u32be key_id_size
+// u32be data_size
+// u8[system_id_size] system_id
+// u8[key_id_size][num_key_id] key_ids
+// u8[data_size] data
+// }[init_info_count]
#define FF_ENCRYPTION_INIT_INFO_EXTRA 16
@@ -215,6 +218,7 @@ void av_encryption_init_info_free(AVEncryptionInitInfo *info)
for (i = 0; i < info->num_key_ids; i++) {
av_free(info->key_ids[i]);
}
+ av_encryption_init_info_free(info->next);
av_free(info->system_id);
av_free(info->key_ids);
av_free(info->data);
@@ -225,71 +229,111 @@ void av_encryption_init_info_free(AVEncryptionInitInfo *info)
AVEncryptionInitInfo *av_encryption_init_info_get_side_data(
const uint8_t *side_data, size_t side_data_size)
{
- AVEncryptionInitInfo *info;
- uint64_t system_id_size, num_key_ids, key_id_size, data_size, i;
+ // |ret| tracks the front of the list, |info| tracks the back.
+ AVEncryptionInitInfo *ret = NULL, *info, *temp_info;
+ uint64_t system_id_size, num_key_ids, key_id_size, data_size, i, j;
+ uint64_t init_info_count;
- if (!side_data || side_data_size < FF_ENCRYPTION_INIT_INFO_EXTRA)
+ if (!side_data || side_data_size < 4)
return NULL;
- system_id_size = AV_RB32(side_data);
- num_key_ids = AV_RB32(side_data + 4);
- key_id_size = AV_RB32(side_data + 8);
- data_size = AV_RB32(side_data + 12);
+ init_info_count = AV_RB32(side_data);
+ side_data += 4;
+ side_data_size -= 4;
+ for (i = 0; i < init_info_count; i++) {
+ if (side_data_size < FF_ENCRYPTION_INIT_INFO_EXTRA) {
+ av_encryption_init_info_free(ret);
+ return NULL;
+ }
- // UINT32_MAX + UINT32_MAX + UINT32_MAX * UINT32_MAX == UINT64_MAX
- if (side_data_size - FF_ENCRYPTION_INIT_INFO_EXTRA < system_id_size + data_size + num_key_ids * key_id_size)
- return NULL;
+ system_id_size = AV_RB32(side_data);
+ num_key_ids = AV_RB32(side_data + 4);
+ key_id_size = AV_RB32(side_data + 8);
+ data_size = AV_RB32(side_data + 12);
- info = av_encryption_init_info_alloc(system_id_size, num_key_ids, key_id_size, data_size);
- if (!info)
- return NULL;
+ // UINT32_MAX + UINT32_MAX + UINT32_MAX * UINT32_MAX == UINT64_MAX
+ if (side_data_size - FF_ENCRYPTION_INIT_INFO_EXTRA < system_id_size + data_size + num_key_ids * key_id_size) {
+ av_encryption_init_info_free(ret);
+ return NULL;
+ }
+ side_data += FF_ENCRYPTION_INIT_INFO_EXTRA;
+ side_data_size -= FF_ENCRYPTION_INIT_INFO_EXTRA;
+
+ temp_info = av_encryption_init_info_alloc(system_id_size, num_key_ids, key_id_size, data_size);
+ if (!temp_info) {
+ av_encryption_init_info_free(ret);
+ return NULL;
+ }
+ if (i == 0) {
+ info = ret = temp_info;
+ } else {
+ info->next = temp_info;
+ info = temp_info;
+ }
- memcpy(info->system_id, side_data + 16, system_id_size);
- side_data += system_id_size + 16;
- for (i = 0; i < num_key_ids; i++) {
- memcpy(info->key_ids[i], side_data, key_id_size);
- side_data += key_id_size;
+ memcpy(info->system_id, side_data, system_id_size);
+ side_data += system_id_size;
+ side_data_size -= system_id_size;
+ for (j = 0; j < num_key_ids; j++) {
+ memcpy(info->key_ids[j], side_data, key_id_size);
+ side_data += key_id_size;
+ side_data_size -= key_id_size;
+ }
+ memcpy(info->data, side_data, data_size);
+ side_data += data_size;
+ side_data_size -= data_size;
}
- memcpy(info->data, side_data, data_size);
- return info;
+ return ret;
}
uint8_t *av_encryption_init_info_add_side_data(const AVEncryptionInitInfo *info, size_t *side_data_size)
{
+ const AVEncryptionInitInfo *cur_info;
uint8_t *buffer, *cur_buffer;
- uint32_t i, max_size;
-
- if (UINT32_MAX - FF_ENCRYPTION_INIT_INFO_EXTRA < info->system_id_size ||
- UINT32_MAX - FF_ENCRYPTION_INIT_INFO_EXTRA - info->system_id_size < info->data_size) {
- return NULL;
- }
-
- if (info->num_key_ids) {
- max_size = UINT32_MAX - FF_ENCRYPTION_INIT_INFO_EXTRA - info->system_id_size - info->data_size;
- if (max_size / info->num_key_ids < info->key_id_size)
+ uint32_t i, init_info_count;
+ uint64_t temp_side_data_size;
+
+ temp_side_data_size = 4;
+ init_info_count = 0;
+ for (cur_info = info; cur_info; cur_info = cur_info->next) {
+ temp_side_data_size += (uint64_t)FF_ENCRYPTION_INIT_INFO_EXTRA + info->system_id_size + info->data_size;
+ if (init_info_count == UINT32_MAX || temp_side_data_size > UINT32_MAX) {
return NULL;
+ }
+ init_info_count++;
+
+ if (info->num_key_ids) {
+ temp_side_data_size += (uint64_t)info->num_key_ids * info->key_id_size;
+ if (temp_side_data_size > UINT32_MAX) {
+ return NULL;
+ }
+ }
}
+ *side_data_size = temp_side_data_size;
- *side_data_size = FF_ENCRYPTION_INIT_INFO_EXTRA + info->system_id_size +
- info->data_size + (info->num_key_ids * info->key_id_size);
cur_buffer = buffer = av_malloc(*side_data_size);
if (!buffer)
return NULL;
- AV_WB32(cur_buffer, info->system_id_size);
- AV_WB32(cur_buffer + 4, info->num_key_ids);
- AV_WB32(cur_buffer + 8, info->key_id_size);
- AV_WB32(cur_buffer + 12, info->data_size);
- cur_buffer += 16;
-
- memcpy(cur_buffer, info->system_id, info->system_id_size);
- cur_buffer += info->system_id_size;
- for (i = 0; i < info->num_key_ids; i++) {
- memcpy(cur_buffer, info->key_ids[i], info->key_id_size);
- cur_buffer += info->key_id_size;
+ AV_WB32(cur_buffer, init_info_count);
+ cur_buffer += 4;
+ for (cur_info = info; cur_info; cur_info = cur_info->next) {
+ AV_WB32(cur_buffer, cur_info->system_id_size);
+ AV_WB32(cur_buffer + 4, cur_info->num_key_ids);
+ AV_WB32(cur_buffer + 8, cur_info->key_id_size);
+ AV_WB32(cur_buffer + 12, cur_info->data_size);
+ cur_buffer += 16;
+
+ memcpy(cur_buffer, cur_info->system_id, cur_info->system_id_size);
+ cur_buffer += cur_info->system_id_size;
+ for (i = 0; i < cur_info->num_key_ids; i++) {
+ memcpy(cur_buffer, cur_info->key_ids[i], cur_info->key_id_size);
+ cur_buffer += cur_info->key_id_size;
+ }
+ memcpy(cur_buffer, cur_info->data, cur_info->data_size);
+ cur_buffer += cur_info->data_size;
}
- memcpy(cur_buffer, info->data, info->data_size);
return buffer;
}
diff --git a/libavutil/encryption_info.h b/libavutil/encryption_info.h
index ec5501a..9140968 100644
--- a/libavutil/encryption_info.h
+++ b/libavutil/encryption_info.h
@@ -115,6 +115,11 @@ typedef struct AVEncryptionInitInfo {
*/
uint8_t* data;
uint32_t data_size;
+
+ /**
+ * An optional pointer to the next initialization info in the list.
+ */
+ struct AVEncryptionInitInfo *next;
} AVEncryptionInitInfo;
/**
OpenPOWER on IntegriCloud