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/media_sample.h"
11 
12 namespace edash_packager {
13 namespace media {
14 namespace webm {
15 namespace {
16 
17 // Generate 64bit IV by default.
18 const size_t kDefaultIvSize = 8u;
19 
20 Status CreateContentEncryption(mkvmuxer::Track* track, EncryptionKey* key) {
21  if (!track->AddContentEncoding()) {
22  return Status(error::INTERNAL_ERROR,
23  "Could not add ContentEncoding to track.");
24  }
25 
26  mkvmuxer::ContentEncoding* const encoding =
27  track->GetContentEncodingByIndex(0);
28  if (!encoding) {
29  return Status(error::INTERNAL_ERROR,
30  "Could not add ContentEncoding to track.");
31  }
32 
33  mkvmuxer::ContentEncAESSettings* const aes = encoding->enc_aes_settings();
34  if (!aes) {
35  return Status(error::INTERNAL_ERROR,
36  "Error getting ContentEncAESSettings.");
37  }
38  if (aes->cipher_mode() != mkvmuxer::ContentEncAESSettings::kCTR) {
39  return Status(error::INTERNAL_ERROR, "Cipher Mode is not CTR.");
40  }
41 
42  if (!key->key_id.empty() &&
43  !encoding->SetEncryptionID(
44  reinterpret_cast<const uint8*>(key->key_id.data()),
45  key->key_id.size())) {
46  return Status(error::INTERNAL_ERROR, "Error setting encryption ID.");
47  }
48  return Status::OK;
49 }
50 
51 } // namespace
52 
53 Encryptor::Encryptor() {}
54 
55 Encryptor::~Encryptor() {}
56 
58  KeySource::TrackType track_type,
59  KeySource* key_source) {
60  DCHECK(key_source);
61  return CreateEncryptor(muxer_listener, track_type, key_source);
62 }
63 
64 Status Encryptor::AddTrackInfo(mkvmuxer::Track* track) {
65  DCHECK(key_);
66  return CreateContentEncryption(track, key_.get());
67 }
68 
69 Status Encryptor::EncryptFrame(scoped_refptr<MediaSample> sample,
70  bool encrypt_frame) {
71  DCHECK(encryptor_);
72 
73  const size_t sample_size = sample->data_size();
74  if (encrypt_frame) {
75  // | 1 | iv | enc_data |
76  const size_t iv_size = encryptor_->iv().size();
77  sample->resize_data(sample_size + iv_size + 1);
78  uint8_t* sample_data = sample->writable_data();
79 
80  // Encrypt the data in-place.
81  if (!encryptor_->Encrypt(sample_data, sample_size, sample_data)) {
82  return Status(error::MUXER_FAILURE, "Failed to encrypt the frame.");
83  }
84 
85  // First move the sample data to after the IV; then write the IV and signal
86  // byte.
87  memmove(sample_data + iv_size + 1, sample_data, sample_size);
88  sample_data[0] = 0x01;
89  memcpy(sample_data + 1, encryptor_->iv().data(), iv_size);
90 
91  encryptor_->UpdateIv();
92  } else {
93  // | 0 | data |
94  sample->resize_data(sample_size + 1);
95  uint8_t* sample_data = sample->writable_data();
96  memmove(sample_data + 1, sample_data, sample_size);
97  sample_data[0] = 0x00;
98  }
99 
100  return Status::OK;
101 }
102 
103 Status Encryptor::CreateEncryptor(MuxerListener* muxer_listener,
104  KeySource::TrackType track_type,
105  KeySource* key_source) {
106  scoped_ptr<EncryptionKey> encryption_key(new EncryptionKey());
107  Status status = key_source->GetKey(track_type, encryption_key.get());
108  if (!status.ok())
109  return status;
110 
111  scoped_ptr<AesCtrEncryptor> encryptor(new AesCtrEncryptor());
112  const bool initialized = encryption_key->iv.empty()
113  ? encryptor->InitializeWithRandomIv(
114  encryption_key->key, kDefaultIvSize)
115  : encryptor->InitializeWithIv(
116  encryption_key->key, encryption_key->iv);
117  if (!initialized)
118  return Status(error::INTERNAL_ERROR, "Failed to create the encryptor.");
119 
120  if (muxer_listener) {
121  const bool kInitialEncryptionInfo = true;
122  muxer_listener->OnEncryptionInfoReady(
123  kInitialEncryptionInfo, key_source->UUID(), key_source->SystemName(),
124  encryption_key->key_id, encryption_key->pssh);
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:69
virtual Status GetKey(TrackType track_type, EncryptionKey *key)
Definition: key_source.cc:48
virtual std::string UUID()
Definition: key_source.cc:94
KeySource is responsible for encryption key acquisition.
Definition: key_source.h:33
Status Initialize(MuxerListener *muxer_listener, KeySource::TrackType track_type, KeySource *key_source)
Definition: encryptor.cc:57
Status AddTrackInfo(mkvmuxer::Track *track)
Definition: encryptor.cc:64
virtual std::string SystemName()
Definition: key_source.cc:98