This new side-data will contain info on how a packet is encrypted. This allows the app to handle packet decryption. Signed-off-by: Jacob Trimble <modmaker@google.com> Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>tags/n4.0
@@ -15,6 +15,10 @@ libavutil: 2017-10-21 | |||
API changes, most recent first: | |||
2018-xx-xx - xxxxxxx - lavu 56.8.100 - encryption_info.h | |||
Add AVEncryptionInitInfo and AVEncryptionInfo structures to hold new side-data | |||
for encryption info. | |||
2018-03-21 - xxxxxxx - lavc 58.15.100 - avcodec.h | |||
Add av_packet_make_writable(). | |||
@@ -1344,6 +1344,19 @@ enum AVPacketSideDataType { | |||
*/ | |||
AV_PKT_DATA_A53_CC, | |||
/** | |||
* This side data is encryption initialization data. | |||
* The format is not part of ABI, use av_encryption_init_info_* methods to | |||
* access. | |||
*/ | |||
AV_PKT_DATA_ENCRYPTION_INIT_INFO, | |||
/** | |||
* This side data contains encryption info for how to decrypt the packet. | |||
* The format is not part of ABI, use av_encryption_info_* methods to access. | |||
*/ | |||
AV_PKT_DATA_ENCRYPTION_INFO, | |||
/** | |||
* The number of side data types. | |||
* This is not part of the public API/ABI in the sense that it may | |||
@@ -24,6 +24,7 @@ HEADERS = adler32.h \ | |||
dict.h \ | |||
display.h \ | |||
downmix_info.h \ | |||
encryption_info.h \ | |||
error.h \ | |||
eval.h \ | |||
fifo.h \ | |||
@@ -107,6 +108,7 @@ OBJS = adler32.o \ | |||
dict.o \ | |||
display.o \ | |||
downmix_info.o \ | |||
encryption_info.o \ | |||
error.o \ | |||
eval.o \ | |||
fifo.o \ | |||
@@ -0,0 +1,295 @@ | |||
/** | |||
* This file is part of FFmpeg. | |||
* | |||
* FFmpeg is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 2.1 of the License, or (at your option) any later version. | |||
* | |||
* FFmpeg is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public | |||
* License along with FFmpeg; if not, write to the Free Software | |||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
*/ | |||
#include "encryption_info.h" | |||
#include "mem.h" | |||
#include "intreadwrite.h" | |||
#define FF_ENCRYPTION_INFO_EXTRA 24 | |||
// The format of the AVEncryptionInfo side data: | |||
// u32be scheme | |||
// u32be crypt_byte_block | |||
// u32be skip_byte_block | |||
// u32be key_id_size | |||
// u32be iv_size | |||
// u32be subsample_count | |||
// u8[key_id_size] key_id | |||
// u8[iv_size] iv | |||
// { | |||
// u32be bytes_of_clear_data | |||
// u32be bytes_of_protected_data | |||
// }[subsample_count] | |||
AVEncryptionInfo *av_encryption_info_alloc(uint32_t subsample_count, uint32_t key_id_size, uint32_t iv_size) | |||
{ | |||
AVEncryptionInfo *info; | |||
info = av_mallocz(sizeof(*info)); | |||
if (!info) | |||
return NULL; | |||
info->key_id = av_mallocz(key_id_size); | |||
info->key_id_size = key_id_size; | |||
info->iv = av_mallocz(iv_size); | |||
info->iv_size = iv_size; | |||
info->subsamples = av_mallocz_array(subsample_count, sizeof(*info->subsamples)); | |||
info->subsample_count = subsample_count; | |||
// Allow info->subsamples to be NULL if there are no subsamples. | |||
if (!info->key_id || !info->iv || (!info->subsamples && subsample_count)) { | |||
av_encryption_info_free(info); | |||
return NULL; | |||
} | |||
return info; | |||
} | |||
AVEncryptionInfo *av_encryption_info_clone(const AVEncryptionInfo *info) | |||
{ | |||
AVEncryptionInfo *ret; | |||
ret = av_encryption_info_alloc(info->subsample_count, info->key_id_size, info->iv_size); | |||
if (!ret) | |||
return NULL; | |||
ret->scheme = info->scheme; | |||
ret->crypt_byte_block = info->crypt_byte_block; | |||
ret->skip_byte_block = info->skip_byte_block; | |||
memcpy(ret->iv, info->iv, info->iv_size); | |||
memcpy(ret->key_id, info->key_id, info->key_id_size); | |||
memcpy(ret->subsamples, info->subsamples, sizeof(*info->subsamples) * info->subsample_count); | |||
return ret; | |||
} | |||
void av_encryption_info_free(AVEncryptionInfo *info) | |||
{ | |||
if (info) { | |||
av_free(info->key_id); | |||
av_free(info->iv); | |||
av_free(info->subsamples); | |||
av_free(info); | |||
} | |||
} | |||
AVEncryptionInfo *av_encryption_info_get_side_data(const uint8_t* buffer, size_t size) | |||
{ | |||
AVEncryptionInfo *info; | |||
uint64_t key_id_size, iv_size, subsample_count, i; | |||
if (!buffer || size < FF_ENCRYPTION_INFO_EXTRA) | |||
return NULL; | |||
key_id_size = AV_RB32(buffer + 12); | |||
iv_size = AV_RB32(buffer + 16); | |||
subsample_count = AV_RB32(buffer + 20); | |||
if (size < FF_ENCRYPTION_INFO_EXTRA + key_id_size + iv_size + subsample_count * 8) | |||
return NULL; | |||
info = av_encryption_info_alloc(subsample_count, key_id_size, iv_size); | |||
if (!info) | |||
return NULL; | |||
info->scheme = AV_RB32(buffer); | |||
info->crypt_byte_block = AV_RB32(buffer + 4); | |||
info->skip_byte_block = AV_RB32(buffer + 8); | |||
memcpy(info->key_id, buffer + 24, key_id_size); | |||
memcpy(info->iv, buffer + key_id_size + 24, iv_size); | |||
buffer += key_id_size + iv_size + 24; | |||
for (i = 0; i < subsample_count; i++) { | |||
info->subsamples[i].bytes_of_clear_data = AV_RB32(buffer); | |||
info->subsamples[i].bytes_of_protected_data = AV_RB32(buffer + 4); | |||
buffer += 8; | |||
} | |||
return info; | |||
} | |||
uint8_t *av_encryption_info_add_side_data(const AVEncryptionInfo *info, size_t *size) | |||
{ | |||
uint8_t *buffer, *cur_buffer; | |||
uint32_t i; | |||
if (UINT32_MAX - FF_ENCRYPTION_INFO_EXTRA < info->key_id_size || | |||
UINT32_MAX - FF_ENCRYPTION_INFO_EXTRA - info->key_id_size < info->iv_size || | |||
(UINT32_MAX - FF_ENCRYPTION_INFO_EXTRA - info->key_id_size - info->iv_size) / 8 < info->subsample_count) { | |||
return NULL; | |||
} | |||
*size = FF_ENCRYPTION_INFO_EXTRA + info->key_id_size + info->iv_size + | |||
(info->subsample_count * 8); | |||
cur_buffer = buffer = av_malloc(*size); | |||
if (!buffer) | |||
return NULL; | |||
AV_WB32(cur_buffer, info->scheme); | |||
AV_WB32(cur_buffer + 4, info->crypt_byte_block); | |||
AV_WB32(cur_buffer + 8, info->skip_byte_block); | |||
AV_WB32(cur_buffer + 12, info->key_id_size); | |||
AV_WB32(cur_buffer + 16, info->iv_size); | |||
AV_WB32(cur_buffer + 20, info->subsample_count); | |||
cur_buffer += 24; | |||
memcpy(cur_buffer, info->key_id, info->key_id_size); | |||
cur_buffer += info->key_id_size; | |||
memcpy(cur_buffer, info->iv, info->iv_size); | |||
cur_buffer += info->iv_size; | |||
for (i = 0; i < info->subsample_count; i++) { | |||
AV_WB32(cur_buffer, info->subsamples[i].bytes_of_clear_data); | |||
AV_WB32(cur_buffer + 4, info->subsamples[i].bytes_of_protected_data); | |||
cur_buffer += 8; | |||
} | |||
return buffer; | |||
} | |||
// 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 | |||
#define FF_ENCRYPTION_INIT_INFO_EXTRA 16 | |||
AVEncryptionInitInfo *av_encryption_init_info_alloc( | |||
uint32_t system_id_size, uint32_t num_key_ids, uint32_t key_id_size, uint32_t data_size) | |||
{ | |||
AVEncryptionInitInfo *info; | |||
uint32_t i; | |||
info = av_mallocz(sizeof(*info)); | |||
if (!info) | |||
return NULL; | |||
info->system_id = av_mallocz(system_id_size); | |||
info->system_id_size = system_id_size; | |||
info->key_ids = key_id_size ? av_mallocz_array(num_key_ids, sizeof(*info->key_ids)) : NULL; | |||
info->num_key_ids = num_key_ids; | |||
info->key_id_size = key_id_size; | |||
info->data = av_mallocz(data_size); | |||
info->data_size = data_size; | |||
// Allow pointers to be NULL if the size is 0. | |||
if ((!info->system_id && system_id_size) || (!info->data && data_size) || | |||
(!info->key_ids && num_key_ids && key_id_size)) { | |||
av_encryption_init_info_free(info); | |||
return NULL; | |||
} | |||
if (key_id_size) { | |||
for (i = 0; i < num_key_ids; i++) { | |||
info->key_ids[i] = av_mallocz(key_id_size); | |||
if (!info->key_ids[i]) { | |||
av_encryption_init_info_free(info); | |||
return NULL; | |||
} | |||
} | |||
} | |||
return info; | |||
} | |||
void av_encryption_init_info_free(AVEncryptionInitInfo *info) | |||
{ | |||
uint32_t i; | |||
if (info) { | |||
for (i = 0; i < info->num_key_ids; i++) { | |||
av_free(info->key_ids[i]); | |||
} | |||
av_free(info->system_id); | |||
av_free(info->key_ids); | |||
av_free(info->data); | |||
av_free(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; | |||
if (!side_data || side_data_size < FF_ENCRYPTION_INIT_INFO_EXTRA) | |||
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); | |||
// 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; | |||
info = av_encryption_init_info_alloc(system_id_size, num_key_ids, key_id_size, data_size); | |||
if (!info) | |||
return NULL; | |||
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->data, side_data, data_size); | |||
return info; | |||
} | |||
uint8_t *av_encryption_init_info_add_side_data(const AVEncryptionInitInfo *info, size_t *side_data_size) | |||
{ | |||
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) | |||
return NULL; | |||
} | |||
*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; | |||
} | |||
memcpy(cur_buffer, info->data, info->data_size); | |||
return buffer; | |||
} |
@@ -0,0 +1,200 @@ | |||
/** | |||
* This file is part of FFmpeg. | |||
* | |||
* FFmpeg is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 2.1 of the License, or (at your option) any later version. | |||
* | |||
* FFmpeg is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public | |||
* License along with FFmpeg; if not, write to the Free Software | |||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
*/ | |||
#ifndef AVUTIL_ENCRYPTION_INFO_H | |||
#define AVUTIL_ENCRYPTION_INFO_H | |||
#include <stddef.h> | |||
#include <stdint.h> | |||
typedef struct AVSubsampleEncryptionInfo { | |||
/** The number of bytes that are clear. */ | |||
unsigned int bytes_of_clear_data; | |||
/** | |||
* The number of bytes that are protected. If using pattern encryption, | |||
* the pattern applies to only the protected bytes; if not using pattern | |||
* encryption, all these bytes are encrypted. | |||
*/ | |||
unsigned int bytes_of_protected_data; | |||
} AVSubsampleEncryptionInfo; | |||
/** | |||
* This describes encryption info for a packet. This contains frame-specific | |||
* info for how to decrypt the packet before passing it to the decoder. | |||
* | |||
* The size of this struct is not part of the public ABI. | |||
*/ | |||
typedef struct AVEncryptionInfo { | |||
/** The fourcc encryption scheme. */ | |||
uint32_t scheme; | |||
/** | |||
* Only used for pattern encryption. This is the number of 16-byte blocks | |||
* that are encrypted. | |||
*/ | |||
uint32_t crypt_byte_block; | |||
/** | |||
* Only used for pattern encryption. This is the number of 16-byte blocks | |||
* that are clear. | |||
*/ | |||
uint32_t skip_byte_block; | |||
/** | |||
* The ID of the key used to encrypt the packet. This should always be | |||
* 16 bytes long, but may be changed in the future. | |||
*/ | |||
uint8_t *key_id; | |||
uint32_t key_id_size; | |||
/** | |||
* The initialization vector. This may have been zero-filled to be the | |||
* correct block size. This should always be 16 bytes long, but may be | |||
* changed in the future. | |||
*/ | |||
uint8_t *iv; | |||
uint32_t iv_size; | |||
/** | |||
* An array of subsample encryption info specifying how parts of the sample | |||
* are encrypted. If there are no subsamples, then the whole sample is | |||
* encrypted. | |||
*/ | |||
AVSubsampleEncryptionInfo *subsamples; | |||
uint32_t subsample_count; | |||
} AVEncryptionInfo; | |||
/** | |||
* This describes info used to initialize an encryption key system. | |||
* | |||
* The size of this struct is not part of the public ABI. | |||
*/ | |||
typedef struct AVEncryptionInitInfo { | |||
/** | |||
* A unique identifier for the key system this is for, can be NULL if it | |||
* is not known. This should always be 16 bytes, but may change in the | |||
* future. | |||
*/ | |||
uint8_t* system_id; | |||
uint32_t system_id_size; | |||
/** | |||
* An array of key IDs this initialization data is for. All IDs are the | |||
* same length. Can be NULL if there are no known key IDs. | |||
*/ | |||
uint8_t** key_ids; | |||
/** The number of key IDs. */ | |||
uint32_t num_key_ids; | |||
/** | |||
* The number of bytes in each key ID. This should always be 16, but may | |||
* change in the future. | |||
*/ | |||
uint32_t key_id_size; | |||
/** | |||
* Key-system specific initialization data. This data is copied directly | |||
* from the file and the format depends on the specific key system. This | |||
* can be NULL if there is no initialization data; in that case, there | |||
* will be at least one key ID. | |||
*/ | |||
uint8_t* data; | |||
uint32_t data_size; | |||
} AVEncryptionInitInfo; | |||
/** | |||
* Allocates an AVEncryptionInfo structure and sub-pointers to hold the given | |||
* number of subsamples. This will allocate pointers for the key ID, IV, | |||
* and subsample entries, set the size members, and zero-initialize the rest. | |||
* | |||
* @param subsample_count The number of subsamples. | |||
* @param key_id_size The number of bytes in the key ID, should be 16. | |||
* @param key_id_size The number of bytes in the IV, should be 16. | |||
* | |||
* @return The new AVEncryptionInfo structure, or NULL on error. | |||
*/ | |||
AVEncryptionInfo *av_encryption_info_alloc(uint32_t subsample_count, uint32_t key_id_size, uint32_t iv_size); | |||
/** | |||
* Allocates an AVEncryptionInfo structure with a copy of the given data. | |||
* @return The new AVEncryptionInfo structure, or NULL on error. | |||
*/ | |||
AVEncryptionInfo *av_encryption_info_clone(const AVEncryptionInfo *info); | |||
/** | |||
* Frees the given encryption info object. This MUST NOT be used to free the | |||
* side-data data pointer, that should use normal side-data methods. | |||
*/ | |||
void av_encryption_info_free(AVEncryptionInfo *info); | |||
/** | |||
* Creates a copy of the AVEncryptionInfo that is contained in the given side | |||
* data. The resulting object should be passed to av_encryption_info_free() | |||
* when done. | |||
* | |||
* @return The new AVEncryptionInfo structure, or NULL on error. | |||
*/ | |||
AVEncryptionInfo *av_encryption_info_get_side_data(const uint8_t *side_data, size_t side_data_size); | |||
/** | |||
* Allocates and initializes side data that holds a copy of the given encryption | |||
* info. The resulting pointer should be either freed using av_free or given | |||
* to av_packet_add_side_data(). | |||
* | |||
* @return The new side-data pointer, or NULL. | |||
*/ | |||
uint8_t *av_encryption_info_add_side_data( | |||
const AVEncryptionInfo *info, size_t *side_data_size); | |||
/** | |||
* Allocates an AVEncryptionInitInfo structure and sub-pointers to hold the | |||
* given sizes. This will allocate pointers and set all the fields. | |||
* | |||
* @return The new AVEncryptionInitInfo structure, or NULL on error. | |||
*/ | |||
AVEncryptionInitInfo *av_encryption_init_info_alloc( | |||
uint32_t system_id_size, uint32_t num_key_ids, uint32_t key_id_size, uint32_t data_size); | |||
/** | |||
* Frees the given encryption init info object. This MUST NOT be used to free | |||
* the side-data data pointer, that should use normal side-data methods. | |||
*/ | |||
void av_encryption_init_info_free(AVEncryptionInitInfo* info); | |||
/** | |||
* Creates a copy of the AVEncryptionInitInfo that is contained in the given | |||
* side data. The resulting object should be passed to | |||
* av_encryption_init_info_free() when done. | |||
* | |||
* @return The new AVEncryptionInitInfo structure, or NULL on error. | |||
*/ | |||
AVEncryptionInitInfo *av_encryption_init_info_get_side_data( | |||
const uint8_t* side_data, size_t side_data_size); | |||
/** | |||
* Allocates and initializes side data that holds a copy of the given encryption | |||
* init info. The resulting pointer should be either freed using av_free or | |||
* given to av_packet_add_side_data(). | |||
* | |||
* @return The new side-data pointer, or NULL. | |||
*/ | |||
uint8_t *av_encryption_init_info_add_side_data( | |||
const AVEncryptionInitInfo *info, size_t *side_data_size); | |||
#endif /* AVUTIL_ENCRYPTION_INFO_H */ |
@@ -79,7 +79,7 @@ | |||
*/ | |||
#define LIBAVUTIL_VERSION_MAJOR 56 | |||
#define LIBAVUTIL_VERSION_MINOR 11 | |||
#define LIBAVUTIL_VERSION_MINOR 12 | |||
#define LIBAVUTIL_VERSION_MICRO 100 | |||
#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ | |||