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 24namespace OHOS { 25namespace SignatureTools { 26const std::string ParamsRunTool::VERSION = "1.0.0"; 27 28std::vector<std::string> ParamsRunTool::InformList = { 29 "bin", 30 "elf", 31 "zip" 32}; 33 34static 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 42static 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 53bool 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 88bool 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 102bool 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 148bool 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 171bool 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 184bool 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 215bool 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 251bool 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 295bool 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 312bool 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 329bool 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 353bool 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 381bool 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 422bool 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 449void ParamsRunTool::PrintHelp() 450{ 451 PrintMsg(HELP_TXT); 452} 453 454void ParamsRunTool::Version() 455{ 456 PrintMsg(ParamsRunTool::VERSION); 457} 458 459bool 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