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.
5 #include "chrome/browser/chromeos/login/hwid_checker.h"
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"
21 unsigned CalculateCRC32(const std::string
& data
) {
22 return static_cast<unsigned>(crc32(
24 reinterpret_cast<const Bytef
*>(data
.c_str()),
28 std::string
CalculateHWIDv2Checksum(const std::string
& data
) {
29 unsigned crc32
= CalculateCRC32(data
);
30 // We take four least significant decimal digits of CRC-32.
33 snprintf(checksum
, 5, "%04u", crc32
% 10000);
34 LOG_ASSERT(snprintf_result
== 4);
38 bool IsCorrectHWIDv2(const std::string
& hwid
) {
41 if (!RE2::FullMatch(hwid
, "([\\s\\S]*) (\\d{4})", &body
, &checksum
))
43 return CalculateHWIDv2Checksum(body
) == checksum
;
46 bool IsExceptionalHWID(const std::string
& hwid
) {
47 return RE2::PartialMatch(hwid
, "^(SPRING [A-D])|(FALCO A)");
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.
56 checksum
+= base32_alphabet
[(crc32
>> 5) & 0x1f];
57 checksum
+= base32_alphabet
[crc32
& 0x1f];
61 bool IsCorrectExceptionalHWID(const std::string
& hwid
) {
62 if (!IsExceptionalHWID(hwid
))
65 if (!RE2::FullMatch(hwid
, "[A-Z0-9]+ ((?:[A-Z2-7]{4}-)*[A-Z2-7]{1,4})", &bom
))
69 std::string hwid_without_dashes
;
70 base::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
;
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.
85 checksum
+= base8_alphabet
[(crc32
>> 5) & 0x7];
86 checksum
+= base32_alphabet
[crc32
& 0x1f];
90 bool IsCorrectHWIDv3(const std::string
& hwid
) {
91 if (IsExceptionalHWID(hwid
))
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
, ¬_checksum
, &checksum
))
98 base::RemoveChars(not_checksum
, "-", ¬_checksum
);
99 return CalculateHWIDv3Checksum(not_checksum
) == checksum
;
102 } // anonymous namespace
106 bool IsHWIDCorrect(const std::string
& hwid
) {
107 return IsCorrectHWIDv2(hwid
) || IsCorrectExceptionalHWID(hwid
) ||
108 IsCorrectHWIDv3(hwid
);
111 bool IsMachineHWIDCorrect() {
112 #if !defined(GOOGLE_CHROME_BUILD)
115 base::CommandLine
* cmd_line
= base::CommandLine::ForCurrentProcess();
116 if (cmd_line
->HasSwitch(::switches::kTestType
))
118 if (!base::SysInfo::IsRunningOnChromeOS())
121 chromeos::system::StatisticsProvider
* stats
=
122 chromeos::system::StatisticsProvider::GetInstance();
123 if (!stats
->GetMachineStatistic(chromeos::system::kHardwareClassKey
, &hwid
)) {
124 LOG(ERROR
) << "Couldn't get machine statistic 'hardware_class'.";
127 if (!chromeos::IsHWIDCorrect(hwid
)) {
128 LOG(ERROR
) << "Machine has malformed HWID '" << hwid
<< "'.";
134 } // namespace chromeos