• 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 <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 }