xref: /aosp_15_r20/external/libbrillo/brillo/cryptohome.cc (revision 1a96fba65179ea7d3f56207137718607415c5953)
1*1a96fba6SXin Li // Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2*1a96fba6SXin Li // Use of this source code is governed by a BSD-style license that can be
3*1a96fba6SXin Li // found in the LICENSE file.
4*1a96fba6SXin Li 
5*1a96fba6SXin Li #include "brillo/cryptohome.h"
6*1a96fba6SXin Li 
7*1a96fba6SXin Li #include <openssl/sha.h>
8*1a96fba6SXin Li #include <stdint.h>
9*1a96fba6SXin Li 
10*1a96fba6SXin Li #include <algorithm>
11*1a96fba6SXin Li #include <cstring>
12*1a96fba6SXin Li #include <limits>
13*1a96fba6SXin Li #include <vector>
14*1a96fba6SXin Li 
15*1a96fba6SXin Li #include <base/files/file_util.h>
16*1a96fba6SXin Li #include <base/strings/string_number_conversions.h>
17*1a96fba6SXin Li #include <base/strings/stringprintf.h>
18*1a96fba6SXin Li 
19*1a96fba6SXin Li using base::FilePath;
20*1a96fba6SXin Li 
21*1a96fba6SXin Li namespace brillo {
22*1a96fba6SXin Li namespace cryptohome {
23*1a96fba6SXin Li namespace home {
24*1a96fba6SXin Li 
25*1a96fba6SXin Li const char kGuestUserName[] = "$guest";
26*1a96fba6SXin Li 
27*1a96fba6SXin Li // Path to user homes mounted with the mount_hidden option. The user home mount
28*1a96fba6SXin Li // will be located at:
29*1a96fba6SXin Li // kHiddenUserHomeBaseDir/<sanitized_user_name>/kHiddenUserHomeMountSubdir
30*1a96fba6SXin Li const char kHiddenUserHomeBaseDir[] = "/home/.shadow";
31*1a96fba6SXin Li const char kHiddenUserHomeMountSubdir[] = "mount";
32*1a96fba6SXin Li 
33*1a96fba6SXin Li // Subdirectory of a user home mount where daemon-specific data is stored.
34*1a96fba6SXin Li // This is used to assemble daemon data storage paths for hidden user home
35*1a96fba6SXin Li // mounts.
36*1a96fba6SXin Li const char kHiddenUserHomeRootSubdir[] = "root";
37*1a96fba6SXin Li 
38*1a96fba6SXin Li static char g_user_home_prefix[PATH_MAX] = "/home/user/";
39*1a96fba6SXin Li static char g_root_home_prefix[PATH_MAX] = "/home/root/";
40*1a96fba6SXin Li static char g_system_salt_path[PATH_MAX] = "/home/.shadow/salt";
41*1a96fba6SXin Li 
42*1a96fba6SXin Li static std::string* salt = nullptr;
43*1a96fba6SXin Li 
EnsureSystemSaltIsLoaded()44*1a96fba6SXin Li bool EnsureSystemSaltIsLoaded() {
45*1a96fba6SXin Li   if (salt && !salt->empty())
46*1a96fba6SXin Li     return true;
47*1a96fba6SXin Li   FilePath salt_path(g_system_salt_path);
48*1a96fba6SXin Li   int64_t file_size;
49*1a96fba6SXin Li   if (!base::GetFileSize(salt_path, &file_size)) {
50*1a96fba6SXin Li     PLOG(ERROR) << "Could not get size of system salt: " << g_system_salt_path;
51*1a96fba6SXin Li     return false;
52*1a96fba6SXin Li   }
53*1a96fba6SXin Li   if (file_size > static_cast<int64_t>(std::numeric_limits<int>::max())) {
54*1a96fba6SXin Li     LOG(ERROR) << "System salt too large: " << file_size;
55*1a96fba6SXin Li     return false;
56*1a96fba6SXin Li   }
57*1a96fba6SXin Li   std::vector<char> buf;
58*1a96fba6SXin Li   buf.resize(file_size);
59*1a96fba6SXin Li   unsigned int data_read = base::ReadFile(salt_path, buf.data(), file_size);
60*1a96fba6SXin Li   if (data_read != file_size) {
61*1a96fba6SXin Li     PLOG(ERROR) << "Could not read entire file: " << data_read
62*1a96fba6SXin Li                 << " != " << file_size;
63*1a96fba6SXin Li     return false;
64*1a96fba6SXin Li   }
65*1a96fba6SXin Li 
66*1a96fba6SXin Li   if (!salt)
67*1a96fba6SXin Li     salt = new std::string();
68*1a96fba6SXin Li   salt->assign(buf.data(), file_size);
69*1a96fba6SXin Li   return true;
70*1a96fba6SXin Li }
71*1a96fba6SXin Li 
SanitizeUserName(const std::string & username)72*1a96fba6SXin Li std::string SanitizeUserName(const std::string& username) {
73*1a96fba6SXin Li   if (!EnsureSystemSaltIsLoaded())
74*1a96fba6SXin Li     return std::string();
75*1a96fba6SXin Li 
76*1a96fba6SXin Li   unsigned char binmd[SHA_DIGEST_LENGTH];
77*1a96fba6SXin Li   std::string lowercase(username);
78*1a96fba6SXin Li   std::transform(
79*1a96fba6SXin Li       lowercase.begin(), lowercase.end(), lowercase.begin(), ::tolower);
80*1a96fba6SXin Li   SHA_CTX ctx;
81*1a96fba6SXin Li   SHA1_Init(&ctx);
82*1a96fba6SXin Li   SHA1_Update(&ctx, salt->data(), salt->size());
83*1a96fba6SXin Li   SHA1_Update(&ctx, lowercase.data(), lowercase.size());
84*1a96fba6SXin Li   SHA1_Final(binmd, &ctx);
85*1a96fba6SXin Li   std::string final = base::HexEncode(binmd, sizeof(binmd));
86*1a96fba6SXin Li   // Stay compatible with CryptoLib::HexEncodeToBuffer()
87*1a96fba6SXin Li   std::transform(final.begin(), final.end(), final.begin(), ::tolower);
88*1a96fba6SXin Li   return final;
89*1a96fba6SXin Li }
90*1a96fba6SXin Li 
GetUserPathPrefix()91*1a96fba6SXin Li FilePath GetUserPathPrefix() {
92*1a96fba6SXin Li   return FilePath(g_user_home_prefix);
93*1a96fba6SXin Li }
94*1a96fba6SXin Li 
GetRootPathPrefix()95*1a96fba6SXin Li FilePath GetRootPathPrefix() {
96*1a96fba6SXin Li   return FilePath(g_root_home_prefix);
97*1a96fba6SXin Li }
98*1a96fba6SXin Li 
GetHashedUserPath(const std::string & hashed_username)99*1a96fba6SXin Li FilePath GetHashedUserPath(const std::string& hashed_username) {
100*1a96fba6SXin Li   return FilePath(
101*1a96fba6SXin Li       base::StringPrintf("%s%s", g_user_home_prefix, hashed_username.c_str()));
102*1a96fba6SXin Li }
103*1a96fba6SXin Li 
GetUserPath(const std::string & username)104*1a96fba6SXin Li FilePath GetUserPath(const std::string& username) {
105*1a96fba6SXin Li   if (!EnsureSystemSaltIsLoaded())
106*1a96fba6SXin Li     return FilePath();
107*1a96fba6SXin Li   return GetHashedUserPath(SanitizeUserName(username));
108*1a96fba6SXin Li }
109*1a96fba6SXin Li 
GetRootPath(const std::string & username)110*1a96fba6SXin Li FilePath GetRootPath(const std::string& username) {
111*1a96fba6SXin Li   if (!EnsureSystemSaltIsLoaded())
112*1a96fba6SXin Li     return FilePath();
113*1a96fba6SXin Li   return FilePath(base::StringPrintf(
114*1a96fba6SXin Li       "%s%s", g_root_home_prefix, SanitizeUserName(username).c_str()));
115*1a96fba6SXin Li }
116*1a96fba6SXin Li 
GetDaemonPath(const std::string & username,const std::string & daemon)117*1a96fba6SXin Li FilePath GetDaemonPath(const std::string& username, const std::string& daemon) {
118*1a96fba6SXin Li   if (!EnsureSystemSaltIsLoaded())
119*1a96fba6SXin Li     return FilePath();
120*1a96fba6SXin Li   return GetRootPath(username).Append(daemon);
121*1a96fba6SXin Li }
122*1a96fba6SXin Li 
GetDaemonPathForHiddenUserHome(const std::string & username,const std::string & daemon)123*1a96fba6SXin Li FilePath GetDaemonPathForHiddenUserHome(const std::string& username,
124*1a96fba6SXin Li                                         const std::string& daemon) {
125*1a96fba6SXin Li   if (!EnsureSystemSaltIsLoaded())
126*1a96fba6SXin Li     return FilePath();
127*1a96fba6SXin Li 
128*1a96fba6SXin Li   return FilePath(kHiddenUserHomeBaseDir)
129*1a96fba6SXin Li       .Append(SanitizeUserName(username))
130*1a96fba6SXin Li       .Append(kHiddenUserHomeMountSubdir)
131*1a96fba6SXin Li       .Append(kHiddenUserHomeRootSubdir)
132*1a96fba6SXin Li       .Append(daemon);
133*1a96fba6SXin Li }
134*1a96fba6SXin Li 
IsSanitizedUserName(const std::string & sanitized)135*1a96fba6SXin Li bool IsSanitizedUserName(const std::string& sanitized) {
136*1a96fba6SXin Li   std::vector<uint8_t> bytes;
137*1a96fba6SXin Li   return (sanitized.length() == 2 * SHA_DIGEST_LENGTH) &&
138*1a96fba6SXin Li          base::HexStringToBytes(sanitized, &bytes);
139*1a96fba6SXin Li }
140*1a96fba6SXin Li 
SetUserHomePrefix(const std::string & prefix)141*1a96fba6SXin Li void SetUserHomePrefix(const std::string& prefix) {
142*1a96fba6SXin Li   if (prefix.length() < sizeof(g_user_home_prefix)) {
143*1a96fba6SXin Li     snprintf(
144*1a96fba6SXin Li         g_user_home_prefix, sizeof(g_user_home_prefix), "%s", prefix.c_str());
145*1a96fba6SXin Li   }
146*1a96fba6SXin Li }
147*1a96fba6SXin Li 
SetRootHomePrefix(const std::string & prefix)148*1a96fba6SXin Li void SetRootHomePrefix(const std::string& prefix) {
149*1a96fba6SXin Li   if (prefix.length() < sizeof(g_root_home_prefix)) {
150*1a96fba6SXin Li     snprintf(
151*1a96fba6SXin Li         g_root_home_prefix, sizeof(g_root_home_prefix), "%s", prefix.c_str());
152*1a96fba6SXin Li   }
153*1a96fba6SXin Li }
154*1a96fba6SXin Li 
GetSystemSalt()155*1a96fba6SXin Li std::string* GetSystemSalt() {
156*1a96fba6SXin Li   return salt;
157*1a96fba6SXin Li }
158*1a96fba6SXin Li 
SetSystemSalt(std::string * value)159*1a96fba6SXin Li void SetSystemSalt(std::string* value) {
160*1a96fba6SXin Li   salt = value;
161*1a96fba6SXin Li }
162*1a96fba6SXin Li 
163*1a96fba6SXin Li }  // namespace home
164*1a96fba6SXin Li }  // namespace cryptohome
165*1a96fba6SXin Li }  // namespace brillo
166