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[] = { | |
| 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 |kInitialIv|. | |
| 45 static const uint8 kCtrEncryptedData[] = { | |
| 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 // |kCtrSubsampleEncryptedData| is |kOriginalData|, subsampled according to | |
| 53 // |kSubsamples|, with ciphered portions encrypted with |kRightKey|, using | |
| 54 // initial counter |kInitialIv|. | |
| 55 static const uint8 kCtrSubsampleEncryptedData[] = { | |
| 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 kInitialIv[] = { | |
| 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 |
| 54 arraysize(kEncryptedData)); | 91 protected: |
| 92 void InitCBC() { | |
|
xhwang
2012/06/27 22:38:35
Change to InitCbc(), to be consistent with kCbcEnc
strobe_
2012/07/13 00:47:07
Done.
| |
| 93 encrypted_data_ = DecoderBuffer::CopyFrom( | |
| 94 kCbcEncryptedData, arraysize(kCbcEncryptedData)); | |
| 95 encrypted_data_->SetDecryptConfig( | |
| 96 scoped_ptr<DecryptConfig>(new DecryptConfig( | |
| 97 kKeyId1, arraysize(kKeyId1)))); | |
| 55 } | 98 } |
| 56 | 99 |
| 57 protected: | 100 void InitCTR() { |
| 101 encrypted_data_ = DecoderBuffer::CopyFrom( | |
| 102 kCtrEncryptedData, arraysize(kCtrEncryptedData)); | |
| 103 encrypted_data_->SetDecryptConfig( | |
| 104 scoped_ptr<DecryptConfig>(new DecryptConfig( | |
| 105 kKeyId1, arraysize(kKeyId1), | |
| 106 kInitialIv, arraysize(kInitialIv), | |
| 107 NULL, 0))); | |
| 108 } | |
| 109 | |
| 110 void InitCTRSubsample() { | |
| 111 encrypted_data_ = DecoderBuffer::CopyFrom( | |
| 112 kCtrSubsampleEncryptedData, arraysize(kCtrSubsampleEncryptedData)); | |
| 113 encrypted_data_->SetDecryptConfig( | |
| 114 scoped_ptr<DecryptConfig>(new DecryptConfig( | |
| 115 kKeyId1, arraysize(kKeyId1), | |
| 116 kInitialIv, arraysize(kInitialIv), | |
| 117 kSubsamples, arraysize(kSubsamples)))); | |
| 118 } | |
| 119 | |
| 58 void GenerateKeyRequest() { | 120 void GenerateKeyRequest() { |
| 59 EXPECT_CALL(client_, KeyMessageMock(kClearKeySystem, StrNe(std::string()), | 121 EXPECT_CALL(client_, KeyMessageMock(kClearKeySystem, StrNe(std::string()), |
| 60 NotNull(), Gt(0), "")) | 122 NotNull(), Gt(0), "")) |
| 61 .WillOnce(SaveArg<1>(&session_id_string_)); | 123 .WillOnce(SaveArg<1>(&session_id_string_)); |
| 62 decryptor_.GenerateKeyRequest(kClearKeySystem, | 124 decryptor_.GenerateKeyRequest(kClearKeySystem, |
| 63 kInitData, arraysize(kInitData)); | 125 kInitData, arraysize(kInitData)); |
| 64 } | 126 } |
| 65 | 127 |
| 66 template <int KeyIdSize, int KeySize> | 128 template <int KeyIdSize, int KeySize> |
| 67 void AddKeyAndExpectToSucceed(const uint8 (&key_id)[KeyIdSize], | 129 void AddKeyAndExpectToSucceed(const uint8 (&key_id)[KeyIdSize], |
| 68 const uint8 (&key)[KeySize]) { | 130 const uint8 (&key)[KeySize]) { |
| 69 EXPECT_CALL(client_, KeyAdded(kClearKeySystem, session_id_string_)); | 131 EXPECT_CALL(client_, KeyAdded(kClearKeySystem, session_id_string_)); |
| 70 decryptor_.AddKey(kClearKeySystem, key, KeySize, key_id, KeyIdSize, | 132 decryptor_.AddKey(kClearKeySystem, key, KeySize, key_id, KeyIdSize, |
| 71 session_id_string_); | 133 session_id_string_); |
| 72 } | 134 } |
| 73 | 135 |
| 74 template <int KeyIdSize, int KeySize> | 136 template <int KeyIdSize, int KeySize> |
| 75 void AddKeyAndExpectToFail(const uint8 (&key_id)[KeyIdSize], | 137 void AddKeyAndExpectToFail(const uint8 (&key_id)[KeyIdSize], |
| 76 const uint8 (&key)[KeySize]) { | 138 const uint8 (&key)[KeySize]) { |
| 77 EXPECT_CALL(client_, KeyError(kClearKeySystem, session_id_string_, | 139 EXPECT_CALL(client_, KeyError(kClearKeySystem, session_id_string_, |
| 78 Decryptor::kUnknownError, 0)); | 140 Decryptor::kUnknownError, 0)); |
| 79 decryptor_.AddKey(kClearKeySystem, key, KeySize, key_id, KeyIdSize, | 141 decryptor_.AddKey(kClearKeySystem, key, KeySize, key_id, KeyIdSize, |
| 80 session_id_string_); | 142 session_id_string_); |
| 81 } | 143 } |
| 82 | 144 |
| 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() { | 145 void DecryptAndExpectToSucceed() { |
| 90 scoped_refptr<DecoderBuffer> decrypted = | 146 scoped_refptr<DecoderBuffer> decrypted = |
| 91 decryptor_.Decrypt(encrypted_data_); | 147 decryptor_.Decrypt(encrypted_data_); |
| 92 ASSERT_TRUE(decrypted); | 148 ASSERT_TRUE(decrypted); |
| 93 int data_length = sizeof(kOriginalData); | 149 int data_length = sizeof(kOriginalData); |
| 94 ASSERT_EQ(data_length, decrypted->GetDataSize()); | 150 ASSERT_EQ(data_length, decrypted->GetDataSize()); |
| 95 EXPECT_EQ(0, memcmp(kOriginalData, decrypted->GetData(), data_length)); | 151 EXPECT_EQ(0, memcmp(kOriginalData, decrypted->GetData(), data_length)); |
| 96 } | 152 } |
| 97 | 153 |
| 154 // This function depends on PKCS#5 verification, which is only performed by | |
| 155 // CBC. Remove along with CBC. | |
|
ddorwin
2012/07/03 21:03:47
\nTODO: Remove..
strobe_
2012/07/13 00:47:07
Done.
| |
| 98 void DecryptAndExpectToFail() { | 156 void DecryptAndExpectToFail() { |
| 99 scoped_refptr<DecoderBuffer> decrypted = | 157 scoped_refptr<DecoderBuffer> decrypted = |
| 100 decryptor_.Decrypt(encrypted_data_); | 158 decryptor_.Decrypt(encrypted_data_); |
| 101 EXPECT_FALSE(decrypted); | 159 ASSERT_FALSE(decrypted); |
| 160 } | |
| 161 | |
| 162 void DecryptAndExpectIncorrectData() { | |
| 163 scoped_refptr<DecoderBuffer> decrypted = | |
| 164 decryptor_.Decrypt(encrypted_data_); | |
| 165 ASSERT_TRUE(decrypted); | |
| 166 int data_length = sizeof(kOriginalData); | |
| 167 ASSERT_EQ(data_length, decrypted->GetDataSize()); | |
| 168 EXPECT_NE(0, memcmp(kOriginalData, decrypted->GetData(), data_length)); | |
| 102 } | 169 } |
| 103 | 170 |
| 104 scoped_refptr<DecoderBuffer> encrypted_data_; | 171 scoped_refptr<DecoderBuffer> encrypted_data_; |
| 105 MockDecryptorClient client_; | 172 MockDecryptorClient client_; |
| 106 AesDecryptor decryptor_; | 173 AesDecryptor decryptor_; |
| 107 std::string session_id_string_; | 174 std::string session_id_string_; |
| 108 }; | 175 }; |
| 109 | 176 |
| 110 TEST_F(AesDecryptorTest, NormalDecryption) { | 177 TEST_F(AesDecryptorTest, NormalDecryption) { |
| 178 InitCTR(); | |
| 111 GenerateKeyRequest(); | 179 GenerateKeyRequest(); |
| 112 AddKeyAndExpectToSucceed(kKeyId1, kRightKey); | 180 AddKeyAndExpectToSucceed(kKeyId1, kRightKey); |
| 113 SetKeyIdForEncryptedData(kKeyId1); | |
| 114 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed()); | 181 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed()); |
| 115 } | 182 } |
| 116 | 183 |
| 184 TEST_F(AesDecryptorTest, NormalCBCDecryption) { | |
| 185 InitCBC(); | |
| 186 GenerateKeyRequest(); | |
| 187 AddKeyAndExpectToSucceed(kKeyId1, kRightKey); | |
| 188 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed()); | |
| 189 } | |
| 190 | |
| 191 TEST_F(AesDecryptorTest, NormalCTRSubsampleDecryption) { | |
| 192 InitCTRSubsample(); | |
| 193 GenerateKeyRequest(); | |
| 194 AddKeyAndExpectToSucceed(kKeyId1, kRightKey); | |
| 195 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed()); | |
| 196 } | |
| 197 | |
| 198 // This test relies on CBC verification of PKCS#5 padding, which CTR mode does | |
| 199 // not expect or verify. It should be removed along with support for CBC. | |
|
ddorwin
2012/07/03 21:03:47
If you want to remove this one, there should be a
strobe_
2012/07/13 00:47:07
Done.
| |
| 117 TEST_F(AesDecryptorTest, WrongKey) { | 200 TEST_F(AesDecryptorTest, WrongKey) { |
| 201 InitCBC(); | |
| 118 GenerateKeyRequest(); | 202 GenerateKeyRequest(); |
| 119 AddKeyAndExpectToSucceed(kKeyId1, kWrongKey); | 203 AddKeyAndExpectToSucceed(kKeyId1, kWrongKey); |
| 120 SetKeyIdForEncryptedData(kKeyId1); | |
| 121 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToFail()); | 204 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToFail()); |
| 122 } | 205 } |
| 123 | 206 |
| 124 TEST_F(AesDecryptorTest, MultipleKeys) { | 207 TEST_F(AesDecryptorTest, MultipleKeys) { |
| 208 InitCTR(); | |
| 125 GenerateKeyRequest(); | 209 GenerateKeyRequest(); |
| 126 AddKeyAndExpectToSucceed(kKeyId1, kRightKey); | 210 AddKeyAndExpectToSucceed(kKeyId1, kRightKey); |
| 127 AddKeyAndExpectToSucceed(kKeyId2, kWrongKey); | 211 AddKeyAndExpectToSucceed(kKeyId2, kWrongKey); |
| 128 SetKeyIdForEncryptedData(kKeyId1); | |
| 129 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed()); | 212 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed()); |
| 130 } | 213 } |
| 131 | 214 |
| 132 TEST_F(AesDecryptorTest, KeyReplacement) { | 215 TEST_F(AesDecryptorTest, KeyReplacement) { |
| 216 InitCTR(); | |
| 133 GenerateKeyRequest(); | 217 GenerateKeyRequest(); |
| 134 SetKeyIdForEncryptedData(kKeyId1); | |
| 135 AddKeyAndExpectToSucceed(kKeyId1, kWrongKey); | 218 AddKeyAndExpectToSucceed(kKeyId1, kWrongKey); |
| 136 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToFail()); | 219 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectIncorrectData()); |
| 137 AddKeyAndExpectToSucceed(kKeyId1, kRightKey); | 220 AddKeyAndExpectToSucceed(kKeyId1, kRightKey); |
| 138 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed()); | 221 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed()); |
| 139 } | 222 } |
| 140 | 223 |
| 141 TEST_F(AesDecryptorTest, WrongSizedKey) { | 224 TEST_F(AesDecryptorTest, WrongSizedKey) { |
| 225 InitCTR(); | |
| 142 GenerateKeyRequest(); | 226 GenerateKeyRequest(); |
| 143 AddKeyAndExpectToFail(kKeyId1, kWrongSizedKey); | 227 AddKeyAndExpectToFail(kKeyId1, kWrongSizedKey); |
| 144 } | 228 } |
| 145 | 229 |
| 146 } // media | 230 } // media |
| OLD | NEW |