• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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