From patchwork Sun Apr 11 19:06:29 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nachiket Tarate X-Patchwork-Id: 26867 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 1EC2A44B54C for ; Sun, 11 Apr 2021 22:08:57 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id F0628688158; Sun, 11 Apr 2021 22:08:56 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-pj1-f42.google.com (mail-pj1-f42.google.com [209.85.216.42]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 9932F6804B5 for ; Sun, 11 Apr 2021 22:08:49 +0300 (EEST) Received: by mail-pj1-f42.google.com with SMTP id u14-20020a17090a1f0eb029014e38011b09so983846pja.5 for ; Sun, 11 Apr 2021 12:08:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id; bh=LZYISyotTRldg4abqPA/lGnImKe2b2oKK5ux7zRtGsg=; b=Zl/VPC6wtvmPJJBEtYr6uaVn2BufTmBI2n+NU3wi7f+Ht6kke84nJWt7tb2SrvDOUw 7X8VLf4imIxt15MtoVfLl96aYvs1chhhn9sa26pJi1lb00Ud3q0bmGRQYxC2NpbwXMzX hg31W3HiWdLv4Rw/6qwAzjnE8IrhUsM5zg3C8Fo/1O8KOCGm/US8l27jKkqi0vAo3Bzs COwIMRiqfdjkIQxG7GwsRDuDPimZz/PnTi2k8t8Sf3A7/cXzpG0k9rlkN3ltiYjKqPiu ngmGGqLcVN5LpZBGlhHPieptrUinHW1xgn+8x9e/AiMgTo95RnOyoZZzUOeK+ZMoVd7I ZgKg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id; bh=LZYISyotTRldg4abqPA/lGnImKe2b2oKK5ux7zRtGsg=; b=E91HF1W0WciISKWzUKBmlCcKcXQrMOjk75weSGr68MenuauV4p+ynWMvgLDkPJ3bwJ 3ibxnUwP8/qQ+kCwXz+DIrXC19Uy8BG/F5iHo2OhjG5sQoVudW1prfW1JQQLFHCu2R33 1IUXFfjggjpiXO1f4g9W6IrLqrtE+MX3M2+FrMCug2mZncUD122w+VXWiuiph1Symshw YKWbKFuviaFF2l2mu5vbMTbEVFfnVNTCH53E911cN/ZaXlBSQbxFBOePIAKIWoGqCQjO FHK//4KZOYn8l9/7zg+XNVC6gwGuCJg1OQVNUenI80kEQsFBGevtFVCHYmLMIUOt1q2E of7A== X-Gm-Message-State: AOAM531CWMrjWmZKyJdJfTCdNKGcBFsJk8Orj5WqH4PxQ0k7YmNtHYS9 Lim2Yo1SnPcjzfg8q5MKCN6sDgBkfi8Pog== X-Google-Smtp-Source: ABdhPJxTS700kj5NeoA0LV7QAz/eok33Z+mfj5L8Cudt4K/wvW5YjSlMgc+bb1cQLygF+8eUBiC1Bw== X-Received: by 2002:a17:90b:4a07:: with SMTP id kk7mr24738576pjb.165.1618168127733; Sun, 11 Apr 2021 12:08:47 -0700 (PDT) Received: from lab-21.india.rsystems.com ([106.198.149.254]) by smtp.gmail.com with ESMTPSA id il6sm8099868pjb.56.2021.04.11.12.08.45 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 11 Apr 2021 12:08:47 -0700 (PDT) From: Nachiket Tarate To: ffmpeg-devel@ffmpeg.org Date: Mon, 12 Apr 2021 00:36:29 +0530 Message-Id: <20210411190629.17642-1-nachiket.programmer@gmail.com> X-Mailer: git-send-email 2.17.1 Subject: [FFmpeg-devel] [PATCH 2/4] libavformat/mov: add support for 'cbcs' encryption scheme specified in Common Encryption (CENC) standard 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 MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" https://www.iso.org/standard/68042.html Signed-off-by: Nachiket Tarate --- libavformat/isom.h | 1 + libavformat/mov.c | 86 ++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 81 insertions(+), 6 deletions(-) diff --git a/libavformat/isom.h b/libavformat/isom.h index 5a6d504090..5a17cb9c07 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -237,6 +237,7 @@ typedef struct MOVStreamContext { int has_sidx; // If there is an sidx entry for this stream. struct { struct AVAESCTR* aes_ctr; + struct AVAES *aes_ctx; unsigned int per_sample_iv_size; // Either 0, 8, or 16. AVEncryptionInfo *default_encrypted_sample; MOVEncryptionIndex *encryption_index; diff --git a/libavformat/mov.c b/libavformat/mov.c index 43c55ef4a4..5eda5f3822 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -6623,15 +6623,10 @@ static int mov_read_dfla(MOVContext *c, AVIOContext *pb, MOVAtom atom) return 0; } -static int cenc_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size) +static int cenc_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size) { int i, ret; - if (sample->scheme != MKBETAG('c','e','n','c') || sample->crypt_byte_block != 0 || sample->skip_byte_block != 0) { - av_log(c->fc, AV_LOG_ERROR, "Only the 'cenc' encryption scheme is supported\n"); - return AVERROR_PATCHWELCOME; - } - if (!sc->cenc.aes_ctr) { /* initialize the cipher */ sc->cenc.aes_ctr = av_aes_ctr_alloc(); @@ -6654,6 +6649,7 @@ static int cenc_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *s } for (i = 0; i < sample->subsample_count; i++) { + if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) { av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n"); return AVERROR_INVALIDDATA; @@ -6677,6 +6673,84 @@ static int cenc_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *s return 0; } +static int cbcs_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size) +{ + int i, ret; + int encrypted_blocks; + uint8_t iv[16]; + + if (!sc->cenc.aes_ctx) { + /* initialize the cipher */ + sc->cenc.aes_ctx = av_aes_alloc(); + if (!sc->cenc.aes_ctx) { + return AVERROR(ENOMEM); + } + + ret = av_aes_init(sc->cenc.aes_ctx, c->decryption_key, 16 * 8, 1); + if (ret < 0) { + return ret; + } + } + + /* whole-block full sample encryption */ + if (!sample->subsample_count) { + /* decrypt the whole packet */ + memcpy(iv, sample->iv, 16); + av_aes_crypt(sc->cenc.aes_ctx, input, input, size/16, iv, 1); + return 0; + } + + for (i = 0; i < sample->subsample_count; i++) { + + if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) { + av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n"); + return AVERROR_INVALIDDATA; + } + + /* skip the clear bytes */ + input += sample->subsamples[i].bytes_of_clear_data; + size -= sample->subsamples[i].bytes_of_clear_data; + + /* decrypt the encrypted bytes */ + memcpy(iv, sample->iv, 16); + encrypted_blocks = sample->subsamples[i].bytes_of_protected_data/16; + if (encrypted_blocks > 0) { + /* pattern encryption */ + if (sample->crypt_byte_block > 0 && sample->skip_byte_block > 0) { + uint8_t *data = input; + int rem_bytes = sample->subsamples[i].bytes_of_protected_data; + while (rem_bytes > 0) { + if (rem_bytes > 16*sample->crypt_byte_block) { + av_aes_crypt(sc->cenc.aes_ctx, data, data, sample->crypt_byte_block, iv, 1); + data += 16*sample->crypt_byte_block; + rem_bytes -= 16*sample->crypt_byte_block; + } + data += FFMIN(16*sample->skip_byte_block, rem_bytes); + rem_bytes -= FFMIN(16*sample->skip_byte_block, rem_bytes); + } + } else { + av_aes_crypt(sc->cenc.aes_ctx, input, input, encrypted_blocks, iv, 1); + } + } + input += sample->subsamples[i].bytes_of_protected_data; + size -= sample->subsamples[i].bytes_of_protected_data; + } + + return 0; +} + +static int cenc_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *sample, uint8_t *input, int size) +{ + if (sample->scheme == MKBETAG('c','e','n','c') && sample->crypt_byte_block == 0 && sample->skip_byte_block == 0) { + return cenc_scheme_decrypt(c, sc, sample, input, size); + } else if (sample->scheme == MKBETAG('c','b','c','s')) { + return cbcs_scheme_decrypt(c, sc, sample, input, size); + } else { + av_log(c->fc, AV_LOG_ERROR, "Only 'cenc' and 'cbcs' encryption schemes are supported\n"); + return AVERROR_PATCHWELCOME; + } +} + static int cenc_filter(MOVContext *mov, AVStream* st, MOVStreamContext *sc, AVPacket *pkt, int current_index) { MOVFragmentStreamInfo *frag_stream_info;