- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / login / hwid_checker.cc
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/chromeos/login/hwid_checker.h"
6
7 #include <cstdio>
8
9 #include "base/command_line.h"
10 #include "base/logging.h"
11 #include "base/strings/string_util.h"
12 #include "base/sys_info.h"
13 #include "chrome/common/chrome_switches.h"
14 #include "chromeos/chromeos_switches.h"
15 #include "chromeos/system/statistics_provider.h"
16 #include "third_party/re2/re2/re2.h"
17 #include "third_party/zlib/zlib.h"
18
19 namespace {
20
21 unsigned CalculateCRC32(const std::string& data) {
22   return static_cast<unsigned>(crc32(
23       0,
24       reinterpret_cast<const Bytef*>(data.c_str()),
25       data.length()));
26 }
27
28 std::string CalculateHWIDv2Checksum(const std::string& data) {
29   unsigned crc32 = CalculateCRC32(data);
30   // We take four least significant decimal digits of CRC-32.
31   char checksum[5];
32   int snprintf_result =
33       snprintf(checksum, 5, "%04u", crc32 % 10000);
34   LOG_ASSERT(snprintf_result == 4);
35   return checksum;
36 }
37
38 bool IsCorrectHWIDv2(const std::string& hwid) {
39   std::string body;
40   std::string checksum;
41   if (!RE2::FullMatch(hwid, "([\\s\\S]*) (\\d{4})", &body, &checksum))
42     return false;
43   return CalculateHWIDv2Checksum(body) == checksum;
44 }
45
46 bool IsExceptionalHWID(const std::string& hwid) {
47   return RE2::PartialMatch(hwid, "^(SPRING [A-D])|(FALCO A)");
48 }
49
50 std::string CalculateExceptionalHWIDChecksum(const std::string& data) {
51   static const char base32_alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
52   unsigned crc32 = CalculateCRC32(data);
53   // We take 10 least significant bits of CRC-32 and encode them in 2 characters
54   // using Base32 alphabet.
55   std::string checksum;
56   checksum += base32_alphabet[(crc32 >> 5) & 0x1f];
57   checksum += base32_alphabet[crc32 & 0x1f];
58   return checksum;
59 }
60
61 bool IsCorrectExceptionalHWID(const std::string& hwid) {
62   if (!IsExceptionalHWID(hwid))
63     return false;
64   std::string bom;
65   if (!RE2::FullMatch(hwid, "[A-Z0-9]+ ((?:[A-Z2-7]{4}-)*[A-Z2-7]{1,4})", &bom))
66     return false;
67   if (bom.length() < 2)
68     return false;
69   std::string hwid_without_dashes;
70   RemoveChars(hwid, "-", &hwid_without_dashes);
71   LOG_ASSERT(hwid_without_dashes.length() >= 2);
72   std::string not_checksum =
73       hwid_without_dashes.substr(0, hwid_without_dashes.length() - 2);
74   std::string checksum =
75       hwid_without_dashes.substr(hwid_without_dashes.length() - 2);
76   return CalculateExceptionalHWIDChecksum(not_checksum) == checksum;
77 }
78
79 std::string CalculateHWIDv3Checksum(const std::string& data) {
80   static const char base8_alphabet[] = "23456789";
81   static const char base32_alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
82   unsigned crc32 = CalculateCRC32(data);
83   // We take 8 least significant bits of CRC-32 and encode them in 2 characters.
84   std::string checksum;
85   checksum += base8_alphabet[(crc32 >> 5) & 0x7];
86   checksum += base32_alphabet[crc32 & 0x1f];
87   return checksum;
88 }
89
90 bool IsCorrectHWIDv3(const std::string& hwid) {
91   if (IsExceptionalHWID(hwid))
92     return false;
93   std::string regex =
94       "([A-Z0-9]+ (?:[A-Z2-7][2-9][A-Z2-7]-)*[A-Z2-7])([2-9][A-Z2-7])";
95   std::string not_checksum, checksum;
96   if (!RE2::FullMatch(hwid, regex, &not_checksum, &checksum))
97     return false;
98   RemoveChars(not_checksum, "-", &not_checksum);
99   return CalculateHWIDv3Checksum(not_checksum) == checksum;
100 }
101
102 } // anonymous namespace
103
104 namespace chromeos {
105
106 bool IsHWIDCorrect(const std::string& hwid) {
107   return IsCorrectHWIDv2(hwid) || IsCorrectExceptionalHWID(hwid) ||
108       IsCorrectHWIDv3(hwid);
109 }
110
111 bool IsMachineHWIDCorrect() {
112 #if !defined(GOOGLE_CHROME_BUILD)
113   return true;
114 #endif
115   CommandLine* cmd_line = CommandLine::ForCurrentProcess();
116   if (cmd_line->HasSwitch(::switches::kTestType) ||
117       cmd_line->HasSwitch(chromeos::switches::kSkipHWIDCheck))
118     return true;
119   if (!base::SysInfo::IsRunningOnChromeOS())
120     return true;
121   std::string hwid;
122   chromeos::system::StatisticsProvider* stats =
123       chromeos::system::StatisticsProvider::GetInstance();
124   if (!stats->GetMachineStatistic(chromeos::system::kHardwareClassKey, &hwid)) {
125     LOG(ERROR) << "Couldn't get machine statistic 'hardware_class'.";
126     return false;
127   }
128   if (!chromeos::IsHWIDCorrect(hwid)) {
129     LOG(ERROR) << "Machine has malformed HWID '" << hwid << "'.";
130     return false;
131   }
132   return true;
133 }
134
135 } // namespace chromeos