| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "content/common/origin_trials/trial_token.h" | 5 #include "content/common/origin_trials/trial_token.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 | 8 |
| 9 #include "base/macros.h" | 9 #include "base/macros.h" |
| 10 #include "base/strings/string_piece.h" | 10 #include "base/strings/string_piece.h" |
| 11 #include "base/strings/string_util.h" | 11 #include "base/strings/string_util.h" |
| 12 #include "base/test/simple_test_clock.h" | 12 #include "base/test/simple_test_clock.h" |
| 13 #include "base/time/time.h" | 13 #include "base/time/time.h" |
| 14 #include "testing/gtest/include/gtest/gtest.h" | 14 #include "testing/gtest/include/gtest/gtest.h" |
| 15 #include "third_party/WebKit/public/platform/WebOriginTrialTokenStatus.h" |
| 15 #include "url/gurl.h" | 16 #include "url/gurl.h" |
| 16 | 17 |
| 17 namespace content { | 18 namespace content { |
| 18 | 19 |
| 19 namespace { | 20 namespace { |
| 20 | 21 |
| 21 // This is a sample public key for testing the API. The corresponding private | 22 // This is a sample public key for testing the API. The corresponding private |
| 22 // key (use this to generate new samples for this test file) is: | 23 // key (use this to generate new samples for this test file) is: |
| 23 // | 24 // |
| 24 // 0x83, 0x67, 0xf4, 0xcd, 0x2a, 0x1f, 0x0e, 0x04, 0x0d, 0x43, 0x13, | 25 // 0x83, 0x67, 0xf4, 0xcd, 0x2a, 0x1f, 0x0e, 0x04, 0x0d, 0x43, 0x13, |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 68 | 69 |
| 69 // The token should be valid if the current time is kValidTimestamp or earlier. | 70 // The token should be valid if the current time is kValidTimestamp or earlier. |
| 70 double kValidTimestamp = 1458766276.0; | 71 double kValidTimestamp = 1458766276.0; |
| 71 | 72 |
| 72 // The token should be invalid if the current time is kInvalidTimestamp or | 73 // The token should be invalid if the current time is kInvalidTimestamp or |
| 73 // later. | 74 // later. |
| 74 double kInvalidTimestamp = 1458766278.0; | 75 double kInvalidTimestamp = 1458766278.0; |
| 75 | 76 |
| 76 // Well-formed trial token with an invalid signature. | 77 // Well-formed trial token with an invalid signature. |
| 77 const char* kInvalidSignatureToken = | 78 const char* kInvalidSignatureToken = |
| 78 "AYeNXSDktgG9p4ns5B1WKsLq2TytMxfR4whfbi+oyT0rXyzh+qXYfxbDMGmyjU2Z" | 79 "Ap+Q/Qm0ELadZql+dlEGSwnAVsFZKgCEtUZg8idQC3uekkIeSZIY1tftoYdrwhqj" |
| 79 "lEJ16vQObMXJoOaYUqd8xwkAAABZeyJvcmlnaW4iOiAiaHR0cHM6Ly92YWxpZC5l" | 80 "7FO5L22sNvkZZnacLvmfNwsAAABaeyJvcmlnaW4iOiAiaHR0cHM6Ly92YWxpZC5l" |
| 80 "eGFtcGxlLmNvbTo0NDMiLCAiZmVhdHVyZSI6ICJGcm9idWxhdGUiLCAiZXhwaXJ5" | 81 "eGFtcGxlLmNvbTo0NDMiLCAiZmVhdHVyZSI6ICJGcm9idWxhdGV4IiwgImV4cGly" |
| 81 "IjogMTQ1ODc2NjI3N30="; | 82 "eSI6IDE0NTg3NjYyNzd9"; |
| 82 | 83 |
| 83 // Trial token truncated in the middle of the length field; too short to | 84 // Trial token truncated in the middle of the length field; too short to |
| 84 // possibly be valid. | 85 // possibly be valid. |
| 85 const char kTruncatedToken[] = | 86 const char kTruncatedToken[] = |
| 86 "Ap+Q/Qm0ELadZql+dlEGSwnAVsFZKgCEtUZg8idQC3uekkIeSZIY1tftoYdrwhqj" | 87 "Ap+Q/Qm0ELadZql+dlEGSwnAVsFZKgCEtUZg8idQC3uekkIeSZIY1tftoYdrwhqj" |
| 87 "7FO5L22sNvkZZnacLvmfNwsA"; | 88 "7FO5L22sNvkZZnacLvmfNwsA"; |
| 88 | 89 |
| 89 // Trial token with an incorrectly-declared length, but with a valid signature. | 90 // Trial token with an incorrectly-declared length, but with a valid signature. |
| 90 const char kIncorrectLengthToken[] = | 91 const char kIncorrectLengthToken[] = |
| 91 "Ao06eNl/CZuM88qurWKX4RfoVEpHcVHWxdOTrEXZkaC1GUHyb/8L4sthADiVWdc9" | 92 "Ao06eNl/CZuM88qurWKX4RfoVEpHcVHWxdOTrEXZkaC1GUHyb/8L4sthADiVWdc9" |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 146 valid_timestamp_(base::Time::FromDoubleT(kValidTimestamp)), | 147 valid_timestamp_(base::Time::FromDoubleT(kValidTimestamp)), |
| 147 invalid_timestamp_(base::Time::FromDoubleT(kInvalidTimestamp)), | 148 invalid_timestamp_(base::Time::FromDoubleT(kInvalidTimestamp)), |
| 148 correct_public_key_( | 149 correct_public_key_( |
| 149 base::StringPiece(reinterpret_cast<const char*>(kTestPublicKey), | 150 base::StringPiece(reinterpret_cast<const char*>(kTestPublicKey), |
| 150 arraysize(kTestPublicKey))), | 151 arraysize(kTestPublicKey))), |
| 151 incorrect_public_key_( | 152 incorrect_public_key_( |
| 152 base::StringPiece(reinterpret_cast<const char*>(kTestPublicKey2), | 153 base::StringPiece(reinterpret_cast<const char*>(kTestPublicKey2), |
| 153 arraysize(kTestPublicKey2))) {} | 154 arraysize(kTestPublicKey2))) {} |
| 154 | 155 |
| 155 protected: | 156 protected: |
| 156 std::unique_ptr<std::string> Extract(const std::string& token_text, | 157 blink::WebOriginTrialTokenStatus Extract(const std::string& token_text, |
| 157 base::StringPiece public_key) { | 158 base::StringPiece public_key, |
| 158 return TrialToken::Extract(token_text, public_key); | 159 std::string* token_payload) { |
| 160 return TrialToken::Extract(token_text, public_key, token_payload); |
| 159 } | 161 } |
| 162 |
| 163 blink::WebOriginTrialTokenStatus ExtractIgnorePayload( |
| 164 const std::string& token_text, |
| 165 base::StringPiece public_key) { |
| 166 std::string token_payload; |
| 167 return Extract(token_text, public_key, &token_payload); |
| 168 } |
| 169 |
| 160 std::unique_ptr<TrialToken> Parse(const std::string& token_payload) { | 170 std::unique_ptr<TrialToken> Parse(const std::string& token_payload) { |
| 161 return TrialToken::Parse(token_payload); | 171 return TrialToken::Parse(token_payload); |
| 162 } | 172 } |
| 163 | 173 |
| 164 bool ValidateOrigin(TrialToken* token, const url::Origin origin) { | 174 bool ValidateOrigin(TrialToken* token, const url::Origin origin) { |
| 165 return token->ValidateOrigin(origin); | 175 return token->ValidateOrigin(origin); |
| 166 } | 176 } |
| 167 | 177 |
| 168 bool ValidateFeatureName(TrialToken* token, const char* feature_name) { | 178 bool ValidateFeatureName(TrialToken* token, const char* feature_name) { |
| 169 return token->ValidateFeatureName(feature_name); | 179 return token->ValidateFeatureName(feature_name); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 189 base::StringPiece incorrect_public_key_; | 199 base::StringPiece incorrect_public_key_; |
| 190 }; | 200 }; |
| 191 | 201 |
| 192 // Test the extraction of the signed payload from token strings. This includes | 202 // Test the extraction of the signed payload from token strings. This includes |
| 193 // checking the included version identifier, payload length, and cryptographic | 203 // checking the included version identifier, payload length, and cryptographic |
| 194 // signature. | 204 // signature. |
| 195 | 205 |
| 196 // Test verification of signature and extraction of token JSON from signed | 206 // Test verification of signature and extraction of token JSON from signed |
| 197 // token. | 207 // token. |
| 198 TEST_F(TrialTokenTest, ValidateValidSignature) { | 208 TEST_F(TrialTokenTest, ValidateValidSignature) { |
| 199 std::unique_ptr<std::string> token_payload = | 209 std::string token_payload; |
| 200 Extract(kSampleToken, correct_public_key()); | 210 blink::WebOriginTrialTokenStatus status = |
| 201 ASSERT_TRUE(token_payload); | 211 Extract(kSampleToken, correct_public_key(), &token_payload); |
| 202 EXPECT_STREQ(kSampleTokenJSON, token_payload.get()->c_str()); | 212 ASSERT_EQ(blink::WebOriginTrialTokenStatus::Success, status); |
| 213 EXPECT_STREQ(kSampleTokenJSON, token_payload.c_str()); |
| 203 } | 214 } |
| 204 | 215 |
| 205 TEST_F(TrialTokenTest, ValidateInvalidSignature) { | 216 TEST_F(TrialTokenTest, ValidateInvalidSignature) { |
| 206 std::unique_ptr<std::string> token_payload = | 217 blink::WebOriginTrialTokenStatus status = |
| 207 Extract(kInvalidSignatureToken, correct_public_key()); | 218 ExtractIgnorePayload(kInvalidSignatureToken, correct_public_key()); |
| 208 ASSERT_FALSE(token_payload); | 219 EXPECT_EQ(blink::WebOriginTrialTokenStatus::InvalidSignature, status); |
| 209 } | 220 } |
| 210 | 221 |
| 211 TEST_F(TrialTokenTest, ValidateSignatureWithIncorrectKey) { | 222 TEST_F(TrialTokenTest, ValidateSignatureWithIncorrectKey) { |
| 212 std::unique_ptr<std::string> token_payload = | 223 blink::WebOriginTrialTokenStatus status = |
| 213 Extract(kSampleToken, incorrect_public_key()); | 224 ExtractIgnorePayload(kSampleToken, incorrect_public_key()); |
| 214 ASSERT_FALSE(token_payload); | 225 EXPECT_EQ(blink::WebOriginTrialTokenStatus::InvalidSignature, status); |
| 215 } | 226 } |
| 216 | 227 |
| 217 TEST_F(TrialTokenTest, ValidateEmptyToken) { | 228 TEST_F(TrialTokenTest, ValidateEmptyToken) { |
| 218 std::unique_ptr<std::string> token_payload = | 229 blink::WebOriginTrialTokenStatus status = |
| 219 Extract("", correct_public_key()); | 230 ExtractIgnorePayload("", correct_public_key()); |
| 220 ASSERT_FALSE(token_payload); | 231 EXPECT_EQ(blink::WebOriginTrialTokenStatus::Malformed, status); |
| 221 } | 232 } |
| 222 | 233 |
| 223 TEST_F(TrialTokenTest, ValidateShortToken) { | 234 TEST_F(TrialTokenTest, ValidateShortToken) { |
| 224 std::unique_ptr<std::string> token_payload = | 235 blink::WebOriginTrialTokenStatus status = |
| 225 Extract(kTruncatedToken, correct_public_key()); | 236 ExtractIgnorePayload(kTruncatedToken, correct_public_key()); |
| 226 ASSERT_FALSE(token_payload); | 237 EXPECT_EQ(blink::WebOriginTrialTokenStatus::Malformed, status); |
| 227 } | 238 } |
| 228 | 239 |
| 229 TEST_F(TrialTokenTest, ValidateUnsupportedVersion) { | 240 TEST_F(TrialTokenTest, ValidateUnsupportedVersion) { |
| 230 std::unique_ptr<std::string> token_payload = | 241 blink::WebOriginTrialTokenStatus status = |
| 231 Extract(kIncorrectVersionToken, correct_public_key()); | 242 ExtractIgnorePayload(kIncorrectVersionToken, correct_public_key()); |
| 232 ASSERT_FALSE(token_payload); | 243 EXPECT_EQ(blink::WebOriginTrialTokenStatus::WrongVersion, status); |
| 233 } | 244 } |
| 234 | 245 |
| 235 TEST_F(TrialTokenTest, ValidateSignatureWithIncorrectLength) { | 246 TEST_F(TrialTokenTest, ValidateSignatureWithIncorrectLength) { |
| 236 std::unique_ptr<std::string> token_payload = | 247 blink::WebOriginTrialTokenStatus status = |
| 237 Extract(kIncorrectLengthToken, correct_public_key()); | 248 ExtractIgnorePayload(kIncorrectLengthToken, correct_public_key()); |
| 238 ASSERT_FALSE(token_payload); | 249 EXPECT_EQ(blink::WebOriginTrialTokenStatus::Malformed, status); |
| 239 } | 250 } |
| 240 | 251 |
| 241 // Test parsing of fields from JSON token. | 252 // Test parsing of fields from JSON token. |
| 242 | 253 |
| 243 TEST_F(TrialTokenTest, ParseEmptyString) { | 254 TEST_F(TrialTokenTest, ParseEmptyString) { |
| 244 std::unique_ptr<TrialToken> empty_token = Parse(""); | 255 std::unique_ptr<TrialToken> empty_token = Parse(""); |
| 245 EXPECT_FALSE(empty_token); | 256 EXPECT_FALSE(empty_token); |
| 246 } | 257 } |
| 247 | 258 |
| 248 TEST_P(TrialTokenTest, ParseInvalidString) { | 259 TEST_P(TrialTokenTest, ParseInvalidString) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 272 token.get(), base::ToUpperASCII(kExpectedFeatureName).c_str())); | 283 token.get(), base::ToUpperASCII(kExpectedFeatureName).c_str())); |
| 273 EXPECT_FALSE(ValidateFeatureName( | 284 EXPECT_FALSE(ValidateFeatureName( |
| 274 token.get(), base::ToLowerASCII(kExpectedFeatureName).c_str())); | 285 token.get(), base::ToLowerASCII(kExpectedFeatureName).c_str())); |
| 275 EXPECT_TRUE(ValidateDate(token.get(), valid_timestamp_)); | 286 EXPECT_TRUE(ValidateDate(token.get(), valid_timestamp_)); |
| 276 EXPECT_FALSE(ValidateDate(token.get(), invalid_timestamp_)); | 287 EXPECT_FALSE(ValidateDate(token.get(), invalid_timestamp_)); |
| 277 } | 288 } |
| 278 | 289 |
| 279 TEST_F(TrialTokenTest, TokenIsValidForFeature) { | 290 TEST_F(TrialTokenTest, TokenIsValidForFeature) { |
| 280 std::unique_ptr<TrialToken> token = Parse(kSampleTokenJSON); | 291 std::unique_ptr<TrialToken> token = Parse(kSampleTokenJSON); |
| 281 ASSERT_TRUE(token); | 292 ASSERT_TRUE(token); |
| 282 EXPECT_TRUE(token->IsValidForFeature(expected_origin_, kExpectedFeatureName, | 293 EXPECT_EQ(blink::WebOriginTrialTokenStatus::Success, |
| 283 valid_timestamp_)); | 294 token->IsValidForFeature(expected_origin_, kExpectedFeatureName, |
| 284 EXPECT_FALSE(token->IsValidForFeature( | 295 valid_timestamp_)); |
| 285 expected_origin_, base::ToUpperASCII(kExpectedFeatureName), | 296 EXPECT_EQ(blink::WebOriginTrialTokenStatus::WrongFeature, |
| 286 valid_timestamp_)); | 297 token->IsValidForFeature(expected_origin_, |
| 287 EXPECT_FALSE(token->IsValidForFeature( | 298 base::ToUpperASCII(kExpectedFeatureName), |
| 288 expected_origin_, base::ToLowerASCII(kExpectedFeatureName), | 299 valid_timestamp_)); |
| 289 valid_timestamp_)); | 300 EXPECT_EQ(blink::WebOriginTrialTokenStatus::WrongFeature, |
| 290 EXPECT_FALSE(token->IsValidForFeature(invalid_origin_, kExpectedFeatureName, | 301 token->IsValidForFeature(expected_origin_, |
| 291 valid_timestamp_)); | 302 base::ToLowerASCII(kExpectedFeatureName), |
| 292 EXPECT_FALSE(token->IsValidForFeature(insecure_origin_, kExpectedFeatureName, | 303 valid_timestamp_)); |
| 293 valid_timestamp_)); | 304 EXPECT_EQ(blink::WebOriginTrialTokenStatus::WrongOrigin, |
| 294 EXPECT_FALSE(token->IsValidForFeature(expected_origin_, kInvalidFeatureName, | 305 token->IsValidForFeature(invalid_origin_, kExpectedFeatureName, |
| 295 valid_timestamp_)); | 306 valid_timestamp_)); |
| 296 EXPECT_FALSE(token->IsValidForFeature(expected_origin_, kExpectedFeatureName, | 307 EXPECT_EQ(blink::WebOriginTrialTokenStatus::WrongOrigin, |
| 297 invalid_timestamp_)); | 308 token->IsValidForFeature(insecure_origin_, kExpectedFeatureName, |
| 309 valid_timestamp_)); |
| 310 EXPECT_EQ(blink::WebOriginTrialTokenStatus::WrongFeature, |
| 311 token->IsValidForFeature(expected_origin_, kInvalidFeatureName, |
| 312 valid_timestamp_)); |
| 313 EXPECT_EQ(blink::WebOriginTrialTokenStatus::Expired, |
| 314 token->IsValidForFeature(expected_origin_, kExpectedFeatureName, |
| 315 invalid_timestamp_)); |
| 316 } |
| 317 |
| 318 // Test overall extraction, to ensure output status matches returned token |
| 319 TEST_F(TrialTokenTest, ExtractValidToken) { |
| 320 blink::WebOriginTrialTokenStatus status; |
| 321 std::unique_ptr<TrialToken> token = |
| 322 TrialToken::From(kSampleToken, correct_public_key(), &status); |
| 323 EXPECT_TRUE(token); |
| 324 EXPECT_EQ(blink::WebOriginTrialTokenStatus::Success, status); |
| 325 } |
| 326 |
| 327 TEST_F(TrialTokenTest, ExtractInvalidSignature) { |
| 328 blink::WebOriginTrialTokenStatus status; |
| 329 std::unique_ptr<TrialToken> token = |
| 330 TrialToken::From(kSampleToken, incorrect_public_key(), &status); |
| 331 EXPECT_FALSE(token); |
| 332 EXPECT_EQ(blink::WebOriginTrialTokenStatus::InvalidSignature, status); |
| 333 } |
| 334 |
| 335 TEST_F(TrialTokenTest, ExtractMalformedToken) { |
| 336 blink::WebOriginTrialTokenStatus status; |
| 337 std::unique_ptr<TrialToken> token = |
| 338 TrialToken::From(kIncorrectLengthToken, correct_public_key(), &status); |
| 339 EXPECT_FALSE(token); |
| 340 EXPECT_EQ(blink::WebOriginTrialTokenStatus::Malformed, status); |
| 298 } | 341 } |
| 299 | 342 |
| 300 } // namespace content | 343 } // namespace content |
| OLD | NEW |