From patchwork Mon Jan 8 19:40:55 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacob Trimble X-Patchwork-Id: 7205 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.2.78.2 with SMTP id r2csp3035871jaa; Mon, 8 Jan 2018 11:41:07 -0800 (PST) X-Google-Smtp-Source: ACJfBotAVfbDRzXHeFmep1uG3FK1JDWz4Uo3fKPItvTzBpgrUjEpk7xnpWLpd3xt7vdP7jBp3FPz X-Received: by 10.28.234.155 with SMTP id g27mr9183960wmi.137.1515440467821; Mon, 08 Jan 2018 11:41:07 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1515440467; cv=none; d=google.com; s=arc-20160816; b=DH5YajUCxqfOf5IH4Px2300iOxUn+3DiV6OFmGxkmig25tr9gNAmD21CjgahlJAz3/ 2ClWF0XX5zrXAIRBtyGsbd/Eo5d6pB4hTHqQknjL6oVNIRkg1doVTaiB90XUeNpgQ5Nb ujP+0UClHzvkjLcB4lb9bNeA8MK8JdoHDgZtFX6KcYDXXb6qZ44xVFrD90aeokZamAbY 0LZ8WxjQHT0tMO8oJteqiSXETNSYti9LY5jMEjATdsQBPVighccboXmKrncXPgyc+sZx atV7V2YYhlPV2X/jwZ0VLxkQB0v53SJbvzFvWx+6aPETnsmCtT4LigIE2Q1pLlpksYoJ Q80g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence:subject:to :message-id:date:from:references:in-reply-to:mime-version :dkim-signature:delivered-to:arc-authentication-results; bh=MbMhnqbqCftlGVBcDM4FqBMPGbWmm4xo6rLx/KDdxdc=; b=QtzuO6Mug8PsOc5LcyQB3RxKRewgV5mLgKxNrq6EYZYTmltjdlF7Oa6wOmPxMFLlFH sRALyYRIAIaqMZUjWHMvg/QDiRvt6uhjXsAfaGS0PBdCj9s9Dnun8UC9Tzymm7oPQZWM pwULOtWakGPn0q6x5xaaTfDudBf1PSK0fWELG5F5ZEv3pcC8Mdbg9p5nuC6n26wuEcKV z+V8s8+qEhICLlUWNzpxIHbp+ueyXymjWQmRkRIr4sx1X7UaWWGSMVOqZ73Zw3pDm/cT R9OLEDynDPk7aV/kId3CrX6ulCzNldGg25rlGTMLGDkKyiMUlp42IwQu+e7MeHo2HNCm gDHg== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@google.com header.s=20161025 header.b=LcfPOd5/; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id j27si4207914wre.435.2018.01.08.11.41.07; Mon, 08 Jan 2018 11:41:07 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@google.com header.s=20161025 header.b=LcfPOd5/; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 9DACE689A5A; Mon, 8 Jan 2018 21:41:04 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-vk0-f51.google.com (mail-vk0-f51.google.com [209.85.213.51]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 5E2BE688398 for ; Mon, 8 Jan 2018 21:40:57 +0200 (EET) Received: by mail-vk0-f51.google.com with SMTP id j192so8023598vkc.1 for ; Mon, 08 Jan 2018 11:40:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=mime-version:in-reply-to:references:from:date:message-id:subject:to; bh=TKRt+NRsKBhJzrj5xjrkE5bc9fjfH7WlNRd5In/QEDc=; b=LcfPOd5/qIrH6nk9tn+qy8EDxFAbN1B/6HNiV542XcVZK7k0TDAHHH46e/TGCzNysn GUqXeBvDeNV1YqZVeb7AiANEQWBL0MFf6h3T263V46QhO4EuQAOZyHVyZt5ViT+X+Ghi JBMe3YrmcdNr7IlTIY876Ms8IGMD6N+jrSyfEcXJusnYJO7WyekCm0AlnLWI1ZZFQO5O asLgAjs7FnazRqduafHGUlQ84zQgE4c8jfIcSISisPPuqY5W1mgckoJqJZP1iu36cQgT eirJRZbQPilC/qDiLXVeSWd/KG4b4g5hI9+GbquQzUHTGeYe6AZy6MFPeUrqW8boEbgD vscg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to; bh=TKRt+NRsKBhJzrj5xjrkE5bc9fjfH7WlNRd5In/QEDc=; b=Css+oGcmo5CHYrdXzunIaAmGbluML09vObM6NJr6t17eun7Kroqr30ZninXksUx3D/ FVUnI9R/ZNo6ESUuNSlApgNGqekk4LXgQLenytN+/Hr40R3bW+dALqD/HkTNpAZ0w2hL uYqkDu04gGay5Bc+B3EZh0vkCzZ4adb+vpXTaFnJ0h01rB8si26OantBJLkWtGEjd1go bMuk57he0HaRq2i6gBg7iishxLiTuK5hgyhgXmeJkIdbyoFtOTxfmiB0+3E0KdaklA23 2FrRZUmY0D8KZ0iJB8H4NqmLcdSukxj2+u4ldEPLoORv+z1cbeggDzS1FLw33TIj4fep XBww== X-Gm-Message-State: AKwxytcv1jRWxkZbI0MKe/QiMi70+JAjTYiI7fS1YGGNDRjZwjUGu+pt ooB69uX32OYvPG4Fu2ftuJJvAFh190NWgMHsVJPnw2pP X-Received: by 10.31.131.15 with SMTP id f15mr11146698vkd.58.1515440456542; Mon, 08 Jan 2018 11:40:56 -0800 (PST) MIME-Version: 1.0 Received: by 10.103.214.138 with HTTP; Mon, 8 Jan 2018 11:40:55 -0800 (PST) In-Reply-To: References: <20171219004433.GU4926@michaelspb> <20171220000504.492f1d33@debian> <20171220212355.4f349638@debian> <20171221013127.1a317177@debian> <20180105202741.1ec063d9@debian> <20180105223229.GY4926@michaelspb> From: Jacob Trimble Date: Mon, 8 Jan 2018 11:40:55 -0800 Message-ID: To: FFmpeg development discussions and patches Subject: Re: [FFmpeg-devel] [RFC] avcodec/avcodec.h: Add encryption info side data X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" > I'd assume we'd wait with applying this until the mp4 patch that uses > it is reviewed. I'm fine with this patch and I think it can be pushed > as it is, although I just noticed an APIchanges entry and minor version > bump is actually missing. You could add them when sending the final > patch set. Added APIchanges entry and version bump. > The format of teh side data should be choosen so that demuxers and encoders > producing it can interoperate with muxers and decoders consuming it. > Please correct me if iam wrong but if some containers can store more than > others, then the "other" containers would not use that extra information nor > set it but it could still be using a compatible representation for interoperability Well I guess I can do the same thing for this as for the frame-specific encryption info. There will be a user-friendly struct for accessing it and a binary format that will be stored in the side data. This will allow different (de)muxers to use the data in a generic way. > These should be checked against size, making sure the data is consistent Done. Also added addition overflow checking. On Fri, Jan 5, 2018 at 2:42 PM, James Almer wrote: > This being in libavutil, the two functions using AVPacket should be > changed to take and return a byte array instead, that the caller > manually either got from side data, or will afterwards adds as side data. Done. From 332f20f951fc4db77a83f9dc60f75e84717b4fd0 Mon Sep 17 00:00:00 2001 From: Jacob Trimble Date: Tue, 5 Dec 2017 14:52:22 -0800 Subject: [PATCH] avcodec/avcodec.h: Add encryption info side data. 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 --- doc/APIchanges | 4 + libavcodec/avcodec.h | 13 ++ libavutil/Makefile | 2 + libavutil/encryption_info.c | 295 ++++++++++++++++++++++++++++++++++++++++++++ libavutil/encryption_info.h | 200 ++++++++++++++++++++++++++++++ libavutil/version.h | 2 +- 6 files changed, 515 insertions(+), 1 deletion(-) create mode 100644 libavutil/encryption_info.c create mode 100644 libavutil/encryption_info.h diff --git a/doc/APIchanges b/doc/APIchanges index d66c842521..b771031740 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -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-01-xx - xxxxxxx - lavfi 7.11.101 - avfilter.h Deprecate avfilter_link_get_channels(). Use av_buffersink_get_channels(). diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index c13deb599f..cc74a9a740 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1341,6 +1341,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_DATA, + + /** + * 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 diff --git a/libavutil/Makefile b/libavutil/Makefile index d7474f59e4..760fce3b30 100644 --- a/libavutil/Makefile +++ b/libavutil/Makefile @@ -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 \ diff --git a/libavutil/encryption_info.c b/libavutil/encryption_info.c new file mode 100644 index 0000000000..f79a9cad5d --- /dev/null +++ b/libavutil/encryption_info.c @@ -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(AVEncryptionInfo)); + 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(AVSubsampleEncryptionInfo)); + 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(AVSubsampleEncryptionInfo) * 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(buffer, info->subsamples[i].bytes_of_clear_data); + AV_WB32(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(AVEncryptionInitInfo)); + 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); + 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; +} diff --git a/libavutil/encryption_info.h b/libavutil/encryption_info.h new file mode 100644 index 0000000000..47dc3a35ca --- /dev/null +++ b/libavutil/encryption_info.h @@ -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 +#include + +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 */ diff --git a/libavutil/version.h b/libavutil/version.h index d81ec6fa7b..d7398c41c5 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 56 -#define LIBAVUTIL_VERSION_MINOR 7 +#define LIBAVUTIL_VERSION_MINOR 8 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ -- 2.16.0.rc0.223.g4a4ac83678-goog