Add CTR encryption.
- Added ContentEncAESSettings, AESSettingsCipherMode, AESSettingsCipherInitData elements to the parser and muxer. - Changed ParseContentEncodingsEntry, ParseContentEncodingEntry, and ParseEncryptionEntry to use PasreElementHeader. - Added ParseContentEncAESSettingsEntry function. - PS6 removed AESSettingsCipherInitData. - PS9 Addressed comments, Fixed some LINT issues, and converted mkvwriter.h/.cpp to Unix line endings. - PS10 Addressed comments. Change-Id: I9d96a0c194f74a6c9bf0001aa0286196e410f07e
This commit is contained in:
464
mkvparser.cpp
464
mkvparser.cpp
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
|
||||
// Copyright (c) 2012 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
|
||||
@@ -4478,11 +4478,147 @@ unsigned long ContentEncoding::GetEncryptionCount() const {
|
||||
return static_cast<unsigned long>(count);
|
||||
}
|
||||
|
||||
void ContentEncoding::ParseEncryptionEntry(
|
||||
long ContentEncoding::ParseContentEncAESSettingsEntry(
|
||||
long long start,
|
||||
long long size,
|
||||
IMkvReader* const pReader,
|
||||
ContentEncryption* const encryption) {
|
||||
IMkvReader* pReader,
|
||||
ContentEncAESSettings* aes) {
|
||||
assert(pReader);
|
||||
assert(aes);
|
||||
|
||||
long long pos = start;
|
||||
const long long stop = start + size;
|
||||
|
||||
while (pos < stop) {
|
||||
long long id, size;
|
||||
const long status = ParseElementHeader(pReader,
|
||||
pos,
|
||||
stop,
|
||||
id,
|
||||
size);
|
||||
if (status < 0) //error
|
||||
return status;
|
||||
|
||||
if (id == 0x7E8) {
|
||||
// AESSettingsCipherMode
|
||||
aes->cipher_mode = UnserializeUInt(pReader, pos, size);
|
||||
if (aes->cipher_mode != 1)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
}
|
||||
|
||||
pos += size; //consume payload
|
||||
assert(pos <= stop);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long ContentEncoding::ParseContentEncodingEntry(long long start,
|
||||
long long size,
|
||||
IMkvReader* pReader) {
|
||||
assert(pReader);
|
||||
|
||||
long long pos = start;
|
||||
const long long stop = start + size;
|
||||
|
||||
// Count ContentCompression and ContentEncryption elements.
|
||||
int compression_count = 0;
|
||||
int encryption_count = 0;
|
||||
|
||||
while (pos < stop) {
|
||||
long long id, size;
|
||||
const long status = ParseElementHeader(pReader,
|
||||
pos,
|
||||
stop,
|
||||
id,
|
||||
size);
|
||||
if (status < 0) //error
|
||||
return status;
|
||||
|
||||
if (id == 0x1034) // ContentCompression ID
|
||||
++compression_count;
|
||||
|
||||
if (id == 0x1035) // ContentEncryption ID
|
||||
++encryption_count;
|
||||
|
||||
pos += size; //consume payload
|
||||
assert(pos <= stop);
|
||||
}
|
||||
|
||||
if (compression_count <= 0 && encryption_count <= 0)
|
||||
return -1;
|
||||
|
||||
if (compression_count > 0) {
|
||||
compression_entries_ =
|
||||
new (std::nothrow) ContentCompression*[compression_count];
|
||||
if (!compression_entries_)
|
||||
return -1;
|
||||
compression_entries_end_ = compression_entries_;
|
||||
}
|
||||
|
||||
if (encryption_count > 0) {
|
||||
encryption_entries_ =
|
||||
new (std::nothrow) ContentEncryption*[encryption_count];
|
||||
if (!encryption_entries_) {
|
||||
delete [] compression_entries_;
|
||||
return -1;
|
||||
}
|
||||
encryption_entries_end_ = encryption_entries_;
|
||||
}
|
||||
|
||||
pos = start;
|
||||
while (pos < stop) {
|
||||
long long id, size;
|
||||
long status = ParseElementHeader(pReader,
|
||||
pos,
|
||||
stop,
|
||||
id,
|
||||
size);
|
||||
if (status < 0) //error
|
||||
return status;
|
||||
|
||||
if (id == 0x1031) {
|
||||
// ContentEncodingOrder
|
||||
encoding_order_ = UnserializeUInt(pReader, pos, size);
|
||||
} else if (id == 0x1032) {
|
||||
// ContentEncodingScope
|
||||
encoding_scope_ = UnserializeUInt(pReader, pos, size);
|
||||
if (encoding_scope_ < 1)
|
||||
return -1;
|
||||
} else if (id == 0x1033) {
|
||||
// ContentEncodingType
|
||||
encoding_type_ = UnserializeUInt(pReader, pos, size);
|
||||
} else if (id == 0x1034) {
|
||||
// ContentCompression ID
|
||||
// TODO(fgaligan): Add code to parse ContentCompression elements.
|
||||
} else if (id == 0x1035) {
|
||||
// ContentEncryption ID
|
||||
ContentEncryption* const encryption =
|
||||
new (std::nothrow) ContentEncryption();
|
||||
if (!encryption)
|
||||
return -1;
|
||||
|
||||
status = ParseEncryptionEntry(pos, size, pReader, encryption);
|
||||
if (status) {
|
||||
delete encryption;
|
||||
return status;
|
||||
}
|
||||
*encryption_entries_end_++ = encryption;
|
||||
}
|
||||
|
||||
pos += size; //consume payload
|
||||
assert(pos <= stop);
|
||||
}
|
||||
|
||||
assert(pos == stop);
|
||||
return 0;
|
||||
}
|
||||
|
||||
long ContentEncoding::ParseEncryptionEntry(
|
||||
long long start,
|
||||
long long size,
|
||||
IMkvReader* pReader,
|
||||
ContentEncryption* encryption) {
|
||||
assert(pReader);
|
||||
assert(encryption);
|
||||
|
||||
@@ -4490,166 +4626,111 @@ void ContentEncoding::ParseEncryptionEntry(
|
||||
const long long stop = start + size;
|
||||
|
||||
while (pos < stop) {
|
||||
#ifdef _DEBUG
|
||||
long len;
|
||||
const long long id = ReadUInt(pReader, pos, len);
|
||||
assert(id >= 0); //TODO: handle error case
|
||||
assert((pos + len) <= stop);
|
||||
#endif
|
||||
long long id, size;
|
||||
const long status = ParseElementHeader(pReader,
|
||||
pos,
|
||||
stop,
|
||||
id,
|
||||
size);
|
||||
if (status < 0) //error
|
||||
return status;
|
||||
|
||||
long long value;
|
||||
unsigned char* buf;
|
||||
size_t buf_len;
|
||||
|
||||
if (Match(pReader, pos, 0x7E1, value)) {
|
||||
if (id == 0x7E1) {
|
||||
// ContentEncAlgo
|
||||
encryption->algo = value;
|
||||
} else if (Match(pReader, pos, 0x7E2, buf, buf_len)) {
|
||||
encryption->algo = UnserializeUInt(pReader, pos, size);
|
||||
if (encryption->algo != 5)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
} else if (id == 0x7E2) {
|
||||
// ContentEncKeyID
|
||||
encryption->key_id = buf;
|
||||
encryption->key_id_len = buf_len;
|
||||
} else if (Match(pReader, pos, 0x7E3, buf, buf_len)) {
|
||||
// ContentSignature
|
||||
encryption->signature = buf;
|
||||
encryption->signature_len = buf_len;
|
||||
} else if (Match(pReader, pos, 0x7E4, buf, buf_len)) {
|
||||
// ContentSigKeyID
|
||||
encryption->sig_key_id = buf;
|
||||
encryption->sig_key_id_len = buf_len;
|
||||
} else if (Match(pReader, pos, 0x7E5, value)) {
|
||||
// ContentSigAlgo
|
||||
encoding_type_ = value;
|
||||
} else if (Match(pReader, pos, 0x7E6, value)) {
|
||||
// ContentSigHashAlgo
|
||||
encoding_type_ = value;
|
||||
} else {
|
||||
long len;
|
||||
const long long id = ReadUInt(pReader, pos, len);
|
||||
assert(id >= 0); //TODO: handle error case
|
||||
assert((pos + len) <= stop);
|
||||
delete[] encryption->key_id;
|
||||
encryption->key_id = NULL;
|
||||
encryption->key_id_len = 0;
|
||||
|
||||
pos += len; //consume id
|
||||
if (size <= 0)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
const long long size = ReadUInt(pReader, pos, len);
|
||||
assert(size >= 0); //TODO: handle error case
|
||||
assert((pos + len) <= stop);
|
||||
const size_t buflen = static_cast<size_t>(size);
|
||||
typedef unsigned char* buf_t;
|
||||
const buf_t buf = new (std::nothrow) unsigned char[buflen];
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
pos += len; //consume length of size
|
||||
assert((pos + size) <= stop);
|
||||
|
||||
pos += size; //consume payload
|
||||
assert(pos <= stop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ContentEncoding::ParseContentEncodingEntry(long long start,
|
||||
long long size,
|
||||
IMkvReader* const pReader) {
|
||||
assert(pReader);
|
||||
|
||||
long long pos = start;
|
||||
const long long stop = start + size;
|
||||
|
||||
// Count ContentCompression and ContentEncryption elements.
|
||||
long long pos1 = start;
|
||||
int compression_count = 0;
|
||||
int encryption_count = 0;
|
||||
|
||||
while (pos1 < stop) {
|
||||
long len;
|
||||
const long long id = ReadUInt(pReader, pos1, len);
|
||||
assert(id >= 0);
|
||||
assert((pos1 + len) <= stop);
|
||||
|
||||
pos1 += len; //consume id
|
||||
|
||||
const long long size = ReadUInt(pReader, pos1, len);
|
||||
assert(size >= 0);
|
||||
assert((pos1 + len) <= stop);
|
||||
|
||||
pos1 += len; //consume length of size
|
||||
|
||||
//pos now designates start of element
|
||||
if (id == 0x1034) // ContentCompression ID
|
||||
++compression_count;
|
||||
|
||||
if (id == 0x1035) // ContentEncryption ID
|
||||
++encryption_count;
|
||||
|
||||
pos1 += size; //consume payload
|
||||
assert(pos1 <= stop);
|
||||
}
|
||||
|
||||
if (compression_count <= 0 && encryption_count <= 0)
|
||||
return false;
|
||||
|
||||
if (compression_count > 0) {
|
||||
compression_entries_ = new ContentCompression*[compression_count];
|
||||
compression_entries_end_ = compression_entries_;
|
||||
}
|
||||
|
||||
if (encryption_count > 0) {
|
||||
encryption_entries_ = new ContentEncryption*[encryption_count];
|
||||
encryption_entries_end_ = encryption_entries_;
|
||||
}
|
||||
|
||||
while (pos < stop) {
|
||||
#ifdef _DEBUG
|
||||
long len;
|
||||
const long long id = ReadUInt(pReader, pos, len);
|
||||
assert(id >= 0); //TODO: handle error case
|
||||
assert((pos + len) <= stop);
|
||||
#endif
|
||||
|
||||
long long value;
|
||||
if (Match(pReader, pos, 0x1031, value)) {
|
||||
// ContentEncodingOrder
|
||||
encoding_order_ = value;
|
||||
} else if (Match(pReader, pos, 0x1032, value)) {
|
||||
// ContentEncodingScope
|
||||
encoding_scope_ = value;
|
||||
assert(encoding_scope_ > 0);
|
||||
} else if (Match(pReader, pos, 0x1033, value)) {
|
||||
// ContentEncodingType
|
||||
encoding_type_ = value;
|
||||
} else {
|
||||
long len;
|
||||
const long long id = ReadUInt(pReader, pos, len);
|
||||
assert(id >= 0); //TODO: handle error case
|
||||
assert((pos + len) <= stop);
|
||||
|
||||
pos += len; //consume id
|
||||
|
||||
const long long size = ReadUInt(pReader, pos, len);
|
||||
assert(size >= 0); //TODO: handle error case
|
||||
assert((pos + len) <= stop);
|
||||
|
||||
pos += len; //consume length of size
|
||||
assert((pos + size) <= stop);
|
||||
|
||||
//pos now designates start of payload
|
||||
|
||||
if (id == 0x1034) {
|
||||
// ContentCompression ID
|
||||
// TODO(fgaligan): Add code to parse ContentCompression elements.
|
||||
} else if (id == 0x1035) {
|
||||
// ContentEncryption ID
|
||||
ContentEncryption* const encryption = new ContentEncryption();
|
||||
|
||||
ParseEncryptionEntry(pos, size, pReader, encryption);
|
||||
*encryption_entries_end_ = encryption;
|
||||
++encryption_entries_end_;
|
||||
const int read_status = pReader->Read(pos, buflen, buf);
|
||||
if (read_status) {
|
||||
delete [] buf;
|
||||
return status;
|
||||
}
|
||||
|
||||
pos += size; //consume payload
|
||||
assert(pos <= stop);
|
||||
encryption->key_id = buf;
|
||||
encryption->key_id_len = buflen;
|
||||
} else if (id == 0x7E3) {
|
||||
// ContentSignature
|
||||
delete[] encryption->signature;
|
||||
encryption->signature = NULL;
|
||||
encryption->signature_len = 0;
|
||||
|
||||
if (size <= 0)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
const size_t buflen = static_cast<size_t>(size);
|
||||
typedef unsigned char* buf_t;
|
||||
const buf_t buf = new (std::nothrow) unsigned char[buflen];
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
const int read_status = pReader->Read(pos, buflen, buf);
|
||||
if (read_status) {
|
||||
delete [] buf;
|
||||
return status;
|
||||
}
|
||||
|
||||
encryption->signature = buf;
|
||||
encryption->signature_len = buflen;
|
||||
} else if (id == 0x7E4) {
|
||||
// ContentSigKeyID
|
||||
delete[] encryption->sig_key_id;
|
||||
encryption->sig_key_id = NULL;
|
||||
encryption->sig_key_id_len = 0;
|
||||
|
||||
if (size <= 0)
|
||||
return E_FILE_FORMAT_INVALID;
|
||||
|
||||
const size_t buflen = static_cast<size_t>(size);
|
||||
typedef unsigned char* buf_t;
|
||||
const buf_t buf = new (std::nothrow) unsigned char[buflen];
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
const int read_status = pReader->Read(pos, buflen, buf);
|
||||
if (read_status) {
|
||||
delete [] buf;
|
||||
return status;
|
||||
}
|
||||
|
||||
encryption->sig_key_id = buf;
|
||||
encryption->sig_key_id_len = buflen;
|
||||
} else if (id == 0x7E5) {
|
||||
// ContentSigAlgo
|
||||
encryption->sig_algo = UnserializeUInt(pReader, pos, size);
|
||||
} else if (id == 0x7E6) {
|
||||
// ContentSigHashAlgo
|
||||
encryption->sig_hash_algo = UnserializeUInt(pReader, pos, size);
|
||||
} else if (id == 0x7E7) {
|
||||
// ContentEncAESSettings
|
||||
const long status = ParseContentEncAESSettingsEntry(
|
||||
pos,
|
||||
size,
|
||||
pReader,
|
||||
&encryption->aes_settings);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
pos += size; //consume payload
|
||||
assert(pos <= stop);
|
||||
}
|
||||
|
||||
assert(pos == stop);
|
||||
|
||||
return true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Track::Track(
|
||||
@@ -5038,7 +5119,7 @@ unsigned long Track::GetContentEncodingCount() const {
|
||||
return static_cast<unsigned long>(count);
|
||||
}
|
||||
|
||||
void Track::ParseContentEncodingsEntry(long long start, long long size) {
|
||||
long Track::ParseContentEncodingsEntry(long long start, long long size) {
|
||||
IMkvReader* const pReader = m_pSegment->m_pReader;
|
||||
assert(pReader);
|
||||
|
||||
@@ -5046,70 +5127,71 @@ void Track::ParseContentEncodingsEntry(long long start, long long size) {
|
||||
const long long stop = start + size;
|
||||
|
||||
// Count ContentEncoding elements.
|
||||
long long pos1 = start;
|
||||
int count = 0;
|
||||
while (pos < stop) {
|
||||
long long id, size;
|
||||
const long status = ParseElementHeader(pReader,
|
||||
pos,
|
||||
stop,
|
||||
id,
|
||||
size);
|
||||
if (status < 0) //error
|
||||
return status;
|
||||
|
||||
while (pos1 < stop) {
|
||||
long len;
|
||||
const long long id = ReadUInt(pReader, pos1, len);
|
||||
assert(id >= 0);
|
||||
assert((pos1 + len) <= stop);
|
||||
|
||||
pos1 += len; //consume id
|
||||
|
||||
const long long size = ReadUInt(pReader, pos1, len);
|
||||
assert(size >= 0);
|
||||
assert((pos1 + len) <= stop);
|
||||
|
||||
pos1 += len; //consume length of size
|
||||
|
||||
//pos now designates start of element
|
||||
if (id == 0x2240) // ContentEncoding ID
|
||||
++count;
|
||||
|
||||
pos1 += size; //consume payload
|
||||
assert(pos1 <= stop);
|
||||
pos += size; //consume payload
|
||||
assert(pos <= stop);
|
||||
}
|
||||
|
||||
if (count <= 0)
|
||||
return;
|
||||
return -1;
|
||||
|
||||
content_encoding_entries_ = new (std::nothrow) ContentEncoding*[count];
|
||||
if (!content_encoding_entries_)
|
||||
return -1;
|
||||
|
||||
content_encoding_entries_ = new ContentEncoding*[count];
|
||||
content_encoding_entries_end_ = content_encoding_entries_;
|
||||
|
||||
pos = start;
|
||||
while (pos < stop) {
|
||||
long len;
|
||||
const long long id = ReadUInt(pReader, pos, len);
|
||||
assert(id >= 0);
|
||||
assert((pos + len) <= stop);
|
||||
|
||||
pos += len; //consume id
|
||||
|
||||
const long long size1 = ReadUInt(pReader, pos, len);
|
||||
assert(size1 >= 0);
|
||||
assert((pos + len) <= stop);
|
||||
|
||||
pos += len; //consume length of size
|
||||
long long id, size;
|
||||
long status = ParseElementHeader(pReader,
|
||||
pos,
|
||||
stop,
|
||||
id,
|
||||
size);
|
||||
if (status < 0) //error
|
||||
return status;
|
||||
|
||||
//pos now designates start of element
|
||||
if (id == 0x2240) { // ContentEncoding ID
|
||||
ContentEncoding* const content_encoding = new ContentEncoding();
|
||||
ContentEncoding* const content_encoding =
|
||||
new (std::nothrow) ContentEncoding();
|
||||
if (!content_encoding)
|
||||
return -1;
|
||||
|
||||
if (!content_encoding->ParseContentEncodingEntry(pos, size1, pReader)) {
|
||||
status = content_encoding->ParseContentEncodingEntry(pos,
|
||||
size,
|
||||
pReader);
|
||||
if (status) {
|
||||
delete content_encoding;
|
||||
} else {
|
||||
*content_encoding_entries_end_ = content_encoding;
|
||||
++content_encoding_entries_end_;
|
||||
return status;
|
||||
}
|
||||
|
||||
*content_encoding_entries_end_++ = content_encoding;
|
||||
}
|
||||
|
||||
pos += size1; //consume payload
|
||||
pos += size; //consume payload
|
||||
assert(pos <= stop);
|
||||
}
|
||||
|
||||
assert(pos == stop);
|
||||
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Track::EOSBlock::EOSBlock() :
|
||||
|
||||
Reference in New Issue
Block a user