• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025-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 <libgen.h>
16 #include <set>
17 #include <unistd.h>
18 #include "cmd_util.h"
19 #include "params_run_tool.h"
20 #include "constant.h"
21 #include "param_constants.h"
22 
23 namespace OHOS {
24 namespace SignatureTools {
25 const std::regex INTEGER_PATTERN = std::regex("\\d{1,10}");
26 
String2Bool(Options * options,const std::string & option)27 bool CmdUtil::String2Bool(Options* options, const std::string& option)
28 {
29     std::string val = options->GetString(option);
30     if (val == "1" || val == "true" || val == "TRUE") {
31         (*options)[option] = true;
32     } else if (val == "0" || val == "false" || val == "FALSE") {
33         (*options)[option] = false;
34     } else {
35         PrintErrorNumberMsg("COMMAND_PARAM_ERROR", COMMAND_PARAM_ERROR,
36                             val + " is not valid value for " + "-" + option);
37         return false;
38     }
39     return true;
40 }
41 
UpdateParamForVariantCertInt(const ParamsSharedPtr & param)42 static bool UpdateParamForVariantCertInt(const ParamsSharedPtr& param)
43 {
44     int defaultValidity = 0;
45     Options* options = param->GetOptions();
46     if (options->count(Options::VALIDITY)) {
47         int validity = 0;
48         std::string val = options->GetString(Options::VALIDITY);
49         for (char x : val) {
50             if (!isdigit(x)) {
51                 PrintErrorNumberMsg("COMMAND_PARAM_ERROR", COMMAND_PARAM_ERROR, "Invalid parameter '"
52                                     + val + "', You should fill in the numbers");
53                 return false;
54             }
55         }
56         if (!StringUtils::CheckStringToint(val, validity)) {
57             PrintErrorNumberMsg("COMMAND_PARAM_ERROR", COMMAND_PARAM_ERROR, "Invalid parameter '"
58                                 + val + "'");
59             return false;
60         }
61         validity *= ONE_DAY_TIME;
62         (*options)[Options::VALIDITY] = validity;
63     } else if (param->GetMethod() == GENERATE_CA || param->GetMethod() == GENERATE_APP_CERT ||
64                param->GetMethod() == GENERATE_PROFILE_CERT) {
65         defaultValidity = DEFAULT_VALIDITY_DAYS * ONE_DAY_TIME;
66         (*options)[Options::VALIDITY] = defaultValidity;
67     } else if (param->GetMethod() == GENERATE_CERT) {
68         defaultValidity = DEFAULT_CUSTOM_VALIDITY_DAYS * ONE_DAY_TIME;
69         (*options)[Options::VALIDITY] = defaultValidity;
70     }
71     return true;
72 }
73 
UpdateParamForVariantInt(const ParamsSharedPtr & param)74 static bool UpdateParamForVariantInt(const ParamsSharedPtr& param)
75 {
76     Options* options = param->GetOptions();
77     // general
78     if (options->count(Options::KEY_SIZE)) {
79         std::string keySize = options->GetString(Options::KEY_SIZE);
80         if (keySize == "NIST-P-256") {
81             (*options)[Options::KEY_SIZE] = NIST_P_256;
82         } else if (keySize == "NIST-P-384") {
83             (*options)[Options::KEY_SIZE] = NIST_P_384;
84         } else {
85             PrintErrorNumberMsg("COMMAND_ERROR", COMMAND_ERROR, "not supported '" + keySize
86                                 + "' Key algorithms length");
87             return false;
88         }
89     }
90     if (!UpdateParamForVariantCertInt(param)) {
91         return false;
92     }
93     return true;
94 }
95 
UpdateParamForVariantBoolKeyUsage(const ParamsSharedPtr & param)96 static bool UpdateParamForVariantBoolKeyUsage(const ParamsSharedPtr& param)
97 {
98     Options* options = param->GetOptions();
99 
100     // The bool type is used only by the "generate-cert" module
101     if (options->count(Options::KEY_USAGE_CRITICAL)) {
102         if (!CmdUtil::String2Bool(options, Options::KEY_USAGE_CRITICAL)) {
103             return false;
104         }
105     } else if (param->GetMethod() == GENERATE_CERT) {
106         (*options)[Options::KEY_USAGE_CRITICAL] = DEFAULT_KEY_USAGE_CRITICAL;
107     }
108 
109     // The bool type is used only by the "generate-cert" module
110     if (options->count(Options::EXT_KEY_USAGE_CRITICAL)) {
111         if (!CmdUtil::String2Bool(options, Options::EXT_KEY_USAGE_CRITICAL)) {
112             return false;
113         }
114     } else if (param->GetMethod() == GENERATE_CERT) {
115         (*options)[Options::EXT_KEY_USAGE_CRITICAL] = DEFAULT_EXT_KEY_USAGE_CRITICAL;
116     }
117     return true;
118 }
119 
UpdateParamForVariantBoolProfileSigned(const ParamsSharedPtr & param)120 static bool UpdateParamForVariantBoolProfileSigned(const ParamsSharedPtr& param)
121 {
122     Options* options = param->GetOptions();
123 
124     // The bool type is used only by the "sign-elf" module
125     if (options->count(Options::PROFILE_SIGNED)) {
126         std::string val = options->GetString(Options::PROFILE_SIGNED);
127         if (val == "1" || val == "true" || val == "TRUE") {
128             (*options)[Options::PROFILE_SIGNED] = DEFAULT_PROFILE_SIGNED_1;
129         } else if (val == "0" || val == "false" || val == "FALSE") {
130             (*options)[Options::PROFILE_SIGNED] = DEFAULT_PROFILE_SIGNED_0;
131         } else {
132             PrintErrorNumberMsg("COMMAND_PARAM_ERROR", COMMAND_PARAM_ERROR,
133                                 val + " is not valid value for "+"-" + Options::PROFILE_SIGNED);
134             return false;
135         }
136     } else if (param->GetMethod() == SIGN_ELF) {
137         (*options)[Options::PROFILE_SIGNED] = DEFAULT_PROFILE_SIGNED_1;
138     }
139 
140     return true;
141 }
142 
UpdateParamForVariantBoolSelfSign(const ParamsSharedPtr & param)143 static bool UpdateParamForVariantBoolSelfSign(const ParamsSharedPtr& param)
144 {
145     Options* options = param->GetOptions();
146     // The bool type is used only by the "sign-elf" module
147     if (options->count(Options::SELF_SIGN)) {
148         std::string val = options->GetString(Options::SELF_SIGN);
149         if (val == "1" || val == "true" || val == "TRUE") {
150             (*options)[Options::SELF_SIGN] = ParamConstants::SELF_SIGN_TYPE_1;
151         } else if (val == "0" || val == "false" || val == "FALSE") {
152             (*options)[Options::SELF_SIGN] = ParamConstants::SELF_SIGN_TYPE_0;
153         } else {
154             PrintErrorNumberMsg("COMMAND_PARAM_ERROR", COMMAND_PARAM_ERROR,
155                                 val + " is not valid value for "+"-" + Options::SELF_SIGN);
156             return false;
157         }
158     } else if (param->GetMethod() == SIGN_ELF) {
159         (*options)[Options::SELF_SIGN] = ParamConstants::SELF_SIGN_TYPE_0;
160     }
161 
162     return true;
163 }
164 
GetParentPath(const std::string & outFilePath)165 static std::string GetParentPath(const std::string &outFilePath)
166 {
167     if (outFilePath.size() == 0) {
168         PrintErrorNumberMsg("COMMAND_PARAM_ERROR", COMMAND_PARAM_ERROR,
169                             "get_parent_path realpath error, empty input");
170         return "";
171     }
172 
173     if (outFilePath.size() > PATH_MAX) {
174         PrintErrorNumberMsg("COMMAND_PARAM_ERROR", COMMAND_PARAM_ERROR,
175                             "get_parent_path realpath error, input too long");
176         return "";
177     }
178 
179     char resolvedPath[PATH_MAX + 1] = {0x00};
180     if (realpath(outFilePath.c_str(), resolvedPath) == nullptr) {
181         SIGNATURE_TOOLS_LOGI("Get realpath from %s may failed", resolvedPath);
182         return "";
183     }
184     resolvedPath[PATH_MAX] = '\0';
185     SIGNATURE_TOOLS_LOGI("GetParentPath, resolvedPath:%s", resolvedPath);
186     char *parentPath = dirname(resolvedPath);
187     if (parentPath == nullptr) {
188         SIGNATURE_TOOLS_LOGI("Get parentPath of %s may failed", resolvedPath);
189         return "";
190     }
191 
192     SIGNATURE_TOOLS_LOGI("GetParentPath :%s", parentPath);
193     return std::string(parentPath);
194 }
195 
GetFileName(const std::string & path)196 static std::string GetFileName(const std::string &path)
197 {
198     size_t lastSlash = path.find_last_of('/');
199     if (lastSlash == std::string::npos) {
200         return path;
201     }
202 
203     return path.substr(lastSlash + 1);
204 }
205 
UpdateParamForCheckOutFile(Options * options,const std::initializer_list<std::string> & outFileKeys)206 bool CmdUtil::UpdateParamForCheckOutFile(Options* options, const std::initializer_list<std::string>& outFileKeys)
207 {
208     for (auto& key : outFileKeys) {
209         if (options->count(key)) {
210             std::string outFilePath = options->GetString(key);
211             std::string parentPath = GetParentPath(outFilePath);
212 
213             // Purpose: To prevent the user output path from passing an empty string. eg "   "
214             std::string tmpOutFilePath = outFilePath;
215             tmpOutFilePath.erase(std::remove_if(tmpOutFilePath.begin(),
216                 tmpOutFilePath.end(), ::isspace), tmpOutFilePath.end());
217 
218             if (parentPath.empty() && !tmpOutFilePath.empty()) {
219                 parentPath = "./";
220             }
221             char realFilePath[PATH_MAX + 1] = {0x00};
222             if (parentPath.size() > PATH_MAX) {
223                 PrintErrorNumberMsg("FILE_NOT_FOUND", FILE_NOT_FOUND, "'" + outFilePath + "' File path longer than '"
224                                     + std::to_string(PATH_MAX) + "' characters");
225                 return false;
226             }
227             if (realpath(parentPath.c_str(), realFilePath) == nullptr) {
228                 PrintErrorNumberMsg("FILE_NOT_FOUND", FILE_NOT_FOUND, "The '" + outFilePath +
229                                     "' file does not exist or the path is invalid"
230                                     + ", parameter name '-" + key + "'");
231                 return false;
232             }
233             std::string charStr(realFilePath);
234             std::string fileName = GetFileName(outFilePath);
235             if (fileName.empty()) {
236                 PrintErrorNumberMsg("FILE_NOT_FOUND", FILE_NOT_FOUND, "The file name cannot be empty '"
237                                     + outFilePath + "', parameter name '-" + key + "'");
238                 return false;
239             } else {
240                 SIGNATURE_TOOLS_LOGI("UpdateParamForCheckOutFile GetFileName:%s", fileName.c_str());
241             }
242             (*options)[key] = charStr + "/" + fileName;
243         }
244     }
245     return true;
246 }
247 
UpdateParamForCheckInFile(Options * options,const std::initializer_list<std::string> & inFileKeys)248 bool CmdUtil::UpdateParamForCheckInFile(Options* options, const std::initializer_list<std::string>& inFileKeys)
249 {
250     for (auto& key : inFileKeys) {
251         if (options->count(key)) {
252             std::string inFilePath = options->GetString(key);
253             char realFilePath[PATH_MAX + 1] = {0x00};
254             if (inFilePath.size() > PATH_MAX) {
255                 PrintErrorNumberMsg("FILE_NOT_FOUND", FILE_NOT_FOUND, "'" + inFilePath + "' File path longer than '"
256                                     + std::to_string(PATH_MAX) + "' characters");
257                 return false;
258             }
259             if (realpath(inFilePath.c_str(), realFilePath) == nullptr) {
260                 PrintErrorNumberMsg("FILE_NOT_FOUND", FILE_NOT_FOUND, "The '" + inFilePath +
261                                     "' file does not exist or the path is invalid"
262                                     + ", parameter name '-" + key + "'");
263                 return false;
264             }
265             std::string charStr(realFilePath);
266             (*options)[key] = charStr;
267 
268             if (!FileUtils::IsValidFile(inFilePath)) {
269                 return false;
270             }
271         }
272     }
273 
274     return true;
275 }
276 
UpdateParamForCheckSignAlg(const ParamsSharedPtr & param)277 static bool UpdateParamForCheckSignAlg(const ParamsSharedPtr& param)
278 {
279     // check signAlg
280     Options* options = param->GetOptions();
281     if (options->count(Options::SIGN_ALG)) {
282         std::string signAlg = options->GetString(Options::SIGN_ALG);
283         if (signAlg != SIGN_ALG_SHA256 && signAlg != SIGN_ALG_SHA384) {
284             PrintErrorNumberMsg("NOT_SUPPORT_ERROR", NOT_SUPPORT_ERROR, "'" + signAlg + "' parameter is incorrect");
285             return false;
286         }
287     }
288     return true;
289 }
290 
UpdateParamForOutform(const ParamsSharedPtr & param)291 static bool UpdateParamForOutform(const ParamsSharedPtr& param)
292 {
293     // check generate_app_cert generate_profile_cert
294     Options* options = param->GetOptions();
295     if (param->GetMethod() == GENERATE_APP_CERT ||
296         param->GetMethod() == GENERATE_PROFILE_CERT) {
297         if (options->count(Options::OUT_FORM)) {
298             std::string outForm = options->GetString(Options::OUT_FORM);
299             if (outForm != OUT_FORM_CERT && outForm != OUT_FORM_CERT_CHAIN) {
300                 PrintErrorNumberMsg("COMMAND_ERROR", COMMAND_ERROR, "parameter '" + outForm
301                                     + "' format error, Outform only supprot cert/cerChain");
302                 return false;
303             }
304         } else {
305             (*options)[Options::OUT_FORM] = OUT_FORM_CERT_CHAIN;
306         }
307     }
308     return true;
309 }
310 
UpdateParam(const ParamsSharedPtr & param)311 static bool UpdateParam(const ParamsSharedPtr& param)
312 {
313     if (!UpdateParamForVariantInt(param)) {
314         return false;
315     }
316     if (!UpdateParamForVariantBoolKeyUsage(param)) {
317         return false;
318     }
319     if (!UpdateParamForVariantBoolProfileSigned(param)) {
320         return false;
321     }
322     if (!UpdateParamForVariantBoolSelfSign(param)) {
323         return false;
324     }
325     if (!UpdateParamForCheckSignAlg(param)) {
326         return false;
327     }
328     if (!UpdateParamForOutform(param)) {
329         return false;
330     }
331     return true;
332 }
333 
GetCommandParameterKey(const char strChar,std::string & strChars,std::vector<std::string> & trustList,std::string & keyStandBy)334 int CmdUtil::GetCommandParameterKey(const char strChar, std::string& strChars, std::vector<std::string>& trustList,
335                                     std::string& keyStandBy)
336 {
337     if (strChar == '-') {
338         bool isTrust = std::find(trustList.begin(), trustList.end(), strChars) != trustList.end();
339         if (!isTrust) {
340             PrintErrorNumberMsg("COMMAND_PARAM_ERROR", COMMAND_PARAM_ERROR, "There is no '"
341                                 + strChars + "' command for the trust list");
342             return RET_FAILED;
343         }
344         keyStandBy = strChars.substr(1);
345     } else {
346         PrintErrorNumberMsg("COMMAND_PARAM_ERROR", COMMAND_PARAM_ERROR, "'" + strChars
347                             + "' Parameters error, Param key - value must in pairs");
348         return RET_FAILED;
349     }
350 
351     return RET_OK;
352 }
353 
Convert2Params(char ** args,const size_t size,const ParamsSharedPtr & param)354 bool CmdUtil::Convert2Params(char** args, const size_t size, const ParamsSharedPtr& param)
355 {
356     param->SetMethod(args[1]);
357     std::string keyStandBy = "";
358     bool readKey = true;
359     std::vector<std::string> trustList = ParamsTrustList::GetInstance().GetTrustList(args[1]);
360     if (trustList.empty()) {
361         return false;
362     }
363     std::string strChars;
364     for (size_t i = 2; i < size; i++) {
365         if (readKey) {
366             strChars = args[i];
367             if (GetCommandParameterKey(args[i][0], strChars, trustList, keyStandBy) == RET_OK) {
368                 readKey = false;
369             } else {
370                 return false;
371             }
372         } else {
373             bool success = ValidAndPutParam(param, keyStandBy, args[i]);
374             if (success) {
375                 keyStandBy = "";
376                 readKey = true;
377             } else {
378                 return false;
379             }
380         }
381     }
382     param->GetOptions()->emplace(Options::MODE, LOCAL_SIGN);
383     if (!readKey) {
384         PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR,
385                             "The last value of parameter cannot be omitted");
386         return false;
387     }
388     if (!UpdateParam(param)) {
389         return false;
390     }
391     return true;
392 }
393 
ValidAndPutParam(const ParamsSharedPtr & params,const std::string & key,char * value)394 bool CmdUtil::ValidAndPutParam(const ParamsSharedPtr& params, const std::string& key, char* value)
395 {
396     std::string  str = "Pwd";
397     bool result = true;
398     if (key.empty()) {
399         PrintErrorNumberMsg("COMMAND_PARAM_ERROR", COMMAND_PARAM_ERROR,
400                             "The command-line parameter key cannot be empty");
401         result = false;
402     } else if (strlen(value) == 0) {
403         PrintErrorNumberMsg("COMMAND_PARAM_ERROR", COMMAND_PARAM_ERROR,
404                             "The command-line parameter value cannot be empty");
405         result = false;
406     } else if (params->GetOptions()->count(key)) {
407         PrintErrorNumberMsg("COMMAND_ERROR", COMMAND_ERROR,
408                             "Duplicate command parameter are not allowed '" + key + "'");
409         result = false;
410     } else if (key.length() >= str.length() && key.substr(key.length() - INVALIDCHAR) == str) {
411         params->GetOptions()->emplace(key, value);
412     } else {
413         if (key == Options::KEY_ALIAS || key == Options::ISSUER_KEY_ALIAS) {
414             std::string keyAlias = value;
415             std::transform(keyAlias.begin(), keyAlias.end(), keyAlias.begin(),
416                            [](unsigned char c) { return std::tolower(c); });
417             params->GetOptions()->emplace(key, keyAlias);
418         } else {
419             params->GetOptions()->emplace(key, std::string(value));
420         }
421     }
422     return result;
423 }
424 
JudgeSignAlgType(const std::string & signAlg)425 bool CmdUtil::JudgeSignAlgType(const std::string& signAlg)
426 {
427     if (signAlg != SIGN_ALG_SHA256 && signAlg != SIGN_ALG_SHA384) {
428         PrintErrorNumberMsg("COMMAND_ERROR", COMMAND_ERROR, "not supported '" + signAlg + "' signature algorithm");
429         return  false;
430     }
431     return true;
432 }
433 } // namespace SignatureTools
434 } // namespace OHOS
435