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 <sys/socket.h>
16 #include "credential_base.h"
17 #include "credential_message.h"
18 #include "hdc_huks.h"
19 #include "hdc_subscriber.h"
20 #include "password.h"
21
22 using namespace Hdc;
23 using namespace HdcCredentialBase;
24
25 Hdc::HdcHuks hdcHuks(HDC_PRIVATE_KEY_FILE_PWD_KEY_ALIAS);
26 Hdc::HdcPassword pwd(HDC_PRIVATE_KEY_FILE_PWD_KEY_ALIAS);
27
BytetoHex(const uint8_t * byteDate,size_t length)28 std::string BytetoHex(const uint8_t* byteDate, size_t length)
29 {
30 uint8_t tmp;
31 std::string encryptPwd;
32
33 for (size_t i = 0; i < length; i++) {
34 tmp = byteDate[i];
35 encryptPwd.push_back(pwd.GetHexChar(tmp >> 4)); // 4 get high 4 bits
36 encryptPwd.push_back(pwd.GetHexChar(tmp & 0x0F));
37 }
38 return encryptPwd;
39 }
40
ResetPwdKey(void)41 bool ResetPwdKey(void)
42 {
43 return hdcHuks.ResetHuksKey();
44 }
45
CredentialEncryptPwd(const std::string & messageStr)46 std::string CredentialEncryptPwd(const std::string& messageStr)
47 {
48 if (messageStr.size() != PASSWORD_LENGTH) {
49 WRITE_LOG(LOG_FATAL, "Invalid input length: expected %d, got %zu", PASSWORD_LENGTH, messageStr.size());
50 return "";
51 }
52 std::vector<uint8_t> encryptData;
53
54 bool encryptResult = hdcHuks.AesGcmEncrypt(reinterpret_cast<const uint8_t*>(messageStr.c_str()),
55 PASSWORD_LENGTH, encryptData);
56 if (!encryptResult) {
57 WRITE_LOG(LOG_FATAL, "CredentialEncryptPwd: AES GCM encryption failed.");
58 return "";
59 }
60
61 return std::string(reinterpret_cast<const char*>(encryptData.data()), encryptData.size());
62 }
63
EncryptPwd(const std::string & messageStr)64 std::string EncryptPwd(const std::string& messageStr)
65 {
66 if (!ResetPwdKey()) {
67 WRITE_LOG(LOG_FATAL, "EncryptPwd: ResetPwdKey failed.");
68 return "";
69 }
70
71 std::string encryptPwd = CredentialEncryptPwd(messageStr);
72 if (encryptPwd.empty()) {
73 WRITE_LOG(LOG_FATAL, "EncryptPwd: CredentialEncryptPwd failed.");
74 return "";
75 }
76
77 return encryptPwd;
78 }
79
DecryptPwd(const std::string & messageStr)80 std::string DecryptPwd(const std::string& messageStr)
81 {
82 uint8_t pwd[PASSWORD_LENGTH] = {0};
83 std::pair<uint8_t*, int> decryptPwd = hdcHuks.AesGcmDecrypt(messageStr);
84 if (decryptPwd.first == nullptr) {
85 WRITE_LOG(LOG_FATAL, "AesGcmDecrypt failed.");
86 return "";
87 }
88
89 do {
90 if (decryptPwd.second != PASSWORD_LENGTH) {
91 WRITE_LOG(LOG_FATAL, "Invalid pwd len %d", decryptPwd.second);
92 break;
93 }
94 int ret = memcpy_s(pwd, PASSWORD_LENGTH, decryptPwd.first, decryptPwd.second);
95 if (ret != EOK) {
96 WRITE_LOG(LOG_FATAL, "Copy failed.ret is %d", ret);
97 break;
98 }
99 } while (0);
100
101 memset_s(decryptPwd.first, decryptPwd.second, 0, decryptPwd.second);
102 delete[] decryptPwd.first;
103
104 std::string pwdStr(reinterpret_cast<const char*>(pwd), PASSWORD_LENGTH);
105 memset_s(pwd, PASSWORD_LENGTH, 0, PASSWORD_LENGTH);
106
107 return pwdStr;
108 }
109
ParseAndProcessMessageStr(const std::string & messageStr)110 std::string ParseAndProcessMessageStr(const std::string& messageStr)
111 {
112 CredentialMessage messageStruct(messageStr);
113 if (messageStruct.GetMessageBody().empty() ||
114 messageStruct.GetMessageVersion() != METHOD_VERSION_V1) {
115 WRITE_LOG(LOG_FATAL, "Invalid message structure or version not v1.");
116 return "";
117 }
118 std::string processMessageValue;
119 switch (messageStruct.GetMessageMethodType()) {
120 case METHOD_ENCRYPT: {
121 processMessageValue = EncryptPwd(messageStruct.GetMessageBody());
122 break;
123 }
124 case METHOD_DECRYPT: {
125 processMessageValue = DecryptPwd(messageStruct.GetMessageBody());
126 break;
127 }
128 default: {
129 WRITE_LOG(LOG_FATAL, "Unsupported message method type.");
130 return "";
131 }
132 }
133
134 messageStruct.SetMessageBody(processMessageValue);
135
136 return messageStruct.Construct();
137 }
138
CreateAndBindSocket(const std::string & socketPath)139 int CreateAndBindSocket(const std::string& socketPath)
140 {
141 if (access(socketPath.c_str(), F_OK) == 0) {
142 if (remove(socketPath.c_str()) < 0) {
143 WRITE_LOG(LOG_FATAL, "Failed to remove existing socket file, message: %s.", strerror(errno));
144 return -1;
145 }
146 }
147
148 int sockfd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
149 if (sockfd < 0) {
150 WRITE_LOG(LOG_FATAL, "Failed to create socket.");
151 return -1;
152 }
153
154 struct sockaddr_un addr = {};
155 addr.sun_family = AF_UNIX;
156 size_t maxPathLen = sizeof(addr.sun_path) - 1;
157 size_t pathLen = socketPath.size();
158 if (pathLen > sizeof(addr.sun_path) - 1) {
159 WRITE_LOG(LOG_FATAL, "Socket path too long.");
160 close(sockfd);
161 return -1;
162 }
163 memcpy_s(addr.sun_path, maxPathLen, socketPath.c_str(), pathLen);
164
165 if (bind(sockfd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)) < 0) {
166 WRITE_LOG(LOG_FATAL, "Failed to bind socket, message: %s.", strerror(errno));
167 close(sockfd);
168 return -1;
169 }
170
171 if (chmod(addr.sun_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) != 0) {
172 WRITE_LOG(LOG_FATAL, "Failed to chmod socket file, message: %s.", strerror(errno));
173 close(sockfd);
174 return -1;
175 }
176 return sockfd;
177 }
178
CredentialUsage()179 std::string CredentialUsage()
180 {
181 std::string ret = "";
182 ret = "\n Harmony device connector (HDC) credential process \n\n"
183 "Usage: hdc_credential [options]...\n"
184 "\n"
185 "general options:\n"
186 " -h - Print help\n"
187 " -v - Print version information\n";
188 return ret;
189 }
190
CredentialVersion()191 std::string CredentialVersion()
192 {
193 const uint8_t a = 'a';
194 uint8_t major = (CREDENTIAL_VERSION_NUMBER >> 28) & 0xff;
195 uint8_t minor = (CREDENTIAL_VERSION_NUMBER << 4 >> 24) & 0xff;
196 uint8_t version = (CREDENTIAL_VERSION_NUMBER << 12 >> 24) & 0xff;
197 uint8_t fix = (CREDENTIAL_VERSION_NUMBER << 20 >> 28) & 0xff; // max 16, tail is p
198 std::string ver = StringFormat("%x.%x.%x%c", major, minor, version, a + fix);
199 return "Ver: " + ver;
200 }
201
SplitCommandToArgs(int argc,const char ** argv)202 bool SplitCommandToArgs(int argc, const char **argv)
203 {
204 if (argc == CMD_ARG1_COUNT) {
205 if (!strcmp(argv[1], "-h")) {
206 std::string usage = CredentialUsage();
207 fprintf(stderr, "%s", usage.c_str());
208 return false;
209 } else if (!strcmp(argv[1], "-v")) {
210 std::string ver = CredentialVersion();
211 fprintf(stderr, "%s\n", ver.c_str());
212 return false;
213 }
214 }
215 if (argc != 1) {
216 fprintf(stderr, "Invalid input parameters, please recheck.\n");
217 std::string usage = CredentialUsage();
218 fprintf(stderr, "%s\n", usage.c_str());
219 return false;
220 }
221 return true;
222 }
main(int argc,const char * argv[])223 int main(int argc, const char *argv[])
224 {
225 if (!SplitCommandToArgs(argc, argv)) {
226 return 0;
227 }
228 if (HdcAccountSubscriberMonitor() != 0) {
229 WRITE_LOG(LOG_FATAL, "HdcAccountSubscriberMonitor failed");
230 return 0;
231 }
232 // fresh all accounts path when process restart.
233 FreshAccountsPath();
234
235 int sockfd = CreateAndBindSocket(HDC_CREDENTIAL_SOCKET_REAL_PATH.c_str());
236 if (sockfd < 0) {
237 WRITE_LOG(LOG_FATAL, "Failed to create and bind socket.");
238 return -1;
239 }
240 if (listen(sockfd, SOCKET_CLIENT_NUMS) < 0) {
241 WRITE_LOG(LOG_FATAL, "Failed to listen on socket.");
242 close(sockfd);
243 return -1;
244 }
245 WRITE_LOG(LOG_INFO, "Listening on socket: %s", HDC_CREDENTIAL_SOCKET_REAL_PATH.c_str());
246 bool running = true;
247 while (running) {
248 int connfd = accept(sockfd, nullptr, nullptr);
249 if (connfd < 0) {
250 WRITE_LOG(LOG_FATAL, "Failed to accept connection!");
251 continue;
252 }
253
254 char buffer[MESSAGE_STR_MAX_LEN] = {0};
255 ssize_t bytesRead = read(connfd, buffer, sizeof(buffer) - 1);
256 if (bytesRead <= 0) {
257 WRITE_LOG(LOG_FATAL, "Error: Failed to read from socket.");
258 close(connfd);
259 continue;
260 }
261 std::string sendBuf = ParseAndProcessMessageStr(std::string(buffer, bytesRead));
262 if (sendBuf.empty()) {
263 WRITE_LOG(LOG_FATAL, "Error: Processed message is empty.");
264 close(connfd);
265 continue;
266 }
267
268 size_t bytesSend = write(connfd, sendBuf.c_str(), sendBuf.size());
269 if (bytesSend != sendBuf.size()) {
270 WRITE_LOG(LOG_FATAL, "Failed to send message.");
271 close(connfd);
272 continue;
273 }
274 memset_s(buffer, sizeof(buffer), 0, sizeof(buffer)); // Clear the buffer
275 close(connfd);
276 } // Keep the server running indefinitely
277 WRITE_LOG(LOG_FATAL, "hdc_credential stopped.");
278 close(sockfd);
279 unlink(HDC_CREDENTIAL_SOCKET_REAL_PATH.c_str());
280 return 0;
281 }