Shaka Player Embedded
decryptor_darwin.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 <CommonCrypto/CommonCryptor.h>
16 #include <Security/Security.h>
17 #include <glog/logging.h> // NOLINT(build/include_alpha)
18 
19 #include "src/util/decryptor.h"
20 
21 namespace shaka {
22 namespace util {
23 
24 namespace {
25 
26 void IncrementIv(std::vector<uint8_t>* iv) {
27  DCHECK_EQ(iv->size(), AES_BLOCK_SIZE);
28  auto* iv_ptr = reinterpret_cast<uint64_t*>(iv->data() + 8);
29  // This converts the number from network (big) byte order to host order, then
30  // increases the value, then converts back to network byte order.
31  *iv_ptr = htonll(ntohll(*iv_ptr) + 1);
32 }
33 
34 } // namespace
35 
36 struct Decryptor::Impl {};
37 
39  const std::vector<uint8_t>& key,
40  const std::vector<uint8_t>& iv)
41  : scheme_(scheme), key_(key), iv_(iv) {
42  DCHECK_EQ(AES_BLOCK_SIZE, key.size());
43  DCHECK_EQ(AES_BLOCK_SIZE, iv.size());
44 }
45 
47 
48 bool Decryptor::DecryptPartialBlock(const uint8_t* data, size_t data_size,
49  uint32_t block_offset, uint8_t* dest) {
50  if (scheme_ == eme::EncryptionScheme::AesCtr) {
51  // Mac/iOS only supports CBC, so we need to implement CTR mode based on
52  // their AES encryption.
53 
54  size_t data_offset = 0;
55  while (data_offset < data_size) {
56  uint8_t encrypted_iv[AES_BLOCK_SIZE];
57  size_t length;
58  CCCryptorStatus result = CCCrypt(
59  kCCEncrypt, kCCAlgorithmAES128, 0, key_.data(), key_.size(), nullptr,
60  iv_.data(), iv_.size(), encrypted_iv, AES_BLOCK_SIZE, &length);
61  if (result != kCCSuccess) {
62  LOG(ERROR) << "Error decrypting data: " << result;
63  return false;
64  }
65  if (length != AES_BLOCK_SIZE) {
66  LOG(ERROR) << "Not all data decrypted";
67  return false;
68  }
69 
70  const size_t to_decrypt = AES_BLOCK_SIZE - block_offset;
71  for (size_t i = 0; i < to_decrypt && i + data_offset < data_size; i++) {
72  dest[data_offset + i] =
73  data[data_offset + i] ^ encrypted_iv[i + block_offset];
74  }
75 
76  data_offset += to_decrypt;
77  block_offset = 0;
78  IncrementIv(&iv_);
79  }
80  } else {
81  if (block_offset != 0) {
82  LOG(ERROR) << "Cannot have block offset when using CBC";
83  return false;
84  }
85  if (data_size % AES_BLOCK_SIZE != 0u) {
86  LOG(ERROR) << "CBC requires protected ranges to be a multiple of the "
87  "block size.";
88  return false;
89  }
90 
91  // This uses AES-CBC.
92  size_t length;
93  CCCryptorStatus result =
94  CCCrypt(kCCDecrypt, kCCAlgorithmAES128, 0, key_.data(), key_.size(),
95  iv_.data(), data, data_size, dest, data_size, &length);
96  if (result != kCCSuccess) {
97  LOG(ERROR) << "Error decrypting data: " << result;
98  return false;
99  }
100  if (length != data_size) {
101  LOG(ERROR) << "Not all data decrypted";
102  return false;
103  }
104 
105  if (data_size >= AES_BLOCK_SIZE) {
106  iv_.assign(data + data_size - AES_BLOCK_SIZE, data + data_size);
107  }
108  }
109 
110  return true;
111 }
112 
113 bool Decryptor::Decrypt(const uint8_t* data, size_t data_size, uint8_t* dest) {
114  return DecryptPartialBlock(data, data_size, 0, dest);
115 }
116 
117 bool Decryptor::InitIfNeeded() {
118  return true;
119 }
120 
121 } // namespace util
122 } // 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)
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