DASH Media Packaging SDK
 All Classes Namespaces Functions Variables Typedefs Enumerator
encryptor.cc
1 // Copyright 2015 Google Inc. All rights reserved.
2 //
3 // Use of this source code is governed by a BSD-style
4 // license that can be found in the LICENSE file or at
5 // https://developers.google.com/open-source/licenses/bsd
6 
7 #include "packager/media/formats/webm/encryptor.h"
8 
9 #include "packager/media/base/aes_encryptor.h"
10 #include "packager/media/base/fourccs.h"
11 #include "packager/media/base/media_sample.h"
12 
13 namespace edash_packager {
14 namespace media {
15 namespace webm {
16 namespace {
17 
18 Status CreateContentEncryption(mkvmuxer::Track* track, EncryptionKey* key) {
19  if (!track->AddContentEncoding()) {
20  return Status(error::INTERNAL_ERROR,
21  "Could not add ContentEncoding to track.");
22  }
23 
24  mkvmuxer::ContentEncoding* const encoding =
25  track->GetContentEncodingByIndex(0);
26  if (!encoding) {
27  return Status(error::INTERNAL_ERROR,
28  "Could not add ContentEncoding to track.");
29  }
30 
31  mkvmuxer::ContentEncAESSettings* const aes = encoding->enc_aes_settings();
32  if (!aes) {
33  return Status(error::INTERNAL_ERROR,
34  "Error getting ContentEncAESSettings.");
35  }
36  if (aes->cipher_mode() != mkvmuxer::ContentEncAESSettings::kCTR) {
37  return Status(error::INTERNAL_ERROR, "Cipher Mode is not CTR.");
38  }
39 
40  if (!key->key_id.empty() &&
41  !encoding->SetEncryptionID(
42  reinterpret_cast<const uint8*>(key->key_id.data()),
43  key->key_id.size())) {
44  return Status(error::INTERNAL_ERROR, "Error setting encryption ID.");
45  }
46  return Status::OK;
47 }
48 
49 } // namespace
50 
51 Encryptor::Encryptor() {}
52 
53 Encryptor::~Encryptor() {}
54 
56  KeySource::TrackType track_type,
57  KeySource* key_source) {
58  DCHECK(key_source);
59  return CreateEncryptor(muxer_listener, track_type, key_source);
60 }
61 
62 Status Encryptor::AddTrackInfo(mkvmuxer::Track* track) {
63  DCHECK(key_);
64  return CreateContentEncryption(track, key_.get());
65 }
66 
67 Status Encryptor::EncryptFrame(scoped_refptr<MediaSample> sample,
68  bool encrypt_frame) {
69  DCHECK(encryptor_);
70 
71  const size_t sample_size = sample->data_size();
72  if (encrypt_frame) {
73  // | 1 | iv | enc_data |
74  const size_t iv_size = encryptor_->iv().size();
75  sample->resize_data(sample_size + iv_size + 1);
76  uint8_t* sample_data = sample->writable_data();
77 
78  // Encrypt the data in-place.
79  if (!encryptor_->Crypt(sample_data, sample_size, sample_data)) {
80  return Status(error::MUXER_FAILURE, "Failed to encrypt the frame.");
81  }
82 
83  // First move the sample data to after the IV; then write the IV and signal
84  // byte.
85  memmove(sample_data + iv_size + 1, sample_data, sample_size);
86  sample_data[0] = 0x01;
87  memcpy(sample_data + 1, encryptor_->iv().data(), iv_size);
88 
89  encryptor_->UpdateIv();
90  } else {
91  // | 0 | data |
92  sample->resize_data(sample_size + 1);
93  uint8_t* sample_data = sample->writable_data();
94  memmove(sample_data + 1, sample_data, sample_size);
95  sample_data[0] = 0x00;
96  }
97 
98  return Status::OK;
99 }
100 
101 Status Encryptor::CreateEncryptor(MuxerListener* muxer_listener,
102  KeySource::TrackType track_type,
103  KeySource* key_source) {
104  scoped_ptr<EncryptionKey> encryption_key(new EncryptionKey());
105  Status status = key_source->GetKey(track_type, encryption_key.get());
106  if (!status.ok())
107  return status;
108  if (encryption_key->iv.empty()) {
109  if (!AesCryptor::GenerateRandomIv(FOURCC_cenc, &encryption_key->iv))
110  return Status(error::INTERNAL_ERROR, "Failed to generate random iv.");
111  }
112 
113  scoped_ptr<AesCtrEncryptor> encryptor(new AesCtrEncryptor());
114  const bool initialized =
115  encryptor->InitializeWithIv(encryption_key->key, encryption_key->iv);
116  if (!initialized)
117  return Status(error::INTERNAL_ERROR, "Failed to create the encryptor.");
118 
119  if (muxer_listener) {
120  const bool kInitialEncryptionInfo = true;
121  muxer_listener->OnEncryptionInfoReady(kInitialEncryptionInfo,
122  encryption_key->key_id,
123  encryptor->iv(),
124  encryption_key->key_system_info);
125  }
126 
127  key_ = encryption_key.Pass();
128  encryptor_ = encryptor.Pass();
129  return Status::OK;
130 }
131 
132 } // namespace webm
133 } // namespace media
134 } // namespace edash_packager
Status EncryptFrame(scoped_refptr< MediaSample > sample, bool encrypt_frame)
Definition: encryptor.cc:67
virtual Status GetKey(TrackType track_type, EncryptionKey *key)=0
virtual void OnEncryptionInfoReady(bool is_initial_encryption_info, const std::vector< uint8_t > &key_id, const std::vector< uint8_t > &iv, const std::vector< ProtectionSystemSpecificInfo > &key_system_info)=0
static bool GenerateRandomIv(FourCC protection_scheme, std::vector< uint8_t > *iv)
Definition: aes_cryptor.cc:58
KeySource is responsible for encryption key acquisition.
Definition: key_source.h:31
Status Initialize(MuxerListener *muxer_listener, KeySource::TrackType track_type, KeySource *key_source)
Definition: encryptor.cc:55
Status AddTrackInfo(mkvmuxer::Track *track)
Definition: encryptor.cc:62