summaryrefslogtreecommitdiffstats
path: root/media/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'media/crypto')
-rw-r--r--media/crypto/DEPS3
-rw-r--r--media/crypto/aes_decryptor.cc78
-rw-r--r--media/crypto/aes_decryptor.h32
-rw-r--r--media/crypto/aes_decryptor_unittest.cc56
4 files changed, 169 insertions, 0 deletions
diff --git a/media/crypto/DEPS b/media/crypto/DEPS
new file mode 100644
index 0000000..4ef4138
--- /dev/null
+++ b/media/crypto/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+crypto",
+]
diff --git a/media/crypto/aes_decryptor.cc b/media/crypto/aes_decryptor.cc
new file mode 100644
index 0000000..8e83daf
--- /dev/null
+++ b/media/crypto/aes_decryptor.cc
@@ -0,0 +1,78 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/crypto/aes_decryptor.h"
+
+#include <string>
+
+#include "base/logging.h"
+#include "crypto/encryptor.h"
+#include "crypto/symmetric_key.h"
+#include "media/base/buffers.h"
+#include "media/base/data_buffer.h"
+#include "media/base/decrypt_config.h"
+
+namespace media {
+
+static const char* kInitialCounter = "0000000000000000";
+
+// Decrypts |input| using |raw_key|, which is the binary data for the decryption
+// key.
+// Return a scoped_refptr to a Buffer object with the decrypted data on success.
+// Return a scoped_refptr to NULL if the data could not be decrypted.
+// TODO(xhwang): Both the input and output are copied! Any performance concern?
+static scoped_refptr<Buffer> DecryptData(const Buffer& input,
+ const uint8* raw_key,
+ int raw_key_size) {
+ CHECK(raw_key && raw_key_size > 0);
+ CHECK(input.GetDataSize());
+
+ scoped_ptr<crypto::SymmetricKey> key(crypto::SymmetricKey::Import(
+ crypto::SymmetricKey::AES,
+ std::string(reinterpret_cast<const char*>(raw_key), raw_key_size)));
+ if (!key.get()) {
+ DVLOG(1) << "Could not import key.";
+ return NULL;
+ }
+
+ // Initialize encryption data.
+ // The IV must be exactly as long as the cipher block size.
+ crypto::Encryptor encryptor;
+ if (!encryptor.Init(key.get(), crypto::Encryptor::CBC, kInitialCounter)) {
+ DVLOG(1) << "Could not initialize encryptor.";
+ return NULL;
+ }
+
+ std::string decrypt_text;
+ std::string encrypted_text(reinterpret_cast<const char*>(input.GetData()),
+ input.GetDataSize());
+ if (!encryptor.Decrypt(encrypted_text, &decrypt_text)) {
+ DVLOG(1) << "Could not decrypt data.";
+ return NULL;
+ }
+
+ return DataBuffer::CopyFrom(
+ reinterpret_cast<const uint8*>(decrypt_text.data()),
+ decrypt_text.size());
+}
+
+AesDecryptor::AesDecryptor() {}
+
+scoped_refptr<Buffer> AesDecryptor::Decrypt(
+ const scoped_refptr<Buffer>& encrypted) {
+ CHECK(encrypted->GetDecryptConfig());
+
+ // For now, the key is the key ID.
+ const uint8* key = encrypted->GetDecryptConfig()->key_id();
+ int key_size = encrypted->GetDecryptConfig()->key_id_size();
+ scoped_refptr<Buffer> decrypted = DecryptData(*encrypted, key, key_size);
+ if (decrypted) {
+ decrypted->SetTimestamp(encrypted->GetTimestamp());
+ decrypted->SetDuration(encrypted->GetDuration());
+ }
+
+ return decrypted;
+}
+
+} // namespace media
diff --git a/media/crypto/aes_decryptor.h b/media/crypto/aes_decryptor.h
new file mode 100644
index 0000000..32d6802
--- /dev/null
+++ b/media/crypto/aes_decryptor.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_CRYPTO_AES_DECRYPTOR_H_
+#define MEDIA_CRYPTO_AES_DECRYPTOR_H_
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "media/base/media_export.h"
+
+namespace media {
+
+class Buffer;
+
+// Decrypts AES encrypted buffer into unencrypted buffer.
+class MEDIA_EXPORT AesDecryptor {
+ public:
+ AesDecryptor();
+
+ // Decrypt |input| buffer. The |input| should not be NULL.
+ // Return a Buffer that contains decrypted data if decryption succeeded.
+ // Return NULL if decryption failed.
+ scoped_refptr<Buffer> Decrypt(const scoped_refptr<Buffer>& input);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(AesDecryptor);
+};
+
+} // namespace media
+
+#endif // MEDIA_CRYPTO_AES_DECRYPTOR_H_
diff --git a/media/crypto/aes_decryptor_unittest.cc b/media/crypto/aes_decryptor_unittest.cc
new file mode 100644
index 0000000..0143bd0
--- /dev/null
+++ b/media/crypto/aes_decryptor_unittest.cc
@@ -0,0 +1,56 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "media/base/data_buffer.h"
+#include "media/base/decrypt_config.h"
+#include "media/crypto/aes_decryptor.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace media {
+
+// |kEncryptedDataHex| is encrypted from |kOriginalData| using |kRawKey|, whose
+// length is |kKeySize|. Modifying any of these independently would fail the
+// test.
+static const char kOriginalData[] = "Original data.";
+static const int kEncryptedDataSize = 16;
+static const unsigned char kEncryptedData[] =
+ "\x82\x3A\x76\x92\xEC\x7F\xF8\x85\xEC\x23\x52\xFB\x19\xB1\xB9\x09";
+static const int kKeySize = 16;
+static const unsigned char kRawKey[] = "A wonderful key!";
+static const unsigned char kWrongKey[] = "I'm a wrong key.";
+
+class AesDecryptorTest : public testing::Test {
+ public:
+ AesDecryptorTest() {
+ encrypted_data_ = DataBuffer::CopyFrom(kEncryptedData, kEncryptedDataSize);
+ }
+
+ protected:
+ void SetKey(const uint8* key, int key_size) {
+ encrypted_data_->SetDecryptConfig(
+ scoped_ptr<DecryptConfig>(new DecryptConfig(key, key_size)));
+ }
+
+ scoped_refptr<DataBuffer> encrypted_data_;
+ AesDecryptor decryptor_;
+};
+
+TEST_F(AesDecryptorTest, NormalDecryption) {
+ SetKey(kRawKey, kKeySize);
+ scoped_refptr<Buffer> decrypted_data = decryptor_.Decrypt(encrypted_data_);
+ ASSERT_TRUE(decrypted_data.get());
+ size_t data_length = sizeof(kOriginalData) - 1;
+ ASSERT_EQ(data_length, decrypted_data->GetDataSize());
+ ASSERT_EQ(0, memcmp(kOriginalData, decrypted_data->GetData(), data_length));
+}
+
+TEST_F(AesDecryptorTest, WrongKey) {
+ SetKey(kWrongKey, kKeySize);
+ scoped_refptr<Buffer> decrypted_data = decryptor_.Decrypt(encrypted_data_);
+ EXPECT_FALSE(decrypted_data.get());
+}
+
+} // media