From patchwork Wed Dec 20 20:07:09 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacob Trimble X-Patchwork-Id: 6880 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.2.79.195 with SMTP id r64csp3382230jad; Wed, 20 Dec 2017 12:07:19 -0800 (PST) X-Google-Smtp-Source: ACJfBotmvqHr/BbmbcVGhHCsaCvPKJvxQiudoxBKvn8b9SQs+Dj+DvFquHxTD8/U85oqsuaZKUk2 X-Received: by 10.28.106.6 with SMTP id f6mr7361770wmc.111.1513800439851; Wed, 20 Dec 2017 12:07:19 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1513800439; cv=none; d=google.com; s=arc-20160816; b=W3af7H5bJqI7MfMUjTsBOQsZqtmUiKEaOBn8Y4tuMaiyXKEm9UmWyvdNE0Jvwhzxx6 zmQNQj3/8Th5vS2x1ieWcj/Z8w8rBn9O2OBSbni6pB/4oU0M6BsCNb9tTKpATjXAqUHh pG/eKYgpVTPWkKfLkAgGQxG0Q3ZAnicCOqsf9SUeX4ANqIlK2cx7/qpNME9baFDPKLSl Si9WFQFEXgbu7f8FfNsh/Gq5iTzZI0F/NDC0zMyfUZ9JNZTVlovS0OqKBRmCctH2Kykr Kvu4PWNf2asT3kpswqufsoD1M0yf0qjkOecY+diR2Sa65WtzCZJM4RRXXjR+ZnFoctb1 Mhrw== 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=kZBMVrj9RxBCJRlkJSZfUrYG7xZQPERfgTEDk+mOKQU=; b=jkq5k6efNnDyUQJ51JadZBbBk9piO/8sG8anc8kXW3NLibiAHytjoc/qdLEm3ZbPGT wbc4GpotQECJMkuvq/7J9O4ND8hZLdZnm8Oms7xaoc7kwbk3RnXjHAJ7ED2PZNCzijcE KZLoClOL1985nn3CW1OixiejKYEbP4mJLSX5PDYVC6wu5BgrHeUB1np1O6eC0PMrt7d7 OltBvufOZsQzz8tQV2RsF6g9viviaAJBz2/PW4D7Z60ToZ4fflezNrWquUQgGt/vqynf nTbVjvEfha6vIue3783+WVIdRAeymkWuQNYVBsRYSha8Jammk+zUYWqMFJUNxVlIEt41 ps3g== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@google.com header.s=20161025 header.b=CAvyDP/3; 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 u7si8606308wrc.235.2017.12.20.12.07.19; Wed, 20 Dec 2017 12:07:19 -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=CAvyDP/3; 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 980DE6808CD; Wed, 20 Dec 2017 22:07:07 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-vk0-f42.google.com (mail-vk0-f42.google.com [209.85.213.42]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 0851C68076D for ; Wed, 20 Dec 2017 22:07:01 +0200 (EET) Received: by mail-vk0-f42.google.com with SMTP id m15so14227533vkf.13 for ; Wed, 20 Dec 2017 12:07:12 -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=h+K0ZyMJ266HWRBKAo10+hV/xlBu9r0Tc9br7mZt1zQ=; b=CAvyDP/3M45jijK9LyLa2BGOqUwx+PlBtVwjPAa8okaOqvamv5WPyWjW+qRHIzrkE+ lZGq8KffgSw69bFsTK0334IIUSS+Dxd6auocPJnFYhiyEMxMIt1HvlmAQnE4wS980Gm9 /uvFYVrSpICcZN+qFpCZffBePjjtG98PXfNX5bmDwxJ+rqUZFpx0GvMnXewrGQXZfptX bbg7hApHh+yYhTPsKMKUTE9zN2e4FJabtwdLXKcx6Fd/pRyhE4RiI4jF+jUvHjWZWrSg uC+Vjg6ac2ek7jx0vccUbZ6D1cdH2c+slk/y/jIscy6g2Eltzd+lY5oGuzs8oS9pwY/0 3Uwg== 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=h+K0ZyMJ266HWRBKAo10+hV/xlBu9r0Tc9br7mZt1zQ=; b=qgnG83bXknKtWZSVEXP3/eXuh5GibbBXlV0KCNsizM4yNPYW1dSYct7IYFO6YIB0XL JJCpS4cQX5RNItvat5ingfZtK0U/FVLDhjhMyMqWCgzAVxqIwqpfgYjrqrCLHrDbtGFj T71bH3N9CvcLY285TzX3aRLNbCSfxCBlgiSo7CCR7T19L69XsrUmekOi1nL9ODIcS8sx 7y4iBFOYesyhwsM4iVcqtAmTGcrEMhxRkmO7MDxIzxiTWTB3eg3MhzgopazsurxNBtrT 9aPL+fMXjBGKec4Tfqldr+eiDeIX9OVWhlGwkjjHlbUGCgbp8z7SaLFfvXCaAKxcAWxv 4FqQ== X-Gm-Message-State: AKGB3mL5+iXnW7J9TI2GN6YQ+02mxCZk0Ed+3rnR6BkIDYkWX8OPlvD9 vHc8JZs028uXWlnjm7rLG/Iv09rrADuIr/Pgwm4MNAop X-Received: by 10.31.67.134 with SMTP id q128mr7842281vka.30.1513800430215; Wed, 20 Dec 2017 12:07:10 -0800 (PST) MIME-Version: 1.0 Received: by 10.103.214.138 with HTTP; Wed, 20 Dec 2017 12:07:09 -0800 (PST) In-Reply-To: <20171220000504.492f1d33@debian> References: <20171214225305.GA4926@michaelspb> <20171218205208.28057570@debian> <88005b78-3b8b-5f20-7d3d-2929cfd36e57@gmail.com> <20171218203824.GQ4926@michaelspb> <20171218220252.1be1bb1c@debian> <20171218211714.GR4926@michaelspb> <20171218222814.157dfd69@debian> <20171218230015.GS4926@michaelspb> <20171219004433.GU4926@michaelspb> <20171220000504.492f1d33@debian> From: Jacob Trimble Date: Wed, 20 Dec 2017 12:07:09 -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" On Tue, Dec 19, 2017 at 3:05 PM, wm4 wrote: > On Tue, 19 Dec 2017 14:20:38 -0800 > Jacob Trimble wrote: > >> > I don't think this is sane. So far, side data could simply be copied >> > with memcpy, and having pointers to non-static data in side data would >> > break this completely >> >> Then how about storing the data like it is now (the encryption info >> followed by the subsample array), but not have a pointer? Then there >> will be several helper methods to get the subsample array from the >> side-data. For example, >> av_encryption_info_get_subsamples(AVPacketEncryptionInfo*) or >> av_encryption_info_get_subsamples(AVPacket*) (since there will only be >> one instance of it). > > I guess that would work? Not particularly fond of the idea anyway. I > think the functions would probably work on the side data byte array, > maybe. I'm not fond of this either, but I can't think of a way to allow a dynamic number of elements while supporting memcpy and not requiring the app to "parse" the side-data. So here is may latest attempt. This has a binary format inside the side-data that allows memcpy to work, but there is a public struct that apps will interact with. There are two methods used to convert between the two so the app doesn't have to. Even though this is a binary format, it is not actually a wire format since the subsamples are stored as-is, so they are host byte ordered. Also, as Michael requested, this uses dynamic sized key ID and IV. From 38c480a470d7f107945180968a5db237c671f7d0 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 --- libavcodec/Makefile | 2 + libavcodec/avcodec.h | 13 ++++++ libavcodec/encryption_info.c | 70 +++++++++++++++++++++++++++++ libavcodec/encryption_info.h | 105 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 190 insertions(+) create mode 100644 libavcodec/encryption_info.c create mode 100644 libavcodec/encryption_info.h diff --git a/libavcodec/Makefile b/libavcodec/Makefile index ab7893f560..11ad642c6c 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -10,6 +10,7 @@ HEADERS = ac3_parser.h \ dirac.h \ dv_profile.h \ dxva2.h \ + encryption_info.h \ jni.h \ mediacodec.h \ qsv.h \ @@ -36,6 +37,7 @@ OBJS = ac3_parser.o \ dirac.o \ dv_profile.o \ encode.o \ + encryption_info.o \ imgconvert.o \ jni.o \ mathtables.o \ diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 5db6a81320..7a5bba2687 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1327,6 +1327,19 @@ enum AVPacketSideDataType { */ AV_PKT_DATA_A53_CC, + /** + * This side data is encryption "initialization data". + * For MP4 this is the entire 'pssh' box. + * For WebM this is the key ID. + */ + AV_PKT_DATA_ENCRYPTION_INIT_DATA, + + /** + * This side data contains encryption info for how to decrypt the packet. + * Use av_encryption_info_get to get the info out of this side data. + */ + 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/libavcodec/encryption_info.c b/libavcodec/encryption_info.c new file mode 100644 index 0000000000..a2c11fe213 --- /dev/null +++ b/libavcodec/encryption_info.c @@ -0,0 +1,70 @@ +/** + * 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 "libavutil/avassert.h" +#include "libavutil/intreadwrite.h" + +#define FF_ENCRYPTION_INFO_EXTRA 24 + +int av_encryption_info_get(const AVPacket* packet, AVEncryptionInfo* info) { + uint8_t *buffer; + + buffer = av_packet_get_side_data(packet, AV_PKT_DATA_ENCRYPTION_INFO, NULL); + if (!buffer) + return 0; + + info->scheme = AV_RB32(buffer); + info->crypt_byte_block = AV_RB32(buffer + 4); + info->skip_byte_block = AV_RB32(buffer + 8); + info->key_id_size = AV_RB32(buffer + 12); + info->key_id = buffer + 16; + info->iv_size = AV_RB32(info->key_id + info->key_id_size); + info->iv = info->key_id + info->key_id_size + 4; + info->subsample_count = AV_RB32(info->iv + info->iv_size); + info->subsamples = (AVSubsampleEncryptionInfo*)(info->iv + info->iv_size + 4); + return 1; +} + +int av_encryption_info_add_side_data(AVPacket* packet, const AVEncryptionInfo* info) { + uint8_t *buffer; + size_t size; + + size = FF_ENCRYPTION_INFO_EXTRA + info->key_id_size + info->iv_size + + (sizeof(AVSubsampleEncryptionInfo) * info->subsample_count); + buffer = av_packet_new_side_data(packet, AV_PKT_DATA_ENCRYPTION_INFO, size); + if (!buffer) + return AVERROR(ENOMEM); + + AV_WB32(buffer, info->scheme); + AV_WB32(buffer + 4, info->crypt_byte_block); + AV_WB32(buffer + 8, info->skip_byte_block); + AV_WB32(buffer + 12, info->key_id_size); + buffer += 16; + memcpy(buffer, info->key_id, info->key_id_size); + buffer += info->key_id_size; + AV_WB32(buffer, info->iv_size); + buffer += 4; + memcpy(buffer, info->iv, info->iv_size); + buffer += info->iv_size; + AV_WB32(buffer, info->subsample_count); + buffer += 4; + memcpy(buffer, info->subsamples, info->subsample_count * sizeof(AVSubsampleEncryptionInfo)); + + return 0; +} diff --git a/libavcodec/encryption_info.h b/libavcodec/encryption_info.h new file mode 100644 index 0000000000..03052bf551 --- /dev/null +++ b/libavcodec/encryption_info.h @@ -0,0 +1,105 @@ +/** + * 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 "avcodec.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. + * + * This struct should be allocated on the stack by the app and filled by + * av_encryption_info_get(). The side-data contains a binary format of this + * struct. + */ +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; + +/** + * Gets the encryption info out of the side data of the given packet and fills + * the given object with that info. The pointers in this structure point inside + * the side data of this packet; this means they should NOT be freed and are + * only valid until the side data is freed. + * + * @param packet The packet to extract the encryption info out of. + * @param info The structure to fill with the encryption info. + * + * @return 1 if the packet is encrypted and the data was extracted; 0 if not. + */ +int av_encryption_info_get(const AVPacket* packet, AVEncryptionInfo* info); + +/** + * Adds a new side data to the given packet that holds a copy of the given + * encryption info. + * + * @return 0 on success, or a negative error code on error. + */ +int av_encryption_info_add_side_data(AVPacket* packet, const AVEncryptionInfo* info); + +#endif /* AVUTIL_ENCRYPTION_INFO_H */ -- 2.15.1.620.gb9897f4670-goog