1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chromecast/media/cma/pipeline/decrypt_util.h"
7 #include <openssl/aes.h>
10 #include "base/logging.h"
11 #include "chromecast/media/cma/base/decoder_buffer_base.h"
12 #include "crypto/symmetric_key.h"
13 #include "media/base/decrypt_config.h"
15 namespace chromecast
{
20 class DecoderBufferClear
: public DecoderBufferBase
{
22 explicit DecoderBufferClear(const scoped_refptr
<DecoderBufferBase
>& buffer
);
24 // DecoderBufferBase implementation.
25 base::TimeDelta
timestamp() const override
;
26 const uint8
* data() const override
;
27 uint8
* writable_data() const override
;
28 int data_size() const override
;
29 const ::media::DecryptConfig
* decrypt_config() const override
;
30 bool end_of_stream() const override
;
33 ~DecoderBufferClear() override
;
35 scoped_refptr
<DecoderBufferBase
> const buffer_
;
37 DISALLOW_COPY_AND_ASSIGN(DecoderBufferClear
);
40 DecoderBufferClear::DecoderBufferClear(
41 const scoped_refptr
<DecoderBufferBase
>& buffer
)
45 DecoderBufferClear::~DecoderBufferClear() {
48 base::TimeDelta
DecoderBufferClear::timestamp() const {
49 return buffer_
->timestamp();
52 const uint8
* DecoderBufferClear::data() const {
53 return buffer_
->data();
56 uint8
* DecoderBufferClear::writable_data() const {
57 return buffer_
->writable_data();
60 int DecoderBufferClear::data_size() const {
61 return buffer_
->data_size();
64 const ::media::DecryptConfig
* DecoderBufferClear::decrypt_config() const {
65 // Buffer is clear so no decryption info.
69 bool DecoderBufferClear::end_of_stream() const {
70 return buffer_
->end_of_stream();
75 scoped_refptr
<DecoderBufferBase
> DecryptDecoderBuffer(
76 const scoped_refptr
<DecoderBufferBase
>& buffer
,
77 crypto::SymmetricKey
* key
) {
78 if (buffer
->end_of_stream())
81 const ::media::DecryptConfig
* decrypt_config
= buffer
->decrypt_config();
82 if (!decrypt_config
|| decrypt_config
->iv().size() == 0)
87 if (!key
->GetRawKey(&raw_key
)) {
88 LOG(ERROR
) << "Failed to get the underlying AES key";
91 DCHECK_EQ(static_cast<int>(raw_key
.length()), AES_BLOCK_SIZE
);
92 const uint8
* key_u8
= reinterpret_cast<const uint8
*>(raw_key
.data());
94 if (AES_set_encrypt_key(key_u8
, AES_BLOCK_SIZE
* 8, &aes_key
) != 0) {
95 LOG(ERROR
) << "Failed to set the AES key";
100 uint8 aes_iv
[AES_BLOCK_SIZE
];
101 DCHECK_EQ(static_cast<int>(decrypt_config
->iv().length()),
103 memcpy(aes_iv
, decrypt_config
->iv().data(), AES_BLOCK_SIZE
);
106 unsigned int encrypted_byte_offset
= 0;
107 uint8 ecount_buf
[AES_BLOCK_SIZE
];
109 // Perform the decryption.
110 const std::vector
< ::media::SubsampleEntry
>& subsamples
=
111 decrypt_config
->subsamples();
112 uint8
* data
= buffer
->writable_data();
114 for (size_t k
= 0; k
< subsamples
.size(); k
++) {
115 offset
+= subsamples
[k
].clear_bytes
;
116 uint32 cypher_bytes
= subsamples
[k
].cypher_bytes
;
117 CHECK_LE(offset
+ cypher_bytes
, buffer
->data_size());
119 data
+ offset
, data
+ offset
, cypher_bytes
, &aes_key
,
120 aes_iv
, ecount_buf
, &encrypted_byte_offset
);
121 offset
+= cypher_bytes
;
124 return scoped_refptr
<DecoderBufferBase
>(new DecoderBufferClear(buffer
));
128 } // namespace chromecast