Remove the build dependency on Chromium. Change-Id: I09b62c24fcdb83b33ab16b8fd64d838c8a4c9cff
diff --git a/webm_crypt/Makefile b/webm_crypt/Makefile index c52bf99..35309f4 100644 --- a/webm_crypt/Makefile +++ b/webm_crypt/Makefile
@@ -1,24 +1,12 @@ LIBWEBM = ../../libwebm -CHROMIUMINC = /usr/local/google/Chromium/src -CHROMIUMOBJ = $(CHROMIUMINC)/out/Debug/obj -OBJECTS = ../shared/webm_endian.o webm_crypt.o +OBJECTS = webm_crypt.o EXE = webm_crypt -INCLUDES = -I$(LIBWEBM) -I../shared -I$(CHROMIUMINC) -I/usr/include/nss \ - -I/usr/include/nspr -CXXFLAGS = -W -Wall -g -DUSE_NSS -std=c++11 +INCLUDES = -I$(LIBWEBM) -I../shared +CXXFLAGS = -W -Wall -g -std=c++11 $(EXE): $(OBJECTS) $(CXX) $(OBJECTS) -L$(LIBWEBM) \ - -L$(CHROMIUMOBJ)/base -L$(CHROMIUMOBJ)/crypto \ - -L$(CHROMIUMOBJ)/base/third_party/dynamic_annotations \ - -L$(CHROMIUMOBJ)/third_party/boringssl \ - -Wl,-rpath,$(CHROMIUMOBJ)/base,-rpath,$(CHROMIUMOBJ)/crypto \ - -Wl,-rpath,$(CHROMIUMOBJ)/base/third_party/dynamic_annotations \ - -Wl,-rpath,$(CHROMIUMOBJ)/third_party/boringssl \ - -lwebm -lcrcrypto \ - -lbase -lbase_static -lsymbolize -ldynamic_annotations -lboringssl \ - -ldl -lrt -lglib-2.0 -lnss3 \ - -lnssutil3 -lnspr4 -lpthread -o $@ + -lwebm -lcrypto -ldl -o $@ %.o: %.cc $(CXX) -c $(CXXFLAGS) $(INCLUDES) $< -o $@
diff --git a/webm_crypt/Readme.txt b/webm_crypt/Readme.txt index 3c2f87e..4bc0ac9 100644 --- a/webm_crypt/Readme.txt +++ b/webm_crypt/Readme.txt
@@ -6,25 +6,29 @@ // in the file PATENTS. All contributing project authors may // be found in the AUTHORS file in the root of the source tree. -// This application uses the crypto library from the Chromium project. +// This application uses the webm library from the libwebm project. // Build instructions for Windows: -1. Follow http://www.chromium.org/developers/how-tos/build-instructions-windows - until the Building Chromium step to get the crypto lib source code. -2. Build the chromium/src/base/base.sln, chromium/src/crypto/crypto.sln, and - chromium/src/base/third_party/dynamic_annotations.sln solutions. -3. Get the libwebm source code. - git clone http://git.chromium.org/webm/libwebm.git -4. Choose the configuration that matches the chromium libs. i.e. "Debug DLL", - "Debug", "Release", or "Release DLL" -5. Build libwebm. -6. Open environment.props file and change CHROMIUM_INC's value to your - Chromium src directory. +1. Install cygwin. + Note: These instructions were written using cygwin + x86_64, but should work with the x86 version. +2. Using the cygwin package manager, make sure make and g++ + are installed. +3. Clone libwebm into the same directory as webm-tools. The libwebm and + webm-tools directories must be siblings in the same root directory. +4. In the libwebm repository, run: + $ make -f Makefile.unix +5. Back in the webm_crypt source directory, run: + $ make +6. To confirm webm_crypt works, run: + $ webm_crypt -test -// Build instructions for Linux: -1. Follow http://code.google.com/p/chromium/wiki/LinuxBuildInstructions to - build chrome application. -2. Get the libwebm source code. - git clone http://git.chromium.org/webm/libwebm.git -3. Build libwebm. -4. Change Makefile to point to your libs and build. +// Build instructions for Linux and Mac: +1. Clone libwebm into the same directory as webm-tools. The libwebm and + webm-tools directories must be siblings in the same root directory. +2. In the libwebm repository, run: + $ make -f Makefile.unix +3. Back in the webm_crypt source directory, run: + $ make +4. To confirm webm_crypt works, run: + $ webm_crypt -test
diff --git a/webm_crypt/aes_ctr.h b/webm_crypt/aes_ctr.h new file mode 100644 index 0000000..862b638 --- /dev/null +++ b/webm_crypt/aes_ctr.h
@@ -0,0 +1,66 @@ +// Copyright (c) 2015 The WebM project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. + +#include <stdint.h> +#include <cstdlib> +#include <cstring> +#include <iostream> +#include <string> + +#include <openssl/aes.h> +#include <openssl/buffer.h> +#include <openssl/conf.h> +#include <openssl/err.h> +#include <openssl/evp.h> +#include <openssl/hmac.h> +#include <openssl/rand.h> + +using namespace std; + +// This class implements AES-CTR encryption. Only 128-bits Initialization +// Vector is supported in this class. +class AesCtr128Encryptor { + public: + AesCtr128Encryptor() {} + ~AesCtr128Encryptor() {} + + bool InitKey(const string& key) { + if (AES_set_encrypt_key(reinterpret_cast<const unsigned char*>(key.c_str()), + 128, &aes_key_) != 0) { + return false; + } + return true; + } + + bool SetCounter(const string& counter) { + if (counter.size() != AES_BLOCK_SIZE) + return false; + counter_ = counter; + return true; + } + + bool Encrypt(const uint8_t* input, size_t size, uint8_t* output) { + if (counter_.size() != AES_BLOCK_SIZE) { + return false; + } + + uint8_t ivec[AES_BLOCK_SIZE] = { 0 }; + uint8_t ecount_buf[AES_BLOCK_SIZE] = { 0 }; + unsigned int block_offset = 0; + + memcpy(ivec, counter_.c_str(), AES_BLOCK_SIZE); + AES_ctr128_encrypt(input, output, size, &aes_key_, ivec, ecount_buf, + &block_offset); + + return true; + } + + private: + string counter_; + AES_KEY aes_key_; +};
diff --git a/webm_crypt/webm_crypt.cc b/webm_crypt/webm_crypt.cc index cd3018e..a7479f7 100644 --- a/webm_crypt/webm_crypt.cc +++ b/webm_crypt/webm_crypt.cc
@@ -6,14 +6,13 @@ // in the file PATENTS. All contributing project authors may // be found in the AUTHORS file in the root of the source tree. +#include <stdint.h> #include <cstdlib> #include <iostream> +#include <memory> #include <string> -#include "base/at_exit.h" -#include "base/base_switches.h" -#include "crypto/encryptor.h" -#include "crypto/symmetric_key.h" +#include "aes_ctr.h" #include "mkvmuxer.hpp" #include "mkvmuxerutil.hpp" #include "mkvparser.hpp" @@ -22,16 +21,14 @@ #include "webm_constants.h" #include "webm_endian.h" -// This application uses the crypto library from the Chromium project. See the +// This application uses the webm library from the libwebm project. See the // readme.txt for build instructions. -// TODO(fgalligan) Remove Chromium crypto library requirement. namespace { -using crypto::Encryptor; -using crypto::SymmetricKey; using mkvparser::ContentEncoding; using std::string; +using std::unique_ptr; const char WEBM_CRYPT_VERSION_STRING[] = "0.3.1.0"; @@ -55,11 +52,11 @@ string content_id; // Initial Initialization Vector for encryption. - uint64 initial_iv; + uint64_t initial_iv; // Do not encrypt frames that have a start time less than // |unencrypted_range| in milliseconds. - int64 unencrypted_range; + int64_t unencrypted_range; }; // Struct to hold file wide encryption settings. @@ -111,7 +108,7 @@ static const size_t kKeySize = 16; static const size_t kSHA1DigestSize = 20; static const size_t kSignalByteSize = 1; - static const uint8 kEncryptedFrame = 0x1; + static const uint8_t kEncryptedFrame = 0x1; // |enc| Encryption settings for a stream. |secret| Encryption key for a // stream. @@ -121,17 +118,17 @@ // Initializes encryption key. Returns true on success. bool Init(); - // Processes |plaintext| according to the encryption settings, - // |encrypt_frame|, and |key_|. |length| is the size of |plaintext| in bytes. + // Processes |source| according to the encryption settings, + // |encrypt_frame|, and |key_|. |length| is the size of |source| in bytes. // |encrypt_frame| tells the encryptor whether to encrypt the frame or just - // add a signal byte to the unencrypted frame. |ciphertext| is the returned - // encrypted data if |encrypt_frame| is true and signal byte + |plaintext| - // if |encrypt_frame| is false. |ciphertext_size| is the size of |ciphertext| - // in bytes. Returns true if |plaintext| was processed and passed back - // through |ciphertext|. - bool ProcessData(const uint8* plaintext, size_t size, + // add a signal byte to the unencrypted frame. |destination| is the returned + // encrypted data if |encrypt_frame| is true and signal byte + |source| + // if |encrypt_frame| is false. |destination_size| is the size of |destination| + // in bytes. Returns true if |source| was processed and passed back + // through |destination|. + bool ProcessData(const uint8_t* source, size_t size, bool encrypt_frame, - uint8** ciphertext, size_t* ciphertext_size); + uint8_t** destination, size_t* destination_size); void set_do_not_encrypt(bool flag) { do_not_encrypt_ = flag; } @@ -149,10 +146,10 @@ const EncryptionSettings enc_; // Encryption key for the stream. - scoped_ptr<SymmetricKey> key_; + string key_; // The next IV. - uint64 next_iv_; + uint64_t next_iv_; }; EncryptModule::EncryptModule(const EncryptionSettings& enc, @@ -160,37 +157,37 @@ : do_not_encrypt_(false), enc_(enc), next_iv_(enc.initial_iv) { - key_.reset(SymmetricKey::Import(SymmetricKey::AES, secret)); + key_.assign(secret); } bool EncryptModule::Init() { - if (!key_.get()) { + if (key_.size() == 0) { fprintf(stderr, "Error creating encryption key.\n"); return false; } return true; } -bool EncryptModule::ProcessData(const uint8* plaintext, size_t size, +bool EncryptModule::ProcessData(const uint8_t* source, size_t size, bool encrypt_frame, - uint8** ciphertext, size_t* ciphertext_size) { - if (!ciphertext || !ciphertext_size) + uint8_t** destination, + size_t* destination_size) { + if (!source || size <= 0) return false; const bool encrypt_the_frame = do_not_encrypt_ ? false : encrypt_frame; - scoped_ptr<uint8[]> cipher_temp; + unique_ptr<uint8_t[]> cipher_temp; size_t cipher_temp_size = size + kSignalByteSize; if (encrypt_the_frame) { - Encryptor encryptor; - if (!encryptor.Init(key_.get(), Encryptor::CTR, "")) { + AesCtr128Encryptor encryptor; + if (!encryptor.InitKey(key_)) { fprintf(stderr, "Could not initialize encryptor.\n"); return false; } // Set the IV. - const uint64 iv = next_iv_++; - + const uint64_t iv = next_iv_++; const string iv_str(reinterpret_cast<const char*>(&iv), sizeof(iv)); string counter_block; if (!GenerateCounterBlock(iv_str, &counter_block)) { @@ -203,36 +200,30 @@ return false; } - const string data_to_encrypt(reinterpret_cast<const char*>(plaintext), - size); - string encrypted_text; - if (!encryptor.Encrypt(data_to_encrypt, &encrypted_text)) { - fprintf(stderr, "Could not encrypt data.\n"); - return false; - } - // Prepend the IV. cipher_temp_size += sizeof(iv); - cipher_temp.reset(new (std::nothrow) uint8[cipher_temp_size]); // NOLINT + cipher_temp.reset(new (std::nothrow) uint8_t[cipher_temp_size]); // NOLINT if (!cipher_temp.get()) return false; memcpy(cipher_temp.get() + kSignalByteSize, &iv, sizeof(iv)); - memcpy(cipher_temp.get() + sizeof(iv) + kSignalByteSize, - encrypted_text.data(), encrypted_text.size()); + if (!encryptor.Encrypt(source, size, + cipher_temp.get() + sizeof(iv) + kSignalByteSize)) { + fprintf(stderr, "Could not encrypt data.\n"); + return false; + } } else { - cipher_temp.reset(new (std::nothrow) uint8[cipher_temp_size]); // NOLINT + cipher_temp.reset(new (std::nothrow) uint8_t[cipher_temp_size]); // NOLINT if (!cipher_temp.get()) return false; - memcpy(cipher_temp.get() + kSignalByteSize, - reinterpret_cast<const char*>(plaintext), size); + memcpy(cipher_temp.get() + kSignalByteSize, source, size); } - const uint8 signal_byte = encrypt_the_frame ? kEncryptedFrame : 0; + const uint8_t signal_byte = encrypt_the_frame ? kEncryptedFrame : 0; cipher_temp[0] = signal_byte; - *ciphertext = cipher_temp.release(); - *ciphertext_size = cipher_temp_size; + *destination = cipher_temp.release(); + *destination_size = cipher_temp_size; return true; } @@ -264,12 +255,13 @@ // success. bool Init(); - // Decrypts |data| according to the encryption settings and encryption key. - // |length| is the size of |data| in bytes. |decrypttext| is the returned - // decrypted data if |data| was decrypted. If data was unencrypted then - // |decrypttext| is the original plaintext. Returns true if |data| was - // decrypted and passed back through |decrypttext|. - bool DecryptData(const uint8* data, size_t length, string* decrypttext); + // Decrypts |source| according to the encryption settings and encryption key. + // |length| is the size of |source| in bytes. |destination| is the returned + // decrypted data if |source| was decrypted. If data was unencrypted then + // |destination| is the original data. Returns true if |data| was decrypted + // and passed back through |destination|. + bool DecryptData(const uint8_t* data, size_t length, uint8_t* destination, + size_t *destination_size); private: // Flag telling if the class should not decrypt the data. This should @@ -280,10 +272,10 @@ const EncryptionSettings enc_; // Encryption key for the stream. - scoped_ptr<SymmetricKey> key_; + string key_; // Decryption class. - Encryptor encryptor_; + AesCtr128Encryptor encryptor_; }; DecryptModule::DecryptModule(const EncryptionSettings& enc, @@ -291,17 +283,17 @@ bool no_decrypt) : do_not_decrypt_(no_decrypt), enc_(enc) { - key_.reset(SymmetricKey::Import(SymmetricKey::AES, secret)); + key_.assign(secret); } bool DecryptModule::Init() { - if (!key_.get()) { + if (key_.size() == 0) { fprintf(stderr, "Error creating encryption key.\n"); return false; } if (!do_not_decrypt_) { - if (!encryptor_.Init(key_.get(), Encryptor::CTR, "")) { + if (!encryptor_.InitKey(key_)) { fprintf(stderr, "Could not initialize decryptor.\n"); return false; } @@ -309,17 +301,19 @@ return true; } -bool DecryptModule::DecryptData(const uint8* data, size_t length, - string* decrypttext) { - if (!decrypttext) +bool DecryptModule::DecryptData(const uint8_t* source, size_t length, + uint8_t* destination, size_t *destination_size) { + if (!source || length <= 0) return false; + size_t offset = 0; + if (!do_not_decrypt_) { if (length == 0) { fprintf(stderr, "Length of encrypted data is 0.\n"); return false; } - const uint8 signal_byte = data[0]; + const uint8_t signal_byte = source[0]; if (signal_byte & EncryptModule::kEncryptedFrame) { if (length < EncryptModule::kSignalByteSize + EncryptModule::kIVSize) { @@ -328,7 +322,7 @@ } const char* iv_data = - reinterpret_cast<const char*>(data + EncryptModule::kSignalByteSize); + reinterpret_cast<const char*>(source + EncryptModule::kSignalByteSize); const string iv(iv_data, EncryptModule::kIVSize); string counter_block; @@ -342,28 +336,22 @@ return false; } - const size_t offset = - EncryptModule::kSignalByteSize + EncryptModule::kIVSize; + offset = EncryptModule::kSignalByteSize + EncryptModule::kIVSize; - // Skip past the IV. - const string encryptedtext( - reinterpret_cast<const char*>(data + offset), - length - offset); - if (!encryptor_.Decrypt(encryptedtext, decrypttext)) { + if (!encryptor_.Encrypt(source + offset, length - offset, destination)) { fprintf(stderr, "Could not decrypt data.\n"); return false; } } else { - const size_t offset = EncryptModule::kSignalByteSize; - decrypttext->assign(reinterpret_cast<const char*>(data + offset), - length - offset); + offset = EncryptModule::kSignalByteSize; + memcpy(destination, source + offset, length - offset); } } else { - const size_t offset = EncryptModule::kSignalByteSize; - decrypttext->assign(reinterpret_cast<const char*>(data + offset), - length - offset); + offset = EncryptModule::kSignalByteSize; + memcpy(destination, source + offset, length - offset); } + *destination_size = length - offset; return true; } @@ -384,7 +372,7 @@ printf(" \n"); printf("-audio_options <string> Comma separated name value pair.\n"); printf(" content_id=<string> Encryption content ID. (Default empty)\n"); - printf(" initial_iv=<uint64> Initial IV value. (Default random)\n"); + printf(" initial_iv=<uint64_t> Initial IV value. (Default random)\n"); printf(" base_file=<string> Path to base secret file. (Default\n"); printf(" empty)\n"); printf(" unencrypted_range=<int64> Do not encrypt frames from\n"); @@ -392,7 +380,7 @@ printf(" \n"); printf("-video_options <string> Comma separated name value pair.\n"); printf(" content_id=<string> Encryption content ID. (Default empty)\n"); - printf(" initial_iv=<uint64> Initial IV value. (Default random)\n"); + printf(" initial_iv=<uint64_t> Initial IV value. (Default random)\n"); printf(" base_file=<string> Path to base secret file. (Default\n"); printf(" empty)\n"); printf(" unencrypted_range=<int64> Do not encrypt frames from\n"); @@ -403,24 +391,23 @@ using std::cout; using std::endl; - scoped_ptr<SymmetricKey> sym_key( - SymmetricKey::GenerateRandomKey(SymmetricKey::AES, 128)); + unsigned char enc_key[AES_BLOCK_SIZE] = { 0 }; + const string kInitialCounter(16, '0'); + AesCtr128Encryptor encryptor; - string raw_key; - if (!sym_key->GetRawKey(&raw_key)) { - fprintf(stderr, "Could not get raw key.\n"); + // Generate a random key. + if (!RAND_bytes(enc_key, AES_BLOCK_SIZE)) { + cout << "Fail to generate a random encode key" << endl; return; } - const string kInitialCounter(16, '0'); - - Encryptor encryptor; - // The IV must be exactly as long as the cipher block size. - bool b = encryptor.Init(sym_key.get(), Encryptor::CTR, ""); + string key_string(reinterpret_cast<const char*>(enc_key)); + bool b = encryptor.InitKey(key_string); if (!b) { fprintf(stderr, "Could not initialize encrypt object.\n"); return; } + b = encryptor.SetCounter(kInitialCounter); if (!b) { fprintf(stderr, "Could not SetCounter on encryptor.\n"); @@ -428,12 +415,16 @@ } string plaintext("this is the plaintext"); - string ciphertext; - b = encryptor.Encrypt(plaintext, &ciphertext); + size_t size = plaintext.size(); + unique_ptr<uint8_t[]> out(new uint8_t[size]); + + b = encryptor.Encrypt(reinterpret_cast<const uint8_t*>(plaintext.c_str()), + size, out.get()); if (!b) { fprintf(stderr, "Could not encrypt data.\n"); return; } + string ciphertext(out.get(), out.get() + size); b = encryptor.SetCounter(kInitialCounter); if (!b) { @@ -441,24 +432,26 @@ return; } - string decrypted; - b = encryptor.Decrypt(ciphertext, &decrypted); + b = encryptor.Encrypt(reinterpret_cast<const uint8_t*>(ciphertext.c_str()), + size, out.get()); if (!b) { fprintf(stderr, "Could not decrypt data.\n"); return; } + string decrypted(out.get(), out.get() + size); + printf("Test 1 finished.\n"); cout << "iv :" << kInitialCounter << endl; - cout << "raw_key :" << raw_key << endl; + cout << "raw_key :" << enc_key << endl; cout << "plaintext :" << plaintext << endl; cout << "ciphertext :" << ciphertext << endl; cout << "decrypted :" << decrypted << endl; const int kNonAsciiSize = 256; - uint8 raw_data[kNonAsciiSize]; + uint8_t raw_data[kNonAsciiSize]; for (int i = 0; i < kNonAsciiSize; ++i) { - raw_data[i] = static_cast<uint8>(i); + raw_data[i] = static_cast<uint8_t>(i); } string non_ascii(reinterpret_cast<char*>(raw_data), kNonAsciiSize); @@ -468,11 +461,13 @@ return; } - b = encryptor.Encrypt(non_ascii, &ciphertext); + out.reset(new (std::nothrow) uint8_t[kNonAsciiSize]); // NOLINT + b = encryptor.Encrypt(raw_data, kNonAsciiSize, out.get()); if (!b) { fprintf(stderr, "Could not encrypt data.\n"); return; } + ciphertext = string(out.get(), out.get() + kNonAsciiSize); b = encryptor.SetCounter(kInitialCounter); if (!b) { @@ -480,11 +475,13 @@ return; } - b = encryptor.Decrypt(ciphertext, &decrypted); + b = encryptor.Encrypt(reinterpret_cast<const uint8_t*>(ciphertext.c_str()), + kNonAsciiSize, out.get()); if (!b) { fprintf(stderr, "Could not decrypt data.\n"); return; } + decrypted = string(out.get(), out.get() + kNonAsciiSize); printf("Test 2 finished.\n"); cout << "iv :" << kInitialCounter << endl; @@ -500,11 +497,16 @@ return; } - b = encryptor.Encrypt(non_ascii, &ciphertext); + size = non_ascii.size(); + out.reset(new (std::nothrow) uint8_t[size]); // NOLINT + b = encryptor.Encrypt(reinterpret_cast<const uint8_t*>(non_ascii.c_str()), + size, out.get()); if (!b) { fprintf(stderr, "Could not encrypt data.\n"); return; } + ciphertext = string(out.get(), out.get() + size); + b = encryptor.SetCounter(kInitialCounter); if (!b) { @@ -512,11 +514,13 @@ return; } - b = encryptor.Decrypt(ciphertext, &decrypted); + b = encryptor.Encrypt(reinterpret_cast<const uint8_t*>(ciphertext.c_str()), + size, out.get()); if (!b) { fprintf(stderr, "Could not decrypt data.\n"); return; } + decrypted = string(out.get(), out.get() + size); printf("Test 3 finished.\n"); cout << "iv :" << kInitialCounter << endl; @@ -534,9 +538,9 @@ bool OpenWebMFiles(const string& input, const string& output, mkvparser::MkvReader* reader, - scoped_ptr<mkvparser::Segment>* parser, + unique_ptr<mkvparser::Segment>* parser, mkvmuxer::MkvWriter* writer, - scoped_ptr<mkvmuxer::Segment>* muxer) { + unique_ptr<mkvmuxer::Segment>* muxer) { if (!reader || !parser || !writer || !muxer) return false; @@ -553,7 +557,7 @@ } mkvparser::Segment* parser_segment; - int64 ret = mkvparser::Segment::CreateInstance(reader, pos, parser_segment); + int64_t ret = mkvparser::Segment::CreateInstance(reader, pos, parser_segment); if (ret) { fprintf(stderr, "Segment::CreateInstance() failed."); return false; @@ -567,7 +571,7 @@ } const mkvparser::SegmentInfo* const segment_info = (*parser)->GetInfo(); - const int64 timeCodeScale = segment_info->GetTimeCodeScale(); + const int64_t timeCodeScale = segment_info->GetTimeCodeScale(); // Set muxer header info if (!writer->Open(output.c_str())) { @@ -604,7 +608,7 @@ const int key_size = ftell(f); fseek(f, 0, SEEK_SET); - scoped_ptr<char[]> raw_key_buf(new (std::nothrow) char[key_size]); // NOLINT + unique_ptr<char[]> raw_key_buf(new (std::nothrow) char[key_size]); // NOLINT const int bytes_read = fread(raw_key_buf.get(), 1, key_size, f); fclose(f); @@ -621,34 +625,29 @@ if (!data) return false; - string temp; - while (temp.length() < length) { - scoped_ptr<SymmetricKey> key( - SymmetricKey::GenerateRandomKey(SymmetricKey::AES, 128)); - string raw_key; - if (!key->GetRawKey(&raw_key)) { - fprintf(stderr, "Error generating base secret data.\n"); - return false; - } - temp.append(raw_key); + unique_ptr<unsigned char[]> temp(new unsigned char[length]); + if (!RAND_bytes(temp.get(), length)) { + fprintf(stderr, "Error generating base secret data.\n"); + return false; } - data->assign(temp, 0, length); + string newString(temp.get(), temp.get() + length); + data->assign(newString); return true; } -// Generate random value for a uint64. |value| output uint64 that contains +// Generate random value for a uint64_t. |value| output uint64_t that contains // the data. Returns true on success. -bool GenerateRandomUInt64(uint64* value) { +bool GenerateRandomuint64_t(uint64_t* value) { if (!value) return false; - scoped_ptr<SymmetricKey> key( - SymmetricKey::GenerateRandomKey(SymmetricKey::AES, 128)); - string raw_key; - if (!key->GetRawKey(&raw_key) || raw_key.length() < sizeof(*value)) + unsigned char* temp = reinterpret_cast<unsigned char*>(value); + if (!RAND_bytes(temp, sizeof(uint64_t))) { + fprintf(stderr, "Error generating base secret data.\n"); return false; - memcpy(value, raw_key.data(), sizeof(*value)); + } + return true; } @@ -808,8 +807,8 @@ int WebMEncrypt(const WebMCryptSettings& webm_crypt) { mkvparser::MkvReader reader; mkvmuxer::MkvWriter writer; - scoped_ptr<mkvparser::Segment> parser_segment; - scoped_ptr<mkvmuxer::Segment> muxer_segment; + unique_ptr<mkvparser::Segment> parser_segment; + unique_ptr<mkvmuxer::Segment> muxer_segment; const bool b = OpenWebMFiles(webm_crypt.input, webm_crypt.output, &reader, @@ -823,9 +822,9 @@ // Set Tracks element attributes const mkvparser::Tracks* const parser_tracks = parser_segment->GetTracks(); - uint32 i = 0; - uint64 vid_track = 0; // no track added - uint64 aud_track = 0; // no track added + uint32_t i = 0; + uint64_t vid_track = 0; // no track added + uint64_t aud_track = 0; // no track added string aud_base_secret; string vid_base_secret; @@ -839,14 +838,14 @@ continue; const char* const track_name = parser_track->GetNameAsUTF8(); - const int64 track_type = parser_track->GetType(); + const int64_t track_type = parser_track->GetType(); if (track_type == mkvparser::Track::kVideo) { // Get the video track from the parser const mkvparser::VideoTrack* const pVideoTrack = reinterpret_cast<const mkvparser::VideoTrack*>(parser_track); - const int64 width = pVideoTrack->GetWidth(); - const int64 height = pVideoTrack->GetHeight(); + const int64_t width = pVideoTrack->GetWidth(); + const int64_t height = pVideoTrack->GetHeight(); // Add the video track to the muxer. 0 tells muxer to decide on track // number. @@ -914,7 +913,7 @@ } } if (!encoding->SetEncryptionID( - reinterpret_cast<const uint8*>(id.data()), id.size())) { + reinterpret_cast<const uint8_t*>(id.data()), id.size())) { fprintf(stderr, "Could not set encryption id for video track.\n"); return -1; } @@ -923,7 +922,7 @@ // Get the audio track from the parser const mkvparser::AudioTrack* const pAudioTrack = reinterpret_cast<const mkvparser::AudioTrack*>(parser_track); - const int64 channels = pAudioTrack->GetChannels(); + const int64_t channels = pAudioTrack->GetChannels(); const double sample_rate = pAudioTrack->GetSamplingRate(); // Add the audio track to the muxer. 0 tells muxer to decide on track @@ -955,7 +954,7 @@ audio->set_seek_pre_roll(pAudioTrack->GetSeekPreRoll()); size_t private_size; - const uint8* const private_data = + const uint8_t* const private_data = pAudioTrack->GetCodecPrivate(private_size); if (private_size > 0) { if (!audio->SetCodecPrivate(private_data, private_size)) { @@ -964,7 +963,7 @@ } } - const int64 bit_depth = pAudioTrack->GetBitDepth(); + const int64_t bit_depth = pAudioTrack->GetBitDepth(); if (bit_depth > 0) audio->set_bit_depth(bit_depth); @@ -1006,7 +1005,7 @@ } } if (!encoding->SetEncryptionID( - reinterpret_cast<const uint8*>(id.data()), id.size())) { + reinterpret_cast<const uint8_t*>(id.data()), id.size())) { fprintf(stderr, "Could not set encryption id for video track.\n"); return -1; } @@ -1018,7 +1017,7 @@ muxer_segment->CuesTrack(vid_track); // Write clusters - scoped_ptr<uint8[]> data; + unique_ptr<uint8_t[]> data; int data_len = 0; EncryptModule audio_encryptor(webm_crypt.aud_enc, aud_base_secret); if (webm_crypt.audio && !audio_encryptor.Init()) { @@ -1044,16 +1043,16 @@ while ((block_entry != NULL) && !block_entry->EOS()) { const mkvparser::Block* const block = block_entry->GetBlock(); - const int64 trackNum = block->GetTrackNumber(); + const int64_t trackNum = block->GetTrackNumber(); const mkvparser::Track* const parser_track = - parser_tracks->GetTrackByNumber(static_cast<uint32>(trackNum)); - const int64 track_type = parser_track->GetType(); + parser_tracks->GetTrackByNumber(static_cast<uint32_t>(trackNum)); + const int64_t track_type = parser_track->GetType(); if ((track_type == mkvparser::Track::kAudio) || (track_type == mkvparser::Track::kVideo)) { const int frame_count = block->GetFrameCount(); - const int64 time_ns = block->GetTime(cluster); - const int64 time_milli = + const int64_t time_ns = block->GetTime(cluster); + const int64_t time_milli = time_ns / webm_tools::kNanosecondsPerMillisecond; const bool is_key = block->IsKey(); @@ -1061,7 +1060,7 @@ const mkvparser::Block::Frame& frame = block->GetFrame(i); if (frame.len > data_len) { - data.reset(new (std::nothrow) uint8[frame.len]); // NOLINT + data.reset(new (std::nothrow) uint8_t[frame.len]); // NOLINT if (!data.get()) return -1; data_len = frame.len; @@ -1075,12 +1074,12 @@ prev_cluster = cluster; } - const uint64 track_num = + const uint64_t track_num = (track_type == mkvparser::Track::kAudio) ? aud_track : vid_track; if ((track_type == mkvparser::Track::kVideo && webm_crypt.video) || (track_type == mkvparser::Track::kAudio && webm_crypt.audio) ) { - uint8* ciphertext; + uint8_t* ciphertext; size_t ciphertext_size; const bool encrypt_frame = time_milli >= webm_crypt.aud_enc.unencrypted_range; @@ -1115,7 +1114,6 @@ fprintf(stderr, "Could not add encrypted frame.\n"); return -1; } - } else { if (!muxer_segment->AddFrame(data.get(), frame.len, @@ -1164,8 +1162,8 @@ int WebMDecrypt(const WebMCryptSettings& webm_crypt) { mkvparser::MkvReader reader; mkvmuxer::MkvWriter writer; - scoped_ptr<mkvparser::Segment> parser_segment; - scoped_ptr<mkvmuxer::Segment> muxer_segment; + unique_ptr<mkvparser::Segment> parser_segment; + unique_ptr<mkvmuxer::Segment> muxer_segment; const bool b = OpenWebMFiles(webm_crypt.input, webm_crypt.output, &reader, @@ -1179,9 +1177,9 @@ // Set Tracks element attributes const mkvparser::Tracks* const parser_tracks = parser_segment->GetTracks(); - uint32 i = 0; - uint64 vid_track = 0; // no track added - uint64 aud_track = 0; // no track added + uint32_t i = 0; + uint64_t vid_track = 0; // no track added + uint64_t aud_track = 0; // no track added EncryptionSettings aud_enc; EncryptionSettings vid_enc; bool decrypt_video = false; @@ -1199,14 +1197,14 @@ continue; const char* const track_name = parser_track->GetNameAsUTF8(); - const int64 track_type = parser_track->GetType(); + const int64_t track_type = parser_track->GetType(); if (track_type == mkvparser::Track::kVideo) { // Get the video track from the parser const mkvparser::VideoTrack* const pVideoTrack = reinterpret_cast<const mkvparser::VideoTrack*>(parser_track); - const int64 width = pVideoTrack->GetWidth(); - const int64 height = pVideoTrack->GetHeight(); + const int64_t width = pVideoTrack->GetWidth(); + const int64_t height = pVideoTrack->GetHeight(); // Add the video track to the muxer. 0 tells muxer to decide on track // number. @@ -1265,7 +1263,7 @@ // Get the audio track from the parser const mkvparser::AudioTrack* const pAudioTrack = reinterpret_cast<const mkvparser::AudioTrack*>(parser_track); - const int64 channels = pAudioTrack->GetChannels(); + const int64_t channels = pAudioTrack->GetChannels(); const double sample_rate = pAudioTrack->GetSamplingRate(); // Add the audio track to the muxer. 0 tells muxer to decide on track @@ -1297,7 +1295,7 @@ audio->set_seek_pre_roll(pAudioTrack->GetSeekPreRoll()); size_t private_size; - const uint8* const private_data = + const uint8_t* const private_data = pAudioTrack->GetCodecPrivate(private_size); if (private_size > 0) { if (!audio->SetCodecPrivate(private_data, private_size)) { @@ -1306,7 +1304,7 @@ } } - const int64 bit_depth = pAudioTrack->GetBitDepth(); + const int64_t bit_depth = pAudioTrack->GetBitDepth(); if (bit_depth > 0) audio->set_bit_depth(bit_depth); @@ -1341,7 +1339,7 @@ muxer_segment->CuesTrack(vid_track); // Write clusters - scoped_ptr<uint8[]> data; + unique_ptr<uint8_t[]> data; int data_len = 0; DecryptModule audio_decryptor(aud_enc, aud_base_secret, @@ -1368,22 +1366,22 @@ while ((block_entry != NULL) && !block_entry->EOS()) { const mkvparser::Block* const block = block_entry->GetBlock(); - const int64 trackNum = block->GetTrackNumber(); + const int64_t trackNum = block->GetTrackNumber(); const mkvparser::Track* const parser_track = - parser_tracks->GetTrackByNumber(static_cast<uint32>(trackNum)); - const int64 track_type = parser_track->GetType(); + parser_tracks->GetTrackByNumber(static_cast<uint32_t>(trackNum)); + const int64_t track_type = parser_track->GetType(); if ((track_type == mkvparser::Track::kAudio) || (track_type == mkvparser::Track::kVideo)) { const int frame_count = block->GetFrameCount(); - const int64 time_ns = block->GetTime(cluster); + const int64_t time_ns = block->GetTime(cluster); const bool is_key = block->IsKey(); for (int i = 0; i < frame_count; ++i) { const mkvparser::Block::Frame& frame = block->GetFrame(i); if (frame.len > data_len) { - data.reset(new (std::nothrow) uint8[frame.len]); // NOLINT + data.reset(new (std::nothrow) uint8_t[frame.len]); // NOLINT if (!data.get()) return -1; data_len = frame.len; @@ -1392,32 +1390,35 @@ if (frame.Read(&reader, data.get())) return -1; - const uint64 track_num = + const uint64_t track_num = (track_type == mkvparser::Track::kAudio) ? aud_track : vid_track; if ((track_type == mkvparser::Track::kVideo && decrypt_video) || (track_type == mkvparser::Track::kAudio && decrypt_audio) ) { - string decrypttext; + unique_ptr<uint8_t[]> decrypttext(new uint8_t[frame.len]); + size_t decrypttext_size = 0; if (track_type == mkvparser::Track::kAudio) { if (!audio_decryptor.DecryptData(data.get(), frame.len, - &decrypttext)) { + decrypttext.get(), + &decrypttext_size)) { fprintf(stderr, "Could not decrypt audio data.\n"); return -1; } } else { if (!video_decryptor.DecryptData(data.get(), frame.len, - &decrypttext)) { + decrypttext.get(), + &decrypttext_size)) { fprintf(stderr, "Could not decrypt video data.\n"); return -1; } } - if (!decrypttext.empty()) { + if (decrypttext_size != 0) { if (!muxer_segment->AddFrame( - reinterpret_cast<const uint8*>(decrypttext.data()), - decrypttext.size(), + decrypttext.get(), + decrypttext_size, track_num, time_ns, is_key)) { @@ -1425,7 +1426,6 @@ return -1; } } - } else { if (!muxer_segment->AddFrame(data.get(), frame.len, @@ -1469,17 +1469,16 @@ } // namespace int main(int argc, char* argv[]) { - base::AtExitManager *at_exit_manager = new base::AtExitManager(); WebMCryptSettings webm_crypt_settings; bool encrypt = true; bool test = false; // Create initial random IV values. - if (!GenerateRandomUInt64(&webm_crypt_settings.aud_enc.initial_iv)) { + if (!GenerateRandomuint64_t(&webm_crypt_settings.aud_enc.initial_iv)) { fprintf(stderr, "Could not generate initial IV value.\n"); return EXIT_FAILURE; } - if (!GenerateRandomUInt64(&webm_crypt_settings.vid_enc.initial_iv)) { + if (!GenerateRandomuint64_t(&webm_crypt_settings.vid_enc.initial_iv)) { fprintf(stderr, "Could not generate initial IV value.\n"); return EXIT_FAILURE; }