Chromium Code Reviews| Index: media/webm/webm_cluster_parser.cc |
| diff --git a/media/webm/webm_cluster_parser.cc b/media/webm/webm_cluster_parser.cc |
| index be5e724c14af8d4f0dc23c4f1d98b7e401a031be..b884b53c0a747c9a5ea5294f69bbb1d13c75bf86 100644 |
| --- a/media/webm/webm_cluster_parser.cc |
| +++ b/media/webm/webm_cluster_parser.cc |
| @@ -5,12 +5,34 @@ |
| #include "media/webm/webm_cluster_parser.h" |
| #include "base/logging.h" |
| +#include "base/sys_byteorder.h" |
| #include "media/base/data_buffer.h" |
| #include "media/base/decrypt_config.h" |
| #include "media/webm/webm_constants.h" |
| namespace media { |
| +// Generates a 16 byte CTR counter block. The CTR counter block format is a |
| +// CTR IV appended with a CTR block counter. |iv| is a CTR IV. |iv_size| is |
| +// the size of |iv| in bytes. Returns counter block on success. Returns empty |
| +// string on failure. |
| +static std::string GenerateCounterBlock(const uint8* iv, int iv_size) { |
| + if (iv_size != WebMClusterParser::kIvSize) |
| + return std::string(); |
| + |
| + char counter_block_data[WebMClusterParser::kDecryptionKeySize]; |
| + |
| + // Set the IV. |
| + memcpy(counter_block_data, iv, iv_size); |
| + |
| + // Set block counter to all 0's. |
| + memset(counter_block_data + iv_size, |
| + 0, |
| + WebMClusterParser::kDecryptionKeySize - iv_size); |
| + |
| + return std::string(counter_block_data, WebMClusterParser::kDecryptionKeySize); |
| +} |
| + |
| WebMClusterParser::WebMClusterParser(int64 timecode_scale, |
| int audio_track_num, |
| int video_track_num, |
| @@ -193,15 +215,36 @@ bool WebMClusterParser::OnBlock(int track_num, int timecode, |
| base::TimeDelta timestamp = base::TimeDelta::FromMicroseconds( |
| (cluster_timecode_ + timecode) * timecode_multiplier_); |
| + // Every encrypted Block has an HMAC and IV prepended to it. Current encrypted |
| + // WebM request for comments specification is here |
| + // http://wiki.webmproject.org/encryption/webm-encryption-rfc |
| + bool encrypted = track_num == video_.track_num() && |
| + video_encryption_key_id_.get(); |
|
ddorwin
2012/07/14 00:50:31
any idea why this is "video_"?
fgalligan1
2012/07/16 23:51:42
No, besides the usual private member to the class.
|
| + // If encrypted skip past the HMAC. Encrypted buffers must include the IV and |
| + // the encrypted frame because the decryptor will verify this data before |
| + // decryption. The HMAC and IV will be copied into DecryptConfig. |
| + int offset = (encrypted) ? kWebMHmacSize : 0; |
| + |
| // The first bit of the flags is set when the block contains only keyframes. |
| // http://www.matroska.org/technical/specs/index.html |
| bool is_keyframe = (flags & 0x80) != 0; |
| scoped_refptr<StreamParserBuffer> buffer = |
| - StreamParserBuffer::CopyFrom(data, size, is_keyframe); |
| + StreamParserBuffer::CopyFrom(data + offset, size - offset, is_keyframe); |
| + |
| + if (encrypted) { |
| + uint64 network_iv; |
| + memcpy(&network_iv, data + kWebMHmacSize, sizeof(network_iv)); |
| + const uint64 iv = base::NetToHost64(network_iv); |
| - if (track_num == video_.track_num() && video_encryption_key_id_.get()) { |
| + std::string counter_block = |
| + GenerateCounterBlock(reinterpret_cast<const uint8*>(&iv), sizeof(iv)); |
| + const uint8* counter_block_data = |
| + reinterpret_cast<const uint8*>(counter_block.data()); |
| buffer->SetDecryptConfig(scoped_ptr<DecryptConfig>(new DecryptConfig( |
| - video_encryption_key_id_.get(), video_encryption_key_id_size_))); |
| + video_encryption_key_id_.get(), video_encryption_key_id_size_, |
| + counter_block_data, counter_block.size(), |
| + data, kWebMHmacSize, |
| + sizeof(iv)))); |
| } |
| buffer->SetTimestamp(timestamp); |