15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/internal_auth.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <deque> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base64.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/rand_util.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h" 15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_checker.h" 18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/hmac.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef std::map<std::string, std::string> VarValueMap; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Size of a tick in microseconds. This determines upper bound for average 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// number of passports generated per time unit. This bound equals to 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (kMicrosecondsPerSecond / TickUs) calls per second. 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int64 kTickUs = 10000; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verification window size in ticks; that means any passport expires in 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (kVerificationWindowTicks * TickUs / kMicrosecondsPerSecond) seconds. 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kVerificationWindowTicks = 2000; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Generation window determines how well we are able to cope with bursts of 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// GeneratePassport calls those exceed upper bound on average speed. 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kGenerationWindowTicks = 20; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Makes no sense to compare other way round. 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)COMPILE_ASSERT(kGenerationWindowTicks <= kVerificationWindowTicks, 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) makes_no_sense_to_have_generation_window_larger_than_verification_one); 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We are not optimized for high value of kGenerationWindowTicks. 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)COMPILE_ASSERT(kGenerationWindowTicks < 30, too_large_generation_window); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Regenerate key after this number of ticks. 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kKeyRegenerationSoftTicks = 500000; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Reject passports if key has not been regenerated in that number of ticks. 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kKeyRegenerationHardTicks = kKeyRegenerationSoftTicks * 2; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Limit for number of accepted var=value pairs. Feel free to bump this limit 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// higher once needed. 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kVarsLimit = 16; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Limit for length of caller-supplied strings. Feel free to bump this limit 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// higher once needed. 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kStringLengthLimit = 512; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Character used as a separator for construction of message to take HMAC of. 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It is critical to validate all caller-supplied data (used to construct 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// message) to be clear of this separator because it could allow attacks. 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kItemSeparator = '\n'; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Character used for var=value separation. 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kVarValueSeparator = '='; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kKeySizeInBytes = 128 / 8; 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const size_t kHMACSizeInBytes = 256 / 8; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Length of base64 string required to encode given number of raw octets. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BASE64_PER_RAW(X) (X > 0 ? ((X - 1) / 3 + 1) * 4 : 0) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Size of decimal string representing 64-bit tick. 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kTickStringLength = 20; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A passport consists of 2 parts: HMAC and tick. 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kPassportSize = 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BASE64_PER_RAW(kHMACSizeInBytes) + kTickStringLength; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 GetCurrentTick() { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 tick = base::Time::Now().ToInternalValue() / kTickUs; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tick < kVerificationWindowTicks || 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tick < kKeyRegenerationHardTicks || 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tick > kint64max - kKeyRegenerationHardTicks) { 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return tick; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsDomainSane(const std::string& domain) { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !domain.empty() && 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) domain.size() <= kStringLengthLimit && 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IsStringUTF8(domain) && 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) domain.find_first_of(kItemSeparator) == std::string::npos; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsVarSane(const std::string& var) { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char kAllowedChars[] = 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "abcdefghijklmnopqrstuvwxyz" 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "0123456789" 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "_"; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) COMPILE_ASSERT( 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(kAllowedChars) == 26 + 26 + 10 + 1 + 1, some_mess_with_chars); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We must not allow kItemSeparator in anything used as an input to construct 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // message to sign. 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(std::find(kAllowedChars, kAllowedChars + arraysize(kAllowedChars), 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kItemSeparator) == kAllowedChars + arraysize(kAllowedChars)); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(std::find(kAllowedChars, kAllowedChars + arraysize(kAllowedChars), 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kVarValueSeparator) == kAllowedChars + arraysize(kAllowedChars)); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !var.empty() && 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var.size() <= kStringLengthLimit && 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IsStringASCII(var) && 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var.find_first_not_of(kAllowedChars) == std::string::npos && 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !IsAsciiDigit(var[0]); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsValueSane(const std::string& value) { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return value.size() <= kStringLengthLimit && 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IsStringUTF8(value) && 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value.find_first_of(kItemSeparator) == std::string::npos; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsVarValueMapSane(const VarValueMap& map) { 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (map.size() > kVarsLimit) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (VarValueMap::const_iterator it = map.begin(); it != map.end(); ++it) { 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& var = it->first; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& value = it->second; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsVarSane(var) || !IsValueSane(value)) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ConvertVarValueMapToBlob(const VarValueMap& map, std::string* out) { 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out->clear(); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(IsVarValueMapSane(map)); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (VarValueMap::const_iterator it = map.begin(); it != map.end(); ++it) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *out += it->first + kVarValueSeparator + it->second + kItemSeparator; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CreatePassport(const std::string& domain, 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const VarValueMap& map, 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 tick, 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const crypto::HMAC* engine, 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* out) { 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(engine); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(out); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(IsDomainSane(domain)); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(IsVarValueMapSane(map)); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out->clear(); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string result(kPassportSize, '0'); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string blob; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob = domain + kItemSeparator; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string tmp; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ConvertVarValueMapToBlob(map, &tmp); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob += tmp + kItemSeparator + base::Uint64ToString(tick); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string hmac; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned char* hmac_data = reinterpret_cast<unsigned char*>( 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteInto(&hmac, kHMACSizeInBytes + 1)); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!engine->Sign(blob, hmac_data, kHMACSizeInBytes)) { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string hmac_base64; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!base::Base64Encode(hmac, &hmac_base64)) { 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (hmac_base64.size() != BASE64_PER_RAW(kHMACSizeInBytes)) { 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(hmac_base64.size() < result.size()); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::copy(hmac_base64.begin(), hmac_base64.end(), result.begin()); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string tick_decimal = base::Uint64ToString(tick); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(tick_decimal.size() <= kTickStringLength); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::copy( 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tick_decimal.begin(), 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tick_decimal.end(), 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.begin() + kPassportSize - tick_decimal.size()); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out->swap(result); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chrome { 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class InternalAuthVerificationService { 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InternalAuthVerificationService() 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : key_change_tick_(0), 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dark_tick_(0) { 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool VerifyPassport( 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& passport, 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& domain, 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const VarValueMap& map) { 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 current_tick = GetCurrentTick(); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 tick = PreVerifyPassport(passport, domain, current_tick); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tick == 0) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsVarValueMapSane(map)) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string reference_passport; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreatePassport(domain, map, tick, engine_.get(), &reference_passport); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (passport != reference_passport) { 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Consider old key. 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (key_change_tick_ + get_verification_window_ticks() < tick) { 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (old_key_.empty() || old_engine_ == NULL) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreatePassport(domain, map, tick, old_engine_.get(), &reference_passport); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (passport != reference_passport) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Record used tick to prevent reuse. 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::deque<int64>::iterator it = std::lower_bound( 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) used_ticks_.begin(), used_ticks_.end(), tick); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(it == used_ticks_.end() || *it != tick); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) used_ticks_.insert(it, tick); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Consider pruning |used_ticks_|. 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (used_ticks_.size() > 50) { 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dark_tick_ = std::max(dark_tick_, 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_tick - get_verification_window_ticks()); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) used_ticks_.erase( 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) used_ticks_.begin(), 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::lower_bound(used_ticks_.begin(), used_ticks_.end(), 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dark_tick_ + 1)); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ChangeKey(const std::string& key) { 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) old_key_.swap(key_); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_.clear(); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) old_engine_.swap(engine_); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) engine_.reset(NULL); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (key.size() != kKeySizeInBytes) 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<crypto::HMAC> new_engine( 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new crypto::HMAC(crypto::HMAC::SHA256)); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!new_engine->Init(key)) 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) engine_.swap(new_engine); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_ = key; 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_change_tick_ = GetCurrentTick(); 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static int get_verification_window_ticks() { 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return InternalAuthVerification::get_verification_window_ticks(); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns tick bound to given passport on success or zero on failure. 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 PreVerifyPassport( 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& passport, 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& domain, 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 current_tick) { 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (passport.size() != kPassportSize || 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !IsStringASCII(passport) || 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !IsDomainSane(domain) || 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_tick <= dark_tick_ || 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_tick > key_change_tick_ + kKeyRegenerationHardTicks || 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_.empty() || 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) engine_ == NULL) { 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Passport consists of 2 parts: first hmac and then tick. 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string tick_decimal = 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) passport.substr(BASE64_PER_RAW(kHMACSizeInBytes)); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(tick_decimal.size() == kTickStringLength); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 tick = 0; 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!base::StringToInt64(tick_decimal, &tick) || 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tick <= dark_tick_ || 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tick > key_change_tick_ + kKeyRegenerationHardTicks || 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tick < current_tick - get_verification_window_ticks() || 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::binary_search(used_ticks_.begin(), used_ticks_.end(), tick)) { 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return tick; 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Current key. 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string key_; 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We keep previous key in order to be able to verify passports during 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // regeneration time. Keys are regenerated on a regular basis. 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string old_key_; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Corresponding HMAC engines. 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<crypto::HMAC> engine_; 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<crypto::HMAC> old_engine_; 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Tick at a time of recent key regeneration. 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 key_change_tick_; 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Keeps track of ticks of successfully verified passports to prevent their 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reuse. Size of this container is kept reasonably low by purging outdated 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ticks. 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::deque<int64> used_ticks_; 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Some ticks before |dark_tick_| were purged from |used_ticks_| container. 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // That means that we must not trust any tick less than or equal to dark tick. 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 dark_tick_; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(InternalAuthVerificationService); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace chrome 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static base::LazyInstance<chrome::InternalAuthVerificationService> 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_verification_service = LAZY_INSTANCE_INITIALIZER; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static base::LazyInstance<base::Lock>::Leaky 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_verification_service_lock = LAZY_INSTANCE_INITIALIZER; 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chrome { 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class InternalAuthGenerationService : public base::ThreadChecker { 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InternalAuthGenerationService() : key_regeneration_tick_(0) { 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GenerateNewKey(); 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void GenerateNewKey() { 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<crypto::HMAC> new_engine(new crypto::HMAC(crypto::HMAC::SHA256)); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string key = base::RandBytesAsString(kKeySizeInBytes); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!new_engine->Init(key)) 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) engine_.swap(new_engine); 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_regeneration_tick_ = GetCurrentTick(); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_verification_service.Get().ChangeKey(key); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::fill(key.begin(), key.end(), 0); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns zero on failure. 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 GetUnusedTick(const std::string& domain) { 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (engine_ == NULL) { 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsDomainSane(domain)) 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 current_tick = GetCurrentTick(); 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!used_ticks_.empty() && used_ticks_.back() > current_tick) 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_tick = used_ticks_.back(); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (bool first_iteration = true;; first_iteration = false) { 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (current_tick < key_regeneration_tick_ + kKeyRegenerationHardTicks) 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!first_iteration) 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GenerateNewKey(); 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Forget outdated ticks if any. 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) used_ticks_.erase( 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) used_ticks_.begin(), 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::lower_bound(used_ticks_.begin(), used_ticks_.end(), 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_tick - kGenerationWindowTicks + 1)); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(used_ticks_.size() <= kGenerationWindowTicks + 0u); 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (used_ticks_.size() >= kGenerationWindowTicks + 0u) { 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Average speed of GeneratePassport calls exceeds limit. 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int64 tick = current_tick; 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tick > current_tick - kGenerationWindowTicks; 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) --tick) { 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int idx = static_cast<int>(used_ticks_.size()) - 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(current_tick - tick + 1); 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (idx < 0 || used_ticks_[idx] != tick) { 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(used_ticks_.end() == 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::find(used_ticks_.begin(), used_ticks_.end(), tick)); 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return tick; 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string GeneratePassport( 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& domain, const VarValueMap& map, int64 tick) { 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tick == 0) { 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tick = GetUnusedTick(domain); 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tick == 0) 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::string(); 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsVarValueMapSane(map)) 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::string(); 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string result; 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreatePassport(domain, map, tick, engine_.get(), &result); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) used_ticks_.insert( 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::lower_bound(used_ticks_.begin(), used_ticks_.end(), tick), tick); 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static int get_verification_window_ticks() { 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return InternalAuthVerification::get_verification_window_ticks(); 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<crypto::HMAC> engine_; 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 key_regeneration_tick_; 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::deque<int64> used_ticks_; 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(InternalAuthGenerationService); 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace chrome 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static base::LazyInstance<chrome::InternalAuthGenerationService> 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_generation_service = LAZY_INSTANCE_INITIALIZER; 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chrome { 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool InternalAuthVerification::VerifyPassport( 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& passport, 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& domain, 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const VarValueMap& var_value_map) { 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock alk(g_verification_service_lock.Get()); 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return g_verification_service.Get().VerifyPassport( 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) passport, domain, var_value_map); 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InternalAuthVerification::ChangeKey(const std::string& key) { 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock alk(g_verification_service_lock.Get()); 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_verification_service.Get().ChangeKey(key); 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int InternalAuthVerification::get_verification_window_ticks() { 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int candidate = kVerificationWindowTicks; 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (verification_window_seconds_ > 0) 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) candidate = verification_window_seconds_ * 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time::kMicrosecondsPerSecond / kTickUs; 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::max(1, std::min(candidate, kVerificationWindowTicks)); 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int InternalAuthVerification::verification_window_seconds_ = 0; 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string InternalAuthGeneration::GeneratePassport( 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& domain, const VarValueMap& var_value_map) { 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return g_generation_service.Get().GeneratePassport(domain, var_value_map, 0); 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InternalAuthGeneration::GenerateNewKey() { 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_generation_service.Get().GenerateNewKey(); 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace chrome 478