From patchwork Fri Sep 29 15:10:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luis Scheurenbrand X-Patchwork-Id: 44021 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:394d:b0:15d:8365:d4b8 with SMTP id r13csp618252pzg; Fri, 29 Sep 2023 08:10:57 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHvFg4E/TXEh1hNlydI47LKH1eA8u/e4Yd/ZmpkGegcqQ4lMZQrc4dtsVQuIT0tVqQhTBTk X-Received: by 2002:a05:6402:204e:b0:532:e1a2:b0b8 with SMTP id bc14-20020a056402204e00b00532e1a2b0b8mr4402911edb.8.1696000257614; Fri, 29 Sep 2023 08:10:57 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1696000257; cv=none; d=google.com; s=arc-20160816; b=LojssSLTqsC49WLVyYoYIGLaXxI5kLYCpAncHUrNY8ww5rzORfCGThaFcm7VHtybEl Cq50+vk1h5wEoYNzY45wyRpD6DdAr53BB0rFhM6z2t7EUuFuddMwATTjSdX/2trAoXcS jTBcFjceZbVqhuYYSvDUY/7VrSy/Fst198YaYsYXwqUsM58jsSFTaUT2PGtjxW+E0KFC eLGP1aZXx749lXwkwNKXYbtSR9alL+vJea13gbjgpfDM7UtSULDuu35JTyqJyJ1XnMwC vM1tYjQE28h0d2M5TR7njj4Xv1Yt8/VTkTpxrVdzxDyDdXkHsNCyLbfa54Gph6ErlKmU YtPA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to:from :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:autocrypt:content-language:to:user-agent :mime-version:date:message-id:feedback-id:delivered-to; bh=wvAb1zK+3x0v9iPe+ZpJpWGf8JqywzzEBQ+XF9QKvjI=; fh=7e88NmSu5q0Rrk+nj/dNaGthwsS/GL06UBBVVuqz8+c=; b=o8kBG0koXkeOvkJF6Ys3yYF9jD/eulTZuVDgT01hsAZwVlBX26tN+Dg4aMyaQyUfxQ PXP4lHo8ubv/q3tLXjc8jZwp1mNI2BC7S6I9wo6UxshBn0Dg7QJm/wAHi6OhwE/am8qH jfAcst3kWce44C4naMkSe4MwOplZehx7ErMPz36ZntxQP0lpPn3pe9AgTugdCDzvE8m7 pPYR3PDSuLmfsaDZoY0HJQr0qeDqWq+mfsDr2eoR6e19dlYnkTx7fWq677goZ20x1jKv FnKxahm1ojdHp4xd9aU9klFBajM8ckRFIM92v7MX70iJD42lVgOp6UNNxyH44zxsWu/+ bnDw== ARC-Authentication-Results: i=1; mx.google.com; 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 c7-20020aa7c747000000b0053626440749si1873278eds.38.2023.09.29.08.10.38; Fri, 29 Sep 2023 08:10:57 -0700 (PDT) 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; 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 0C09568CC24; Fri, 29 Sep 2023 18:10:35 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from sendmail.purelymail.com (unknown [34.202.193.197]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 3197B68CC06 for ; Fri, 29 Sep 2023 18:10:28 +0300 (EEST) Feedback-ID: 17590:3276:null:purelymail X-Pm-Original-To: ffmpeg-devel@ffmpeg.org Received: by smtp.purelymail.com (Purelymail SMTP) with ESMTPSA id 205869887 for (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384); Fri, 29 Sep 2023 15:10:19 +0000 (UTC) Message-ID: Date: Fri, 29 Sep 2023 17:10:18 +0200 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird To: ffmpeg-devel@ffmpeg.org Content-Language: en-US Autocrypt: addr=luis@scheurenbrand.me; keydata= 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 3wpbJHA1DJ/d/EEwWq/i Subject: [FFmpeg-devel] [PATCH] avformat/hls: Re-use crypto URLContext X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Luis Scheurenbrand via ffmpeg-devel From: Luis Scheurenbrand Reply-To: FFmpeg development discussions and patches Cc: Luis Scheurenbrand Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: qnZR0aMdMkDZ Reset crypto state and keep nested http context alive. Previously, an unencrypted file, followed by an encrypted file would result in a corrupted stream, as the stream would not be closed and an encrypted file would be forwarded to the demuxer. fixes: https://trac.ffmpeg.org/ticket/10599 fixes: https://trac.ffmpeg.org/ticket/8490 Signed-off-by: Luis Scheurenbrand --- libavformat/crypto.c | 55 ++++++++++++++++++++++++++++++++++++++++++++ libavformat/crypto.h | 38 ++++++++++++++++++++++++++++++ libavformat/hls.c | 32 ++++++++++++++++++++++---- 3 files changed, 120 insertions(+), 5 deletions(-) create mode 100644 libavformat/crypto.h return 0; } +/* compares two segments to ensure the encryption is the same and + * we can reuse the crypto and/or http context. */ +static int crypto_matches(const struct segment *lhs, const struct segment *rhs) { + if (!lhs || !rhs) + return 0; + if (lhs->key_type != rhs->key_type) + return 0; + if (lhs->key_type == KEY_NONE) + return 1; + + return + strcmp(lhs->key, rhs->key) == 0 && + memcmp(lhs->iv, rhs->iv, sizeof(lhs->iv)) == 0; +} + static int open_url_keepalive(AVFormatContext *s, AVIOContext **pb, const char *url, AVDictionary **options) { #if !CONFIG_HTTP_PROTOCOL return AVERROR_PROTOCOL_NOT_FOUND; #else - int ret; + int ret=0; URLContext *uc = ffio_geturlcontext(*pb); av_assert0(uc); (*pb)->eof_reached = 0; - ret = ff_http_do_new_request2(uc, url, options); + + if (av_strstart(url, "crypto+", &url)) { + ret = ff_crypto_reset(uc); + uc = ff_crypto_get_inner(uc); + } + + if (ret == 0) ret = ff_http_do_new_request2(uc, url, options); if (ret < 0) { ff_format_io_close(s, pb); } @@ -1592,7 +1614,7 @@ reload: seg = next_segment(v); if (c->http_multiple == 1 && !v->input_next_requested && - seg && seg->key_type == KEY_NONE && av_strstart(seg->url, "http", NULL)) { + seg && av_strstart(seg->url, "http", NULL)) { ret = open_input(c, v, seg, &v->input_next); if (ret < 0) { if (ff_check_interrupt(c->interrupt_callback)) @@ -1624,8 +1646,8 @@ reload: return ret; } - if (c->http_persistent && - seg->key_type == KEY_NONE && av_strstart(seg->url, "http", NULL)) { + if (c->http_persistent && crypto_matches(seg, next_segment(v)) && + av_strstart(seg->url, "http", NULL)) { v->input_read_done = 1; } else { ff_format_io_close(v->parent, &v->input); diff --git a/libavformat/crypto.c b/libavformat/crypto.c index 75b00020bc..543300c7c0 100644 --- a/libavformat/crypto.c +++ b/libavformat/crypto.c @@ -20,8 +20,10 @@ */ #include "libavutil/aes.h" +#include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/opt.h" +#include "crypto.h" #include "url.h" // encourage reads of 4096 bytes - 1 block is always retained. @@ -105,6 +107,59 @@ static int set_aes_arg(URLContext *h, uint8_t **buf, int *buf_len, return 0; } +URLContext *ff_crypto_get_inner(URLContext *h) +{ + CryptoContext *c = h->priv_data; + return c->hd; +} + +int ff_crypto_reset(URLContext *h) +{ + int ret = 0; + CryptoContext *c = h->priv_data; + int flags = c->flags; + + if (flags & AVIO_FLAG_READ) { + av_assert0(c->decrypt_key); + av_assert0(c->decrypt_iv); + av_assert0(c->aes_decrypt); + + memcpy(c->decrypt_key, c->key, c->keylen); + memcpy(c->decrypt_iv, c->iv, c->ivlen); + + ret = av_aes_init(c->aes_decrypt, c->decrypt_key, BLOCKSIZE * 8, 1); + if (ret < 0) + goto err; + } + + if (flags & AVIO_FLAG_WRITE) { + av_assert0(c->encrypt_key); + av_assert0(c->encrypt_iv); + av_assert0(c->aes_encrypt); + + memcpy(c->encrypt_key, c->key, c->keylen); + memcpy(c->encrypt_iv, c->iv, c->ivlen); + + ret = av_aes_init(c->aes_encrypt, c->encrypt_key, BLOCKSIZE * 8, 0); + if (ret < 0) + goto err; + } + + c->indata = c->indata_used = c->outdata = 0; + c->position = 0; + c->eof = 0; + c->outdata = 0; + c->outptr = 0; + + av_assert0(c->outbuffer); + av_assert0(c->inbuffer); + memset(c->outbuffer, 0, sizeof(c->outbuffer)); + memset(c->inbuffer, 0, sizeof(c->inbuffer)); + +err: + return ret; +} + static int crypto_open2(URLContext *h, const char *uri, int flags, AVDictionary **options) { const char *nested_url; diff --git a/libavformat/crypto.h b/libavformat/crypto.h new file mode 100644 index 0000000000..7e6d7f0279 --- /dev/null +++ b/libavformat/crypto.h @@ -0,0 +1,38 @@ +/* + * HTTP definitions + * Copyright (c) 2010 Josh Allmann + * + * 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 AVFORMAT_CRYPTO_H +#define AVFORMAT_CRYPTO_H + +#include "url.h" + +URLContext *ff_crypto_get_inner(URLContext *h); + +/** + * Resets the crypto context. + * + * @param h pointer to the resource + * @return a negative value if an error condition occurred, 0 + * otherwise + */ +int ff_crypto_reset(URLContext *h); + +#endif /* AVFORMAT_CRYPTO_H */ diff --git a/libavformat/hls.c b/libavformat/hls.c index 332a5a15bb..7ad0ec9aec 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -44,6 +44,7 @@ #include "avio_internal.h" #include "id3v2.h" #include "url.h" +#include "crypto.h" #include "hls_sample_encryption.h" @@ -620,17 +621,38 @@ static int ensure_playlist(HLSContext *c, struct playlist **pls, const char *url