1 /*
2 * Copyright (c) 2024-2024 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
16 #include "params_run_tool.h"
17 #include <unistd.h>
18 #include <memory>
19 #include <filesystem>
20
21 #include "constant.h"
22 #include "help.h"
23
24 namespace OHOS {
25 namespace SignatureTools {
26 const std::string ParamsRunTool::VERSION = "1.0.0";
27
28 std::vector<std::string> ParamsRunTool::InformList = {
29 "bin",
30 "elf",
31 "zip"
32 };
33
34 static std::unordered_map <std::string,
35 std::function<bool(Options* params, SignToolServiceImpl& api)>> DISPATCH_RUN_METHOD {
36 {SIGN_APP, ParamsRunTool::RunSignApp},
37 {SIGN_PROFILE, ParamsRunTool::RunSignProfile},
38 {VERIFY_APP, ParamsRunTool::RunVerifyApp},
39 {VERIFY_PROFILE, ParamsRunTool::RunVerifyProfile}
40 };
41
42 static std::unordered_map <std::string,
43 std::function<bool(Options* params, SignToolServiceImpl& api)>> GENERATOR_RUN_METHOD {
44 {GENERATE_KEYPAIR, ParamsRunTool::RunKeypair},
45 {GENERATE_CSR, ParamsRunTool::RunCsr},
46 {GENERATE_CA, ParamsRunTool::RunCa},
47 {GENERATE_APP_CERT, ParamsRunTool::RunAppCert},
48 {GENERATE_PROFILE_CERT, ParamsRunTool::RunProfileCert},
49 {GENERATE_CERT, ParamsRunTool::RunCert},
50 };
51
52
ProcessCmd(char** args, size_t size)53 bool ParamsRunTool::ProcessCmd(char** args, size_t size)
54 {
55 if (size < CmdUtil::ARGS_MIN_LEN) {
56 PrintHelp();
57 return true;
58 }
59 if (args == nullptr || strcmp(args[1], "") == 0) {
60 PrintHelp();
61 return true;
62 } else if (strcmp(args[1], "-h") == 0 || strcmp(args[1], "-help") == 0) {
63 PrintHelp();
64 return true;
65 } else if (strcmp(args[1], "-v") == 0 || strcmp(args[1], "-version") == 0) {
66 Version();
67 return true;
68 } else {
69 std::shared_ptr<SignToolServiceImpl> serviceApi = std::make_shared<SignToolServiceImpl>();
70 ParamsSharedPtr param = std::make_shared<Params>();
71 if (!CmdUtil::Convert2Params(args, size, param)) {
72 PrintMsg(param->GetMethod() + " failed");
73 return false;
74 }
75 PrintMsg("Start " + param->GetMethod());
76 SIGNATURE_TOOLS_LOGD("%s run start time ", param->GetMethod().c_str());
77 if (!DispatchParams(param, *serviceApi)) {
78 SIGNATURE_TOOLS_LOGD("%s run end time ", param->GetMethod().c_str());
79 PrintMsg(param->GetMethod() + " failed");
80 return false;
81 }
82 PrintMsg(param->GetMethod() + " success");
83 SIGNATURE_TOOLS_LOGD("%s run end time ", param->GetMethod().c_str());
84 }
85 return true;
86 }
87
CallGenerators(const ParamsSharedPtr& params, SignToolServiceImpl& api)88 bool ParamsRunTool::CallGenerators(const ParamsSharedPtr& params, SignToolServiceImpl& api)
89 {
90 bool isSuccess = false;
91 std::string method = params->GetMethod();
92 auto it = GENERATOR_RUN_METHOD.find(method);
93 if (it == GENERATOR_RUN_METHOD.end()) {
94 PrintErrorNumberMsg("COMMAND_ERROR", COMMAND_ERROR, "Unsupported method: " + method);
95 return false;
96 } else {
97 isSuccess = it->second(params->GetOptions(), api);
98 }
99 return isSuccess;
100 }
101
RunSignApp(Options* params, SignToolServiceImpl& api)102 bool ParamsRunTool::RunSignApp(Options* params, SignToolServiceImpl& api)
103 {
104 if (!params->Required({Options::MODE, Options::IN_FILE, Options::OUT_FILE, Options::SIGN_ALG})) {
105 return false;
106 }
107
108 if (!CmdUtil::UpdateParamForCheckInFile(params, {Options::IN_FILE, Options::APP_CERT_FILE,
109 Options::PROFILE_FILE, Options::KEY_STORE_FILE,
110 ParamConstants::PARAM_REMOTE_SIGNERPLUGIN})) {
111 return false;
112 }
113
114 if (!CmdUtil::UpdateParamForCheckOutFile(params, {Options::OUT_FILE})) {
115 return false;
116 }
117
118 std::string mode = params->GetString(Options::MODE);
119 if (!StringUtils::CaseCompare(mode, LOCAL_SIGN) &&
120 !StringUtils::CaseCompare(mode, REMOTE_SIGN)) {
121 PrintErrorNumberMsg("COMMAND_ERROR", COMMAND_ERROR, "not support command param '" + mode + "'");
122 return false;
123 }
124 if (StringUtils::CaseCompare(mode, LOCAL_SIGN)) {
125 if (!params->Required({Options::KEY_STORE_FILE, Options::KEY_ALIAS, Options::APP_CERT_FILE})) {
126 return false;
127 }
128 if (!FileUtils::ValidFileType(params->GetString(Options::KEY_STORE_FILE), {"p12", "jks"})) {
129 return false;
130 }
131 }
132 if (!CheckProfile(*params)) {
133 return false;
134 }
135 std::string inForm = params->GetString(Options::INFORM, ZIP);
136 if (!StringUtils::IsEmpty(inForm) && !StringUtils::ContainsCase(InformList, inForm)) {
137 PrintErrorNumberMsg("NOT_SUPPORT_ERROR", NOT_SUPPORT_ERROR, "parameter '" + inForm
138 + "' format error, Inform only support zip/elf/bin");
139 return false;
140 }
141 std::string signAlg = params->GetString(Options::SIGN_ALG);
142 if (!CmdUtil::JudgeSignAlgType(signAlg)) {
143 return false;
144 }
145 return api.SignHap(params);
146 }
147
CheckProfile(Options& params)148 bool ParamsRunTool::CheckProfile(Options& params)
149 {
150 std::string inForm = params.GetString(Options::INFORM);
151 std::string profileFile = params.GetString(Options::PROFILE_FILE);
152
153 std::string profileSigned = params.GetString(Options::PROFILE_SIGNED);
154 if (StringUtils::CaseCompare(inForm, ELF) && FileUtils::IsEmpty(profileFile)) {
155 return true;
156 }
157
158 if (profileSigned == "1") {
159 if (!FileUtils::ValidFileType(profileFile, {"p7b"})) {
160 return false;
161 }
162 } else {
163 if (!FileUtils::ValidFileType(profileFile, {"json"})) {
164 return false;
165 }
166 }
167
168 return true;
169 }
170
DispatchParams(const ParamsSharedPtr& params, SignToolServiceImpl& api)171 bool ParamsRunTool::DispatchParams(const ParamsSharedPtr& params, SignToolServiceImpl& api)
172 {
173 bool isSuccess = false;
174 std::string method = params->GetMethod();
175 auto it = DISPATCH_RUN_METHOD.find(method);
176 if (it == DISPATCH_RUN_METHOD.end()) {
177 isSuccess = ParamsRunTool::CallGenerators(params, api);
178 } else {
179 isSuccess = it->second(params->GetOptions(), api);
180 }
181 return isSuccess;
182 }
183
RunCa(Options* params, SignToolServiceImpl& api)184 bool ParamsRunTool::RunCa(Options* params, SignToolServiceImpl& api)
185 {
186 if (!params->Required({Options::KEY_ALIAS, Options::KEY_ALG,
187 Options::KEY_SIZE, Options::SUBJECT, Options::SIGN_ALG, Options::KEY_STORE_FILE})) {
188 return false;
189 }
190
191 if (!CmdUtil::UpdateParamForCheckOutFile(params, {Options::OUT_FILE, Options::KEY_STORE_FILE,
192 Options::ISSUER_KEY_STORE_FILE})) {
193 return false;
194 }
195
196 std::string keyAlg = params->GetString(Options::KEY_ALG);
197 if (!CmdUtil::JudgeAlgType(keyAlg)) {
198 return false;
199 }
200 int keySize = params->GetInt(Options::KEY_SIZE);
201 if (!CmdUtil::JudgeSize(keySize)) {
202 return false;
203 }
204 std::string signAlg = params->GetString(Options::SIGN_ALG);
205 if (!CmdUtil::JudgeSignAlgType(signAlg)) {
206 return false;
207 }
208 if (!FileUtils::ValidFileType(params->GetString(Options::KEY_STORE_FILE), {"p12", "jks"})) {
209 return false;
210 }
211
212 return api.GenerateCA(params);
213 }
214
RunCert(Options* params, SignToolServiceImpl& api)215 bool ParamsRunTool::RunCert(Options* params, SignToolServiceImpl& api)
216 {
217 if (!params->Required({Options::KEY_ALIAS, Options::ISSUER,
218 Options::ISSUER_KEY_ALIAS, Options::SUBJECT, Options::KEY_USAGE,
219 Options::SIGN_ALG, Options::KEY_STORE_FILE})) {
220 return false;
221 }
222
223 if (!CmdUtil::UpdateParamForCheckInFile(params, {Options::KEY_STORE_FILE, Options::ISSUER_KEY_STORE_FILE})) {
224 return false;
225 }
226
227 if (!CmdUtil::UpdateParamForCheckOutFile(params, {Options::OUT_FILE})) {
228 return false;
229 }
230
231 std::string keyusage = params->GetString(Options::KEY_USAGE);
232 if (!CmdUtil::VerifyTypes(keyusage)) {
233 return false;
234 }
235 std::string extkeyusage = params->GetString(Options::EXT_KEY_USAGE);
236 if (!extkeyusage.empty()) {
237 if (!CmdUtil::VerifyType(extkeyusage)) {
238 return false;
239 }
240 }
241 std::string signAlg = params->GetString(Options::SIGN_ALG);
242 if (!CmdUtil::JudgeSignAlgType(signAlg)) {
243 return false;
244 }
245 if (!FileUtils::ValidFileType(params->GetString(Options::KEY_STORE_FILE), {"p12", "jks"})) {
246 return false;
247 }
248 return api.GenerateCert(params);
249 }
250
CheckEndCertArguments(Options& params)251 bool ParamsRunTool::CheckEndCertArguments(Options& params)
252 {
253 if (!params.Required({Options::KEY_ALIAS, Options::ISSUER, Options::ISSUER_KEY_ALIAS,
254 Options::SUBJECT, Options::SIGN_ALG, Options::KEY_STORE_FILE})) {
255 return false;
256 }
257 std::string signAlg = params.GetString(Options::SIGN_ALG);
258 if (!CmdUtil::JudgeSignAlgType(signAlg)) {
259 return false;
260 }
261 std::string outForm = params.GetString(Options::OUT_FORM);
262 if (!outForm.empty()) {
263 if (!CmdUtil::VerifyType(outForm, Options::OUT_FORM_SCOPE)) {
264 return false;
265 }
266 }
267 if (!outForm.empty() && "certChain" == outForm) {
268 if (!params.Required({Options::SUB_CA_CERT_FILE, Options::CA_CERT_FILE})) {
269 return false;
270 }
271 if (!FileUtils::ValidFileType(params.GetString(Options::SUB_CA_CERT_FILE), {"cer"}) ||
272 !FileUtils::ValidFileType(params.GetString(Options::CA_CERT_FILE), {"cer"})) {
273 return false;
274 }
275 }
276 std::string keyStoreFile = params.GetString(Options::KEY_STORE_FILE);
277 if (!FileUtils::ValidFileType(keyStoreFile, {"p12", "jks"})) {
278 return false;
279 }
280 if (params.find(Options::ISSUER_KEY_STORE_FILE) != params.end()) {
281 std::string issuerKeyStoreFile = params.GetString(Options::ISSUER_KEY_STORE_FILE);
282 if (!FileUtils::ValidFileType(issuerKeyStoreFile, {"p12", "jks"})) {
283 return false;
284 }
285 }
286 std::string outFile = params.GetString(Options::OUT_FILE);
287 if (!outFile.empty()) {
288 if (!FileUtils::ValidFileType(outFile, {"cer", "pem"})) {
289 return false;
290 }
291 }
292 return true;
293 }
294
RunAppCert(Options* params, SignToolServiceImpl& api)295 bool ParamsRunTool::RunAppCert(Options* params, SignToolServiceImpl& api)
296 {
297 if (!CmdUtil::UpdateParamForCheckInFile(params, {Options::KEY_STORE_FILE, Options::ISSUER_KEY_STORE_FILE,
298 Options::CA_CERT_FILE, Options::SUB_CA_CERT_FILE})) {
299 return false;
300 }
301
302 if (!CmdUtil::UpdateParamForCheckOutFile(params, {Options::OUT_FILE})) {
303 return false;
304 }
305
306 if (!ParamsRunTool::CheckEndCertArguments(*params)) {
307 return false;
308 }
309 return api.GenerateAppCert(params);
310 }
311
RunProfileCert(Options* params, SignToolServiceImpl& api)312 bool ParamsRunTool::RunProfileCert(Options* params, SignToolServiceImpl& api)
313 {
314 if (!CmdUtil::UpdateParamForCheckInFile(params, {Options::KEY_STORE_FILE, Options::ISSUER_KEY_STORE_FILE,
315 Options::CA_CERT_FILE, Options::SUB_CA_CERT_FILE})) {
316 return false;
317 }
318
319 if (!CmdUtil::UpdateParamForCheckOutFile(params, {Options::OUT_FILE})) {
320 return false;
321 }
322
323 if (!ParamsRunTool::CheckEndCertArguments(*params)) {
324 return false;
325 }
326 return api.GenerateProfileCert(params);
327 }
328
RunKeypair(Options* params, SignToolServiceImpl& api)329 bool ParamsRunTool::RunKeypair(Options* params, SignToolServiceImpl& api)
330 {
331 if (!params->Required({Options::KEY_ALIAS, Options::KEY_ALG, Options::KEY_SIZE, Options::KEY_STORE_FILE})) {
332 return false;
333 }
334
335 if (!CmdUtil::UpdateParamForCheckOutFile(params, {Options::KEY_STORE_FILE})) {
336 return false;
337 }
338
339 std::string keyAlgorithm = params->GetString(Options::KEY_ALG);
340 if (!CmdUtil::JudgeAlgType(keyAlgorithm)) {
341 return false;
342 }
343 int keyAlgorithmSize = params->GetInt(Options::KEY_SIZE);
344 if (!CmdUtil::JudgeSize(keyAlgorithmSize)) {
345 return false;
346 }
347 if (!FileUtils::ValidFileType(params->GetString(Options::KEY_STORE_FILE), {"p12", "jks"})) {
348 return false;
349 }
350 return api.GenerateKeyStore(params);
351 }
352
RunCsr(Options* params, SignToolServiceImpl& api)353 bool ParamsRunTool::RunCsr(Options* params, SignToolServiceImpl& api)
354 {
355 if (!params->Required({Options::KEY_ALIAS, Options::SUBJECT, Options::SIGN_ALG, Options::KEY_STORE_FILE})) {
356 return false;
357 }
358 if (!CmdUtil::UpdateParamForCheckInFile(params, {Options::KEY_STORE_FILE})) {
359 return false;
360 }
361
362 if (!CmdUtil::UpdateParamForCheckOutFile(params, {Options::OUT_FILE})) {
363 return false;
364 }
365
366 std::string signAlg = params->GetString(Options::SIGN_ALG);
367 if (!CmdUtil::JudgeSignAlgType(signAlg)) {
368 return false;
369 }
370 if (!FileUtils::ValidFileType(params->GetString(Options::KEY_STORE_FILE), {"p12", "jks"})) {
371 return false;
372 }
373 if (params->count(Options::OUT_FILE)) {
374 if (!FileUtils::ValidFileType(params->GetString(Options::OUT_FILE), {"csr"})) {
375 return false;
376 }
377 }
378 return api.GenerateCsr(params);
379 }
380
RunSignProfile(Options* params, SignToolServiceImpl& api)381 bool ParamsRunTool::RunSignProfile(Options* params, SignToolServiceImpl& api)
382 {
383 if (!params->Required({params->MODE, params->SIGN_ALG, params->OUT_FILE, params->IN_FILE})) {
384 return false;
385 }
386
387 if (!CmdUtil::UpdateParamForCheckInFile(params, {Options::KEY_STORE_FILE, Options::PROFILE_CERT_FILE,
388 Options::IN_FILE})) {
389 return false;
390 }
391
392 if (!CmdUtil::UpdateParamForCheckOutFile(params, {Options::OUT_FILE})) {
393 return false;
394 }
395
396 std::string mode = params->GetString(Options::MODE);
397 if (!StringUtils::CaseCompare(mode, LOCAL_SIGN) &&
398 !StringUtils::CaseCompare(mode, REMOTE_SIGN)) {
399 PrintErrorNumberMsg("COMMAND_ERROR", COMMAND_ERROR, "not support command param '" + mode + "'");
400 return false;
401 }
402 if (StringUtils::CaseCompare(mode, LOCAL_SIGN)) {
403 if (!params->Required({params->KEY_STORE_FILE, params->KEY_ALIAS, params->PROFILE_CERT_FILE})) {
404 return false;
405 }
406
407 if (!FileUtils::ValidFileType(params->GetString(Options::KEY_STORE_FILE), {"p12", "jks"})) {
408 return false;
409 }
410 }
411 std::string signAlg = params->GetString(Options::SIGN_ALG);
412 if (!CmdUtil::JudgeSignAlgType(signAlg)) {
413 return false;
414 }
415 std::string outFile = params->GetString(Options::OUT_FILE);
416 if (FileUtils::ValidFileType(outFile, {"p7b"}) == false) {
417 return false;
418 }
419 return api.SignProfile(params);
420 }
421
RunVerifyProfile(Options* params, SignToolServiceImpl& api)422 bool ParamsRunTool::RunVerifyProfile(Options* params, SignToolServiceImpl& api)
423 {
424 if (!params->Required({Options::IN_FILE})) {
425 return false;
426 }
427
428 if (!CmdUtil::UpdateParamForCheckInFile(params, {Options::IN_FILE})) {
429 return false;
430 }
431
432 if (!CmdUtil::UpdateParamForCheckOutFile(params, {Options::OUT_FILE})) {
433 return false;
434 }
435
436 if (!FileUtils::ValidFileType(params->GetString(Options::IN_FILE), {"p7b"})) {
437 return false;
438 }
439
440 std::string outFile = params->GetString(Options::OUT_FILE);
441 if (!outFile.empty()) {
442 if (!FileUtils::ValidFileType(outFile, {"json"})) {
443 return false;
444 }
445 }
446 return api.VerifyProfile(params);
447 }
448
PrintHelp()449 void ParamsRunTool::PrintHelp()
450 {
451 PrintMsg(HELP_TXT);
452 }
453
Version()454 void ParamsRunTool::Version()
455 {
456 PrintMsg(ParamsRunTool::VERSION);
457 }
458
RunVerifyApp(Options* params, SignToolServiceImpl& api)459 bool ParamsRunTool::RunVerifyApp(Options* params, SignToolServiceImpl& api)
460 {
461 if (!params->Required({Options::IN_FILE, Options::OUT_CERT_CHAIN, Options::OUT_PROFILE})) {
462 return false;
463 }
464
465 if (!CmdUtil::UpdateParamForCheckInFile(params, {Options::IN_FILE})) {
466 return false;
467 }
468
469 if (!CmdUtil::UpdateParamForCheckOutFile(params, {Options::OUT_CERT_CHAIN, Options::OUT_PROFILE})) {
470 return false;
471 }
472
473 std::string inForm = params->GetString(Options::INFORM, ZIP);
474 if (!StringUtils::ContainsCase(InformList, inForm)) {
475 PrintErrorNumberMsg("NOT_SUPPORT_ERROR", NOT_SUPPORT_ERROR, "parameter '" + inForm
476 + "' format error, Inform only support zip/elf/bin");
477 return false;
478 }
479 if (!FileUtils::ValidFileType(params->GetString(Options::OUT_CERT_CHAIN), {"cer"})) {
480 return false;
481 }
482 if (!FileUtils::ValidFileType(params->GetString(Options::OUT_PROFILE), {"p7b"})) {
483 return false;
484 }
485 return api.VerifyHapSigner(params);
486 }
487 } // namespace SignatureTools
488 } // namespace OHOS