Shaka Player Embedded
decryptor_openssl.cc
Go to the documentation of this file.
1 // Copyright 2018 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <glog/logging.h>
16 #include <openssl/conf.h>
17 #include <openssl/err.h>
18 #include <openssl/evp.h>
19 
20 #include "src/util/decryptor.h"
21 
22 namespace shaka {
23 namespace util {
24 
25 struct Decryptor::Impl {
26  std::unique_ptr<EVP_CIPHER_CTX, void (*)(EVP_CIPHER_CTX*)> ctx{
27  nullptr, &EVP_CIPHER_CTX_free};
28 };
29 
31  const std::vector<uint8_t>& key,
32  const std::vector<uint8_t>& iv)
33  : scheme_(scheme), key_(key), iv_(iv), extra_(new Impl) {
34  DCHECK_EQ(AES_BLOCK_SIZE, key.size());
35  DCHECK_EQ(AES_BLOCK_SIZE, iv.size());
36 }
37 
39 
40 bool Decryptor::DecryptPartialBlock(const uint8_t* data, size_t data_size,
41  uint32_t block_offset, uint8_t* dest) {
42  DCHECK_LE(block_offset + data_size, AES_BLOCK_SIZE);
43 
44  if (!InitIfNeeded())
45  return false;
46 
47  if (scheme_ != eme::EncryptionScheme::AesCtr) {
48  LOG(ERROR) << "Cannot have block offset when using CBC";
49  return false;
50  }
51 
52  uint8_t temp_source[AES_BLOCK_SIZE] = {0};
53  uint8_t temp_dest[AES_BLOCK_SIZE];
54  const size_t partial_size =
55  std::min<size_t>(AES_BLOCK_SIZE - block_offset, data_size);
56  memcpy(temp_source + block_offset, data, partial_size);
57 
58  int num_bytes_read;
59  if (!EVP_DecryptUpdate(extra_->ctx.get(), temp_dest, &num_bytes_read,
60  temp_source, AES_BLOCK_SIZE) ||
61  num_bytes_read != AES_BLOCK_SIZE) {
62  LOG(ERROR) << "Error decrypting data: "
63  << ERR_error_string(ERR_get_error(), nullptr);
64  return false;
65  }
66  memcpy(dest, temp_dest + block_offset, partial_size);
67  return true;
68 }
69 
70 bool Decryptor::Decrypt(const uint8_t* data, size_t data_size, uint8_t* dest) {
71  if (!InitIfNeeded())
72  return false;
73 
74  int num_bytes_read;
75  if (!EVP_DecryptUpdate(extra_->ctx.get(), dest, &num_bytes_read, data,
76  data_size) ||
77  static_cast<size_t>(num_bytes_read) != data_size) {
78  LOG(ERROR) << "Error decrypting data: "
79  << ERR_error_string(ERR_get_error(), nullptr);
80  return false;
81  }
82 
83  return true;
84 }
85 
86 bool Decryptor::InitIfNeeded() {
87  if (!extra_->ctx) {
88  extra_->ctx.reset(EVP_CIPHER_CTX_new());
89  if (!extra_->ctx) {
90  LOG(ERROR) << "Error allocating OpenSSL context: "
91  << ERR_error_string(ERR_get_error(), nullptr);
92  return false;
93  }
94 
95  const bool is_ctr = scheme_ == eme::EncryptionScheme::AesCtr;
96  if (!EVP_DecryptInit_ex(extra_->ctx.get(),
97  is_ctr ? EVP_aes_128_ctr() : EVP_aes_128_cbc(),
98  nullptr, key_.data(), iv_.data()) ||
99  !EVP_CIPHER_CTX_set_padding(extra_->ctx.get(), 0)) {
100  LOG(ERROR) << "Error setting up OpenSSL context: "
101  << ERR_error_string(ERR_get_error(), nullptr);
102  return false;
103  }
104  }
105  return true;
106 }
107 
108 } // namespace util
109 } // namespace shaka
const char * dest
Definition: media_utils.cc:31
bool DecryptPartialBlock(const uint8_t *data, size_t data_size, uint32_t block_offset, uint8_t *dest)
std::unique_ptr< EVP_CIPHER_CTX, void(*)(EVP_CIPHER_CTX *)> ctx
Decryptor(eme::EncryptionScheme scheme, const std::vector< uint8_t > &key, const std::vector< uint8_t > &iv)
bool Decrypt(const uint8_t *data, size_t data_size, uint8_t *dest)
#define AES_BLOCK_SIZE