Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <string> | 5 #include <string> |
| 6 | 6 |
| 7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
| 8 #include "media/base/decoder_buffer.h" | 8 #include "media/base/decoder_buffer.h" |
| 9 #include "media/base/decrypt_config.h" | 9 #include "media/base/decrypt_config.h" |
| 10 #include "media/base/mock_filters.h" | 10 #include "media/base/mock_filters.h" |
| 11 #include "media/crypto/aes_decryptor.h" | 11 #include "media/crypto/aes_decryptor.h" |
| 12 #include "testing/gtest/include/gtest/gtest.h" | 12 #include "testing/gtest/include/gtest/gtest.h" |
| 13 | 13 |
| 14 using ::testing::_; | 14 using ::testing::_; |
| 15 using ::testing::Gt; | 15 using ::testing::Gt; |
| 16 using ::testing::NotNull; | 16 using ::testing::NotNull; |
| 17 using ::testing::SaveArg; | 17 using ::testing::SaveArg; |
| 18 using ::testing::StrNe; | 18 using ::testing::StrNe; |
| 19 | 19 |
| 20 namespace media { | 20 namespace media { |
| 21 | 21 |
| 22 static const char kClearKeySystem[] = "org.w3.clearkey"; | 22 static const char kClearKeySystem[] = "org.w3.clearkey"; |
| 23 static const uint8 kInitData[] = { 0x69, 0x6e, 0x69, 0x74 }; | 23 static const uint8 kInitData[] = { 0x69, 0x6e, 0x69, 0x74 }; |
| 24 // |kEncryptedData| is encrypted from |kOriginalData| using |kRightKey|. | |
| 25 // Modifying any of these independently would fail the test. | |
| 26 static const uint8 kOriginalData[] = { | 24 static const uint8 kOriginalData[] = { |
| 27 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, | 25 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, |
| 28 0x20, 0x64, 0x61, 0x74, 0x61, 0x2e | 26 0x20, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x20, 0x33, |
| 27 0x30, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, | |
| 28 0x6f, 0x66, 0x20, 0x69, 0x74, 0x2e | |
| 29 }; | 29 }; |
| 30 static const uint8 kEncryptedData[] = { | 30 |
| 31 0x82, 0x3A, 0x76, 0x92, 0xEC, 0x7F, 0xF8, 0x85, | 31 // |kCBCEncryptedData| is |kOriginalData| encrypted with |kRightKey| and the |
| 32 0xEC, 0x23, 0x52, 0xFB, 0x19, 0xB1, 0xB9, 0x09 | 32 // default IV embedded in aes_decryptor.cc. |
| 33 // | |
| 34 // TODO(strobe): CBC is only used for an early draft of WebM encryption. | |
| 35 // Remove when https://chromiumcodereview.appspot.com/10535029 lands. | |
| 36 static const uint8 kCBCEncryptedData[] = { | |
|
fgalligan1
2012/06/27 00:28:36
s/kCBCEncryptedData/kCbcEncryptedData
strobe_
2012/06/27 02:01:21
Done.
| |
| 37 0x16, 0xeb, 0x06, 0xf8, 0x99, 0x87, 0xce, 0x09, | |
| 38 0x0e, 0x91, 0x5a, 0xa3, 0x88, 0xc3, 0x5b, 0xf5, | |
| 39 0xe9, 0xac, 0x40, 0x53, 0x95, 0x85, 0x5f, 0x09, | |
| 40 0x3d, 0xa0, 0x4f, 0xbe, 0x66, 0xf5, 0x15, 0xb5 | |
| 33 }; | 41 }; |
| 42 | |
| 43 // |kCTREncryptedData| is |kOriginalData| encrypted with |kRightKey|, using | |
| 44 // initial counter |kInitialCtr|. | |
| 45 static const uint8 kCTREncryptedData[] = { | |
|
fgalligan1
2012/06/27 00:28:36
s/kCTREncryptedData/kCtrEncryptedData/
strobe_
2012/06/27 02:01:21
Done.
| |
| 46 0x06, 0x53, 0x1d, 0x16, 0x67, 0xd4, 0x2d, 0x5c, | |
| 47 0xa8, 0xba, 0x3b, 0x82, 0xc4, 0xdc, 0x14, 0x89, | |
| 48 0xea, 0x2e, 0x8c, 0x64, 0x4c, 0x4b, 0x6b, 0xda, | |
| 49 0x39, 0xbb, 0xe8, 0xc1, 0x25, 0x35 | |
| 50 }; | |
| 51 | |
| 52 // |kCTREncryptedData| is |kOriginalData|, subsampled according to | |
|
fgalligan1
2012/06/27 00:28:36
kCtrSubsampleEncryptedData
strobe_
2012/06/27 02:01:21
Done.
| |
| 53 // |kSubsamples|, with ciphered portions encrypted with |kRightKey|, using | |
| 54 // initial counter |kInitialCtr|. | |
| 55 static const uint8 kCTRSubsampleEncryptedData[] = { | |
|
fgalligan1
2012/06/27 00:28:36
s/kCTRSubsampleEncryptedData/kCtrSubsampleEncrypte
strobe_
2012/06/27 02:01:21
Done.
| |
| 56 0x4f, 0x72, 0x69, 0x2e, 0x48, 0x1a, 0x10, 0x62, | |
| 57 0x20, 0xde, 0x2d, 0x44, 0xe9, 0xf0, 0x7a, 0xc5, | |
| 58 0x95, 0xd2, 0x56, 0xc3, 0xae, 0x6b, 0x9d, 0x3d, | |
| 59 0x57, 0x48, 0x38, 0x93, 0x74, 0x2e | |
| 60 }; | |
| 61 | |
| 34 static const uint8 kRightKey[] = { | 62 static const uint8 kRightKey[] = { |
| 35 0x41, 0x20, 0x77, 0x6f, 0x6e, 0x64, 0x65, 0x72, | 63 0x41, 0x20, 0x77, 0x6f, 0x6e, 0x64, 0x65, 0x72, |
| 36 0x66, 0x75, 0x6c, 0x20, 0x6b, 0x65, 0x79, 0x21 | 64 0x66, 0x75, 0x6c, 0x20, 0x6b, 0x65, 0x79, 0x21 |
| 37 }; | 65 }; |
| 38 static const uint8 kWrongKey[] = { | 66 static const uint8 kWrongKey[] = { |
| 39 0x49, 0x27, 0x6d, 0x20, 0x61, 0x20, 0x77, 0x72, | 67 0x49, 0x27, 0x6d, 0x20, 0x61, 0x20, 0x77, 0x72, |
| 40 0x6f, 0x6e, 0x67, 0x20, 0x6b, 0x65, 0x79, 0x2e | 68 0x6f, 0x6e, 0x67, 0x20, 0x6b, 0x65, 0x79, 0x2e |
| 41 }; | 69 }; |
| 42 static const uint8 kWrongSizedKey[] = { 0x20, 0x20 }; | 70 static const uint8 kWrongSizedKey[] = { 0x20, 0x20 }; |
| 43 static const uint8 kKeyId1[] = { | 71 static const uint8 kKeyId1[] = { |
| 44 0x4b, 0x65, 0x79, 0x20, 0x49, 0x44, 0x20, 0x31 | 72 0x4b, 0x65, 0x79, 0x20, 0x49, 0x44, 0x20, 0x31 |
| 45 }; | 73 }; |
| 46 static const uint8 kKeyId2[] = { | 74 static const uint8 kKeyId2[] = { |
| 47 0x4b, 0x65, 0x79, 0x20, 0x49, 0x44, 0x20, 0x32 | 75 0x4b, 0x65, 0x79, 0x20, 0x49, 0x44, 0x20, 0x32 |
| 48 }; | 76 }; |
| 77 static const uint8 kInitialCtr[] = { | |
|
ddorwin
2012/06/26 06:09:19
Why not call this IV?
strobe_
2012/06/27 02:01:21
Done. (The underlying libraries tend to treat init
| |
| 78 0x41, 0x54, 0x65, 0x73, 0x74, 0x49, 0x56, 0x31, | |
| 79 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | |
| 80 }; | |
| 81 static const SubsampleEntry kSubsamples[] = { | |
| 82 { 3, 5 }, | |
| 83 { 1, 19 }, | |
| 84 { 2, 0 } | |
| 85 }; | |
| 49 | 86 |
| 50 class AesDecryptorTest : public testing::Test { | 87 class AesDecryptorTest : public testing::Test { |
| 51 public: | 88 public: |
| 52 AesDecryptorTest() : decryptor_(&client_) { | 89 AesDecryptorTest() : decryptor_(&client_) { |
| 53 encrypted_data_ = DecoderBuffer::CopyFrom(kEncryptedData, | 90 InitCTR(); |
|
ddorwin
2012/06/26 06:09:19
I think this is unexpected. Please call it in each
strobe_
2012/06/27 02:01:21
Done.
| |
| 54 arraysize(kEncryptedData)); | 91 }; |
| 92 | |
| 93 protected: | |
| 94 void InitCBC() { | |
| 95 encrypted_data_ = DecoderBuffer::CopyFrom( | |
| 96 kCBCEncryptedData, arraysize(kCBCEncryptedData)); | |
| 97 encrypted_data_->SetDecryptConfig( | |
| 98 scoped_ptr<DecryptConfig>(new DecryptConfig( | |
| 99 kKeyId1, arraysize(kKeyId1)))); | |
| 55 } | 100 } |
| 56 | 101 |
| 57 protected: | 102 void InitCTR() { |
| 103 encrypted_data_ = DecoderBuffer::CopyFrom( | |
| 104 kCTREncryptedData, arraysize(kCTREncryptedData)); | |
| 105 encrypted_data_->SetDecryptConfig( | |
| 106 scoped_ptr<DecryptConfig>(new DecryptConfig( | |
| 107 kKeyId1, arraysize(kKeyId1), | |
| 108 kInitialCtr, arraysize(kInitialCtr)))); | |
| 109 } | |
| 110 | |
| 111 void InitCTRSubsample() { | |
| 112 encrypted_data_ = DecoderBuffer::CopyFrom( | |
| 113 kCTRSubsampleEncryptedData, arraysize(kCTRSubsampleEncryptedData)); | |
| 114 encrypted_data_->SetDecryptConfig( | |
| 115 scoped_ptr<DecryptConfig>(new DecryptConfig( | |
| 116 kKeyId1, arraysize(kKeyId1), | |
| 117 kInitialCtr, arraysize(kInitialCtr), | |
| 118 kSubsamples, arraysize(kSubsamples)))); | |
| 119 } | |
| 120 | |
| 58 void GenerateKeyRequest() { | 121 void GenerateKeyRequest() { |
| 59 EXPECT_CALL(client_, KeyMessageMock(kClearKeySystem, StrNe(std::string()), | 122 EXPECT_CALL(client_, KeyMessageMock(kClearKeySystem, StrNe(std::string()), |
| 60 NotNull(), Gt(0), "")) | 123 NotNull(), Gt(0), "")) |
| 61 .WillOnce(SaveArg<1>(&session_id_string_)); | 124 .WillOnce(SaveArg<1>(&session_id_string_)); |
| 62 decryptor_.GenerateKeyRequest(kClearKeySystem, | 125 decryptor_.GenerateKeyRequest(kClearKeySystem, |
| 63 kInitData, arraysize(kInitData)); | 126 kInitData, arraysize(kInitData)); |
| 64 } | 127 } |
| 65 | 128 |
| 66 template <int KeyIdSize, int KeySize> | 129 template <int KeyIdSize, int KeySize> |
| 67 void AddKeyAndExpectToSucceed(const uint8 (&key_id)[KeyIdSize], | 130 void AddKeyAndExpectToSucceed(const uint8 (&key_id)[KeyIdSize], |
| 68 const uint8 (&key)[KeySize]) { | 131 const uint8 (&key)[KeySize]) { |
| 69 EXPECT_CALL(client_, KeyAdded(kClearKeySystem, session_id_string_)); | 132 EXPECT_CALL(client_, KeyAdded(kClearKeySystem, session_id_string_)); |
| 70 decryptor_.AddKey(kClearKeySystem, key, KeySize, key_id, KeyIdSize, | 133 decryptor_.AddKey(kClearKeySystem, key, KeySize, key_id, KeyIdSize, |
| 71 session_id_string_); | 134 session_id_string_); |
| 72 } | 135 } |
| 73 | 136 |
| 74 template <int KeyIdSize, int KeySize> | 137 template <int KeyIdSize, int KeySize> |
| 75 void AddKeyAndExpectToFail(const uint8 (&key_id)[KeyIdSize], | 138 void AddKeyAndExpectToFail(const uint8 (&key_id)[KeyIdSize], |
| 76 const uint8 (&key)[KeySize]) { | 139 const uint8 (&key)[KeySize]) { |
| 77 EXPECT_CALL(client_, KeyError(kClearKeySystem, session_id_string_, | 140 EXPECT_CALL(client_, KeyError(kClearKeySystem, session_id_string_, |
| 78 Decryptor::kUnknownError, 0)); | 141 Decryptor::kUnknownError, 0)); |
| 79 decryptor_.AddKey(kClearKeySystem, key, KeySize, key_id, KeyIdSize, | 142 decryptor_.AddKey(kClearKeySystem, key, KeySize, key_id, KeyIdSize, |
| 80 session_id_string_); | 143 session_id_string_); |
| 81 } | 144 } |
| 82 | 145 |
| 83 template <int KeyIdSize> | |
| 84 void SetKeyIdForEncryptedData(const uint8 (&key_id)[KeyIdSize]) { | |
| 85 encrypted_data_->SetDecryptConfig( | |
| 86 scoped_ptr<DecryptConfig>(new DecryptConfig(key_id, KeyIdSize))); | |
| 87 } | |
| 88 | |
| 89 void DecryptAndExpectToSucceed() { | 146 void DecryptAndExpectToSucceed() { |
| 90 scoped_refptr<DecoderBuffer> decrypted = | 147 scoped_refptr<DecoderBuffer> decrypted = |
| 91 decryptor_.Decrypt(encrypted_data_); | 148 decryptor_.Decrypt(encrypted_data_); |
| 92 ASSERT_TRUE(decrypted); | 149 ASSERT_TRUE(decrypted); |
| 93 int data_length = sizeof(kOriginalData); | 150 int data_length = sizeof(kOriginalData); |
| 94 ASSERT_EQ(data_length, decrypted->GetDataSize()); | 151 ASSERT_EQ(data_length, decrypted->GetDataSize()); |
| 95 EXPECT_EQ(0, memcmp(kOriginalData, decrypted->GetData(), data_length)); | 152 EXPECT_EQ(0, memcmp(kOriginalData, decrypted->GetData(), data_length)); |
| 96 } | 153 } |
| 97 | 154 |
| 98 void DecryptAndExpectToFail() { | 155 void DecryptAndExpectIncorrectData() { |
| 99 scoped_refptr<DecoderBuffer> decrypted = | 156 scoped_refptr<DecoderBuffer> decrypted = |
| 100 decryptor_.Decrypt(encrypted_data_); | 157 decryptor_.Decrypt(encrypted_data_); |
| 101 EXPECT_FALSE(decrypted); | 158 ASSERT_TRUE(decrypted); |
|
ddorwin
2012/06/26 06:09:19
Does this pass because you fixed up the padding or
strobe_
2012/06/27 02:01:21
The latter. Our CBC decoder expects PKCS#5 padding
| |
| 159 int data_length = sizeof(kOriginalData); | |
| 160 ASSERT_EQ(data_length, decrypted->GetDataSize()); | |
| 161 EXPECT_NE(0, memcmp(kOriginalData, decrypted->GetData(), data_length)); | |
| 102 } | 162 } |
| 103 | 163 |
| 104 scoped_refptr<DecoderBuffer> encrypted_data_; | 164 scoped_refptr<DecoderBuffer> encrypted_data_; |
| 105 MockDecryptorClient client_; | 165 MockDecryptorClient client_; |
| 106 AesDecryptor decryptor_; | 166 AesDecryptor decryptor_; |
| 107 std::string session_id_string_; | 167 std::string session_id_string_; |
| 108 }; | 168 }; |
| 109 | 169 |
| 110 TEST_F(AesDecryptorTest, NormalDecryption) { | 170 TEST_F(AesDecryptorTest, NormalDecryption) { |
| 111 GenerateKeyRequest(); | 171 GenerateKeyRequest(); |
| 112 AddKeyAndExpectToSucceed(kKeyId1, kRightKey); | 172 AddKeyAndExpectToSucceed(kKeyId1, kRightKey); |
| 113 SetKeyIdForEncryptedData(kKeyId1); | |
| 114 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed()); | 173 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed()); |
| 115 } | 174 } |
| 116 | 175 |
| 117 TEST_F(AesDecryptorTest, WrongKey) { | 176 TEST_F(AesDecryptorTest, NormalCBCDecryption) { |
| 177 InitCBC(); | |
| 178 GenerateKeyRequest(); | |
| 179 AddKeyAndExpectToSucceed(kKeyId1, kRightKey); | |
| 180 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed()); | |
| 181 } | |
| 182 | |
| 183 TEST_F(AesDecryptorTest, NormalCTRSubsampleDecryption) { | |
| 184 InitCTRSubsample(); | |
| 185 GenerateKeyRequest(); | |
| 186 AddKeyAndExpectToSucceed(kKeyId1, kRightKey); | |
| 187 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed()); | |
| 188 } | |
| 189 | |
| 190 TEST_F(AesDecryptorTest, WrongCBCKey) { | |
|
ddorwin
2012/06/26 06:09:19
add InitCTRSubsample();
I think you also need a Wr
strobe_
2012/06/27 02:01:21
Not sure where this should go.
| |
| 118 GenerateKeyRequest(); | 191 GenerateKeyRequest(); |
| 119 AddKeyAndExpectToSucceed(kKeyId1, kWrongKey); | 192 AddKeyAndExpectToSucceed(kKeyId1, kWrongKey); |
| 120 SetKeyIdForEncryptedData(kKeyId1); | 193 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectIncorrectData()); |
| 121 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToFail()); | |
| 122 } | 194 } |
| 123 | 195 |
| 124 TEST_F(AesDecryptorTest, MultipleKeys) { | 196 TEST_F(AesDecryptorTest, MultipleKeys) { |
| 125 GenerateKeyRequest(); | 197 GenerateKeyRequest(); |
| 126 AddKeyAndExpectToSucceed(kKeyId1, kRightKey); | 198 AddKeyAndExpectToSucceed(kKeyId1, kRightKey); |
| 127 AddKeyAndExpectToSucceed(kKeyId2, kWrongKey); | 199 AddKeyAndExpectToSucceed(kKeyId2, kWrongKey); |
| 128 SetKeyIdForEncryptedData(kKeyId1); | |
| 129 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed()); | 200 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed()); |
| 130 } | 201 } |
| 131 | 202 |
| 132 TEST_F(AesDecryptorTest, KeyReplacement) { | 203 TEST_F(AesDecryptorTest, KeyReplacement) { |
| 133 GenerateKeyRequest(); | 204 GenerateKeyRequest(); |
| 134 SetKeyIdForEncryptedData(kKeyId1); | |
| 135 AddKeyAndExpectToSucceed(kKeyId1, kWrongKey); | 205 AddKeyAndExpectToSucceed(kKeyId1, kWrongKey); |
| 136 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToFail()); | 206 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectIncorrectData()); |
| 137 AddKeyAndExpectToSucceed(kKeyId1, kRightKey); | 207 AddKeyAndExpectToSucceed(kKeyId1, kRightKey); |
| 138 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed()); | 208 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed()); |
| 139 } | 209 } |
| 140 | 210 |
| 141 TEST_F(AesDecryptorTest, WrongSizedKey) { | 211 TEST_F(AesDecryptorTest, WrongSizedKey) { |
| 142 GenerateKeyRequest(); | 212 GenerateKeyRequest(); |
| 143 AddKeyAndExpectToFail(kKeyId1, kWrongSizedKey); | 213 AddKeyAndExpectToFail(kKeyId1, kWrongSizedKey); |
| 144 } | 214 } |
| 145 | 215 |
| 146 } // media | 216 } // media |
| OLD | NEW |