1 /*
2 * Copyright (C) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "base.h"
16 #include "common.h"
17 #include "password.h"
18 #include "sys/socket.h"
19
20 namespace Hdc {
21 static const char* SPECIAL_CHARS = "~!@#$%^&*()-_=+\\|[{}];:'\",<.>/?";
22 static const uint8_t INVALID_HEX_CHAR_TO_INT_RESULT = 255;
23
SendToUnixSocketAndRecvStr(const char * socketPath,const std::string & messageStr)24 std::string HdcPassword::SendToUnixSocketAndRecvStr(const char *socketPath, const std::string &messageStr)
25 {
26 int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
27 if (sockfd < 0) {
28 WRITE_LOG(LOG_FATAL, "Failed to create socket.");
29 return "";
30 }
31
32 struct sockaddr_un addr = {};
33 addr.sun_family = AF_UNIX;
34 size_t maxPathLen = sizeof(addr.sun_path) - 1;
35 size_t pathLen = strlen(socketPath);
36 if (pathLen > maxPathLen) {
37 WRITE_LOG(LOG_FATAL, "Socket path too long.");
38 close(sockfd);
39 return "";
40 }
41 memcpy_s(addr.sun_path, maxPathLen, socketPath, pathLen);
42
43 if (connect(sockfd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)) < 0) {
44 WRITE_LOG(LOG_FATAL, "Failed to connect to socket.");
45 close(sockfd);
46 return "";
47 }
48
49 ssize_t bytesSend = send(sockfd, messageStr.c_str(), messageStr.size(), 0);
50 if (bytesSend < 0) {
51 WRITE_LOG(LOG_FATAL, "Failed to send message.");
52 close(sockfd);
53 return "";
54 }
55
56 std::string response;
57 char buffer[MESSAGE_STR_MAX_LEN] = {0};
58 ssize_t bytesRead = 0;
59 while ((bytesRead = recv(sockfd, buffer, sizeof(buffer) - 1, 0)) > 0) {
60 response.append(buffer, bytesRead);
61 if (memset_s(buffer, sizeof(buffer), 0, MESSAGE_STR_MAX_LEN) != EOK) {
62 WRITE_LOG(LOG_FATAL, "memset_s failed.");
63 close(sockfd);
64 return "";
65 }
66 }
67 if (bytesRead < 0) {
68 WRITE_LOG(LOG_FATAL, "Failed to read from socket.");
69 close(sockfd);
70 return "";
71 }
72
73 close(sockfd);
74 return response;
75 }
76
SplicMessageStr(const std::string & str,const size_t type)77 std::string HdcPassword::SplicMessageStr(const std::string &str, const size_t type)
78 {
79 if (str.empty()) {
80 WRITE_LOG(LOG_FATAL, "Input string is empty.");
81 return "";
82 }
83 const size_t bodyLen = str.size();
84 size_t totalLength = MESSAGE_METHOD_POS + MESSAGE_METHOD_LEN +
85 MESSAGE_LENGTH_LEN + bodyLen;
86
87 std::string messageMethodTypeStr = IntToStringWithPadding(type, MESSAGE_METHOD_LEN);
88 if (messageMethodTypeStr.length() != MESSAGE_METHOD_LEN) {
89 WRITE_LOG(LOG_FATAL, "messageMethodTypeStr length must be:%d,now is:%s",
90 MESSAGE_METHOD_LEN, messageMethodTypeStr.c_str());
91 return "";
92 }
93
94 std::string messageBodyLen = IntToStringWithPadding(str.length(), MESSAGE_LENGTH_LEN);
95 if (messageBodyLen.empty() || (messageBodyLen.length() > MESSAGE_LENGTH_LEN)) {
96 WRITE_LOG(LOG_FATAL, "messageBodyLen length must be:%d,now is:%s", MESSAGE_LENGTH_LEN, messageBodyLen.c_str());
97 return "";
98 }
99
100 std::string result;
101 result.reserve(totalLength);
102 result.push_back('0' + METHOD_VERSION_V1);
103 result.append(messageMethodTypeStr);
104 result.append(messageBodyLen);
105 result.append(str);
106 if (result.size() != totalLength) {
107 WRITE_LOG(LOG_FATAL, "size mismatch. Expected: %zu, Actual: %zu", totalLength, result.size());
108 return "";
109 }
110 return result;
111 }
112
EncryptGetPwdValue(uint8_t * pwd,int pwdLen)113 std::vector<uint8_t> HdcPassword::EncryptGetPwdValue(uint8_t *pwd, int pwdLen)
114 {
115 std::string sendStr = SplicMessageStr(reinterpret_cast<const char*>(pwd), METHOD_ENCRYPT);
116 if (sendStr.empty()) {
117 WRITE_LOG(LOG_FATAL, "sendStr is empty.");
118 return std::vector<uint8_t>();
119 }
120 std::string recvStr = SendToUnixSocketAndRecvStr(HDC_CREDENTIAL_SOCKET_SANDBOX_PATH.c_str(), sendStr);
121 memset_s(sendStr.data(), sendStr.size(), 0, sendStr.size());
122 if (recvStr.empty()) {
123 WRITE_LOG(LOG_FATAL, "recvStr is empty.");
124 return std::vector<uint8_t>();
125 }
126
127 CredentialMessage messageStruct(recvStr);
128 memset_s(recvStr.data(), recvStr.size(), 0, recvStr.size());
129 if (messageStruct.GetMessageBodyLen() > 0) {
130 std::string body = messageStruct.GetMessageBody();
131 std::vector<uint8_t> retByteData = String2Uint8(body, messageStruct.GetMessageBodyLen());
132 if (!body.empty()) {
133 memset_s(&body[0], body.size(), 0, body.size());
134 }
135 return retByteData;
136 } else {
137 WRITE_LOG(LOG_FATAL, "Error: messageBodyLen is 0.");
138 return std::vector<uint8_t>();
139 }
140 }
141
DecryptGetPwdValue(const std::string & encryptData)142 std::pair<uint8_t*, int> HdcPassword::DecryptGetPwdValue(const std::string &encryptData)
143 {
144 std::string sendStr = SplicMessageStr(encryptData, METHOD_DECRYPT);
145 if (sendStr.empty()) {
146 WRITE_LOG(LOG_FATAL, "sendStr is empty.");
147 return std::make_pair(nullptr, 0);
148 }
149 std::string recvStr = SendToUnixSocketAndRecvStr(HDC_CREDENTIAL_SOCKET_SANDBOX_PATH.c_str(), sendStr);
150 memset_s(sendStr.data(), sendStr.size(), 0, sendStr.size());
151 if (recvStr.empty()) {
152 WRITE_LOG(LOG_FATAL, "recvStr is empty.");
153 return std::make_pair(nullptr, 0);
154 }
155
156 CredentialMessage messageStruct(recvStr);
157 memset_s(recvStr.data(), recvStr.size(), 0, recvStr.size());
158 if (messageStruct.GetMessageBodyLen() > 0) {
159 uint8_t *keyData = new uint8_t[messageStruct.GetMessageBodyLen() + 1];
160 std::copy(messageStruct.GetMessageBody().begin(), messageStruct.GetMessageBody().end(), keyData);
161 keyData[messageStruct.GetMessageBodyLen()] = '\0';
162 return std::make_pair(keyData, messageStruct.GetMessageBodyLen());
163 } else {
164 WRITE_LOG(LOG_FATAL, "Error: messageBodyLen is 0.");
165 return std::make_pair(nullptr, 0);
166 }
167 }
HdcPassword(const std::string & pwdKeyAlias)168 HdcPassword::HdcPassword(const std::string &pwdKeyAlias):hdcHuks(pwdKeyAlias)
169 {
170 memset_s(pwd, sizeof(pwd), 0, sizeof(pwd));
171 }
172
~HdcPassword()173 HdcPassword::~HdcPassword()
174 {
175 memset_s(pwd, sizeof(pwd), 0, sizeof(pwd));
176 }
177
GetPassword(void)178 std::pair<uint8_t*, int> HdcPassword::GetPassword(void)
179 {
180 return std::make_pair(pwd, PASSWORD_LENGTH);
181 }
182
GetEncryptPassword(void)183 std::string HdcPassword::GetEncryptPassword(void)
184 {
185 return encryptPwd;
186 }
187
GeneratePassword(void)188 void HdcPassword::GeneratePassword(void)
189 {
190 // password = 1special letter + 1lower letter + 8number letter
191 uint32_t randomNum = Base::GetSecureRandom();
192 this->pwd[0] = SPECIAL_CHARS[(randomNum & 0xFFFF0000) % strlen(SPECIAL_CHARS)];
193 const int lowercaseCount = 26;
194 this->pwd[1] = 'a' + ((randomNum & 0x0000FFFF) % lowercaseCount);
195
196 const int numberCount = 10;
197 int numberStartIndex = 2;
198 randomNum = Base::GetSecureRandom();
199 unsigned char *randomChar = reinterpret_cast<unsigned char*>(&randomNum);
200 for (int i = 0; i < static_cast<int>(sizeof(randomNum)) && numberStartIndex < PASSWORD_LENGTH; i++) {
201 unsigned char byteValue = randomChar[i];
202 this->pwd[numberStartIndex++] = ((byteValue >> 4) % numberCount) + '0'; // 4 high 4 bits
203 this->pwd[numberStartIndex++] = ((byteValue & 0x0F) % numberCount) + '0';
204 }
205 }
206
GetHexChar(uint8_t data)207 char HdcPassword::GetHexChar(uint8_t data)
208 {
209 const uint8_t decimal = 10;
210 return ((data < decimal) ? ('0' + data) : ('A' + (data - decimal)));
211 }
212
ByteToHex(std::vector<uint8_t> & byteData)213 void HdcPassword::ByteToHex(std::vector<uint8_t>& byteData)
214 {
215 uint8_t tmp;
216 for (size_t i = 0; i < byteData.size(); i++) {
217 tmp = byteData[i];
218 encryptPwd.push_back(GetHexChar(tmp >> 4)); // 4 get high 4 bits
219 encryptPwd.push_back(GetHexChar(tmp & 0x0F));
220 }
221 }
222
HexToByte(std::vector<uint8_t> & hexData)223 bool HdcPassword::HexToByte(std::vector<uint8_t>& hexData)
224 {
225 if ((hexData.size() % 2) != 0) { // 2 hexData len must be even
226 WRITE_LOG(LOG_FATAL, "invalid data size %d", hexData.size());
227 return false;
228 }
229 for (size_t i = 0; i < hexData.size(); i += 2) { // 2 hex to 1 byte
230 uint8_t firstHalfByte = HexCharToInt(hexData[i]);
231 uint8_t lastHalfByte = HexCharToInt(hexData[i + 1]);
232 if (firstHalfByte == INVALID_HEX_CHAR_TO_INT_RESULT || lastHalfByte == INVALID_HEX_CHAR_TO_INT_RESULT) {
233 return false;
234 }
235 encryptPwd.push_back((firstHalfByte << 4) | lastHalfByte); // 4 high 4 bites
236 }
237 return true;
238 }
239
HexCharToInt(uint8_t data)240 uint8_t HdcPassword::HexCharToInt(uint8_t data)
241 {
242 const uint8_t decimal = 10;
243
244 if (data >= '0' && data <= '9') {
245 return data - '0';
246 }
247 if (data >= 'A' && data <= 'F') {
248 return data - 'A' + decimal;
249 }
250
251 WRITE_LOG(LOG_FATAL, "invalid data %d", data);
252 return INVALID_HEX_CHAR_TO_INT_RESULT;
253 }
254
DecryptPwd(std::vector<uint8_t> & encryptData)255 bool HdcPassword::DecryptPwd(std::vector<uint8_t>& encryptData)
256 {
257 bool success = false;
258
259 ClearEncryptPwd();
260 if (!HexToByte(encryptData)) {
261 return false;
262 }
263 std::pair<uint8_t*, int> result = DecryptGetPwdValue(encryptPwd);
264 if (result.first == nullptr) {
265 return false;
266 }
267 do {
268 if (result.second != PASSWORD_LENGTH) {
269 WRITE_LOG(LOG_FATAL, "Invalid pwd len %d", result.second);
270 break;
271 }
272 int ret = memcpy_s(this->pwd, PASSWORD_LENGTH, result.first, result.second);
273 if (ret != EOK) {
274 WRITE_LOG(LOG_FATAL, "copy pwd failed %d", ret);
275 break;
276 }
277 success = true;
278 } while (0);
279
280 if (memset_s(result.first, result.second, 0, PASSWORD_LENGTH) != EOK) {
281 WRITE_LOG(LOG_FATAL, "memset_s failed.");
282 success = false;
283 }
284 delete[] result.first;
285 return success;
286 }
287
EncryptPwd(void)288 bool HdcPassword::EncryptPwd(void)
289 {
290 ClearEncryptPwd();
291 std::vector<uint8_t> encryptData = EncryptGetPwdValue(pwd, PASSWORD_LENGTH);
292 if (encryptData.size() == 0) {
293 return false;
294 }
295 ByteToHex(encryptData);
296 return true;
297 }
298
ResetPwdKey()299 bool HdcPassword::ResetPwdKey()
300 {
301 return hdcHuks.ResetHuksKey();
302 }
303
GetEncryptPwdLength()304 int HdcPassword::GetEncryptPwdLength()
305 {
306 return HdcHuks::CaculateGcmEncryptLen(PASSWORD_LENGTH) * 2; // 2, bytes to hex
307 }
308
ClearEncryptPwd(void)309 void HdcPassword::ClearEncryptPwd(void)
310 {
311 encryptPwd.clear();
312 }
313 } // namespace Hdc