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 StreamId
stream_id() const override
;
26 base::TimeDelta
timestamp() const override
;
27 void set_timestamp(const base::TimeDelta
& timestamp
) override
;
28 const uint8
* data() const override
;
29 uint8
* writable_data() const override
;
30 size_t data_size() const override
;
31 const ::media::DecryptConfig
* decrypt_config() const override
;
32 bool end_of_stream() const override
;
35 ~DecoderBufferClear() override
;
37 scoped_refptr
<DecoderBufferBase
> const buffer_
;
39 DISALLOW_COPY_AND_ASSIGN(DecoderBufferClear
);
42 DecoderBufferClear::DecoderBufferClear(
43 const scoped_refptr
<DecoderBufferBase
>& buffer
)
47 DecoderBufferClear::~DecoderBufferClear() {
50 StreamId
DecoderBufferClear::stream_id() const {
51 return buffer_
->stream_id();
54 base::TimeDelta
DecoderBufferClear::timestamp() const {
55 return buffer_
->timestamp();
58 void DecoderBufferClear::set_timestamp(const base::TimeDelta
& timestamp
) {
59 buffer_
->set_timestamp(timestamp
);
62 const uint8
* DecoderBufferClear::data() const {
63 return buffer_
->data();
66 uint8
* DecoderBufferClear::writable_data() const {
67 return buffer_
->writable_data();
70 size_t DecoderBufferClear::data_size() const {
71 return buffer_
->data_size();
74 const ::media::DecryptConfig
* DecoderBufferClear::decrypt_config() const {
75 // Buffer is clear so no decryption info.
79 bool DecoderBufferClear::end_of_stream() const {
80 return buffer_
->end_of_stream();
85 scoped_refptr
<DecoderBufferBase
> DecryptDecoderBuffer(
86 const scoped_refptr
<DecoderBufferBase
>& buffer
,
87 crypto::SymmetricKey
* key
) {
88 if (buffer
->end_of_stream())
91 const ::media::DecryptConfig
* decrypt_config
= buffer
->decrypt_config();
92 if (!decrypt_config
|| decrypt_config
->iv().size() == 0)
97 if (!key
->GetRawKey(&raw_key
)) {
98 LOG(ERROR
) << "Failed to get the underlying AES key";
101 DCHECK_EQ(static_cast<int>(raw_key
.length()), AES_BLOCK_SIZE
);
102 const uint8
* key_u8
= reinterpret_cast<const uint8
*>(raw_key
.data());
104 if (AES_set_encrypt_key(key_u8
, AES_BLOCK_SIZE
* 8, &aes_key
) != 0) {
105 LOG(ERROR
) << "Failed to set the AES key";
110 uint8 aes_iv
[AES_BLOCK_SIZE
];
111 DCHECK_EQ(static_cast<int>(decrypt_config
->iv().length()),
113 memcpy(aes_iv
, decrypt_config
->iv().data(), AES_BLOCK_SIZE
);
116 unsigned int encrypted_byte_offset
= 0;
117 uint8 ecount_buf
[AES_BLOCK_SIZE
];
119 // Perform the decryption.
120 const std::vector
< ::media::SubsampleEntry
>& subsamples
=
121 decrypt_config
->subsamples();
122 uint8
* data
= buffer
->writable_data();
124 for (size_t k
= 0; k
< subsamples
.size(); k
++) {
125 offset
+= subsamples
[k
].clear_bytes
;
126 uint32 cypher_bytes
= subsamples
[k
].cypher_bytes
;
127 CHECK_LE(static_cast<size_t>(offset
+ cypher_bytes
), buffer
->data_size());
129 data
+ offset
, data
+ offset
, cypher_bytes
, &aes_key
,
130 aes_iv
, ecount_buf
, &encrypted_byte_offset
);
131 offset
+= cypher_bytes
;
134 return scoped_refptr
<DecoderBufferBase
>(new DecoderBufferClear(buffer
));
138 } // namespace chromecast