1 /* 2 * Copyright (c) 2021-2022 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 package com.ohos.hapsigntoolcmd; 17 18 import com.ohos.hapsigntool.error.CustomException; 19 import com.ohos.hapsigntool.error.ERROR; 20 import com.ohos.hapsigntool.utils.StringUtils; 21 import com.ohos.hapsigntool.utils.ValidateUtils; 22 23 import java.util.Arrays; 24 import java.util.List; 25 import java.util.Locale; 26 import java.util.regex.Pattern; 27 28 /** 29 * CmdUtil. 30 * 31 * @since 2021/12/28 32 */ 33 public final class CmdUtil { 34 /** 35 * Minimum length of input args. 36 */ 37 private static final int ARGS_MIN_LEN = 2; 38 39 /** 40 * Match size String. 41 */ 42 private static final Pattern INTEGER_PATTERN = Pattern.compile("\\d{1,10}"); 43 CmdUtil()44 private CmdUtil() { 45 } 46 47 /** 48 * Analyze and convert args to Params object. 49 * 50 * @param args Command line args 51 * @return Params 52 */ convert2Params(String[] args)53 public static Params convert2Params(String[] args) { 54 ValidateUtils.throwIfNotMatches(args.length >= ARGS_MIN_LEN, ERROR.COMMAND_ERROR, ""); 55 56 Params params = new Params(); 57 params.setMethod(args[0]); 58 String keyStandBy = null; 59 boolean readKey = true; 60 List<String> trustList = ParamsTrustlist.getTrustList(args[0]); 61 if (trustList.size() == 0) { 62 CustomException.throwException(ERROR.COMMAND_ERROR, "Unsupported cmd"); 63 } 64 for (int i = 1; i < args.length; i++) { 65 String value = args[i]; 66 if (StringUtils.isEmpty(value)) { 67 CustomException.throwException(ERROR.COMMAND_ERROR, "param value could not be empty"); 68 } 69 if (readKey) { 70 // prepare key 71 if (value.startsWith("-")) { 72 value = value.equals("-signcode") ? "-signCode" : value; 73 boolean isTrust = trustList.contains(value); 74 ValidateUtils.throwIfNotMatches(isTrust, 75 ERROR.COMMAND_PARAM_ERROR, "Not support command param"); 76 keyStandBy = value.substring(1); 77 readKey = false; 78 } else { 79 ValidateUtils.throwIfNotMatches(false, 80 ERROR.COMMAND_PARAM_ERROR, "param key value must in pairs"); 81 } 82 } else { 83 // prepare value 84 boolean success = validAndPutParam(params, keyStandBy, value); 85 if (success) { 86 keyStandBy = null; 87 readKey = true; 88 } 89 } 90 } 91 return params; 92 } 93 validAndPutParam(Params params, String key, String value)94 private static boolean validAndPutParam(Params params, String key, String value) { 95 boolean result; 96 if (StringUtils.isEmpty(key)) { 97 result = false; 98 } else if (StringUtils.isEmpty(value)) { 99 CustomException.throwException(ERROR.COMMAND_ERROR, 100 String.format("Command -%s could not be empty", key)); 101 result = false; 102 } else if (params.getOptions().containsKey(key)) { 103 CustomException.throwException(ERROR.COMMAND_ERROR, 104 String.format("Duplicate param '%s'. Stop processing", key)); 105 result = false; 106 } else if (key.toLowerCase(Locale.ROOT).endsWith("pwd")) { 107 params.getOptions().put(key, value.toCharArray()); 108 result = true; 109 } else { 110 params.getOptions().put(key, value); 111 result = true; 112 } 113 return result; 114 } 115 116 /** 117 * Alg type must between RSA and ECC. 118 * 119 * @param alg Incoming string 120 */ judgeAlgType(String alg)121 public static void judgeAlgType(String alg) { 122 if (!"RSA".equalsIgnoreCase(alg) && !"ECC".equalsIgnoreCase(alg)) { 123 CustomException.throwException(ERROR.COMMAND_ERROR, 124 "KeyAlg params is incorrect"); 125 } 126 } 127 128 /** 129 * Check whether the algorithm size is within specified scope. 130 * 131 * @param size algorithm size 132 * @param alg algorithm 133 */ judgeSize(String size, String alg)134 public static void judgeSize(String size, String alg) { 135 String[] array = {"2048", "3072", "4096", "NIST-P-256", "NIST-P-384"}; 136 List<String> arrayList = Arrays.asList(array); 137 if (!arrayList.contains(size)) { 138 CustomException.throwException(ERROR.COMMAND_ERROR, String.format("KeySize '%s' is incorrect", size)); 139 } 140 141 if ("RSA".equalsIgnoreCase(alg)) { 142 if (!"2048".equals(size) && !"3072".equals(size) && !"4096".equals(size)) { 143 CustomException.throwException(ERROR.COMMAND_ERROR, 144 String.format("KeySize of '%s' is incorrect", alg)); 145 } 146 } else { 147 if (!"NIST-P-256".equalsIgnoreCase(size) && !"NIST-P-384".equalsIgnoreCase(size)) { 148 CustomException.throwException(ERROR.COMMAND_ERROR, 149 String.format("KeySize of '%s' is incorrect", alg)); 150 } 151 } 152 } 153 154 /** 155 * Check whether the signature algorithm is within specified scope. 156 * 157 * @param signAlg signature algorithm 158 */ judgeSignAlgType(String signAlg)159 public static void judgeSignAlgType(String signAlg) { 160 List<String> arrayList = Arrays.asList("SHA256withRSA", "SHA384withRSA", "SHA256withECDSA", 161 "SHA384withECDSA"); 162 if (!arrayList.contains(signAlg)) { 163 CustomException.throwException(ERROR.COMMAND_ERROR, 164 "SignAlg params is incorrect"); 165 } 166 } 167 168 /** 169 * Check whether the signature algorithm is within specified scope. 170 * 171 * @param signAlg signature algorithm 172 */ judgeEndSignAlgType(String signAlg)173 public static void judgeEndSignAlgType(String signAlg) { 174 List<String> arrayList = Arrays.asList("SHA256withECDSA", "SHA384withECDSA"); 175 if (!arrayList.contains(signAlg)) { 176 CustomException.throwException(ERROR.NOT_SUPPORT_ERROR, 177 "SignAlg params is incorrect, signature algorithms include SHA256withECDSA,SHA384withECDSA"); 178 } 179 } 180 181 /** 182 * Verify target type. 183 * 184 * @param inputType Types with ',' 185 * @param supportTypes Target types with ',' 186 */ verifyType(String inputType, String supportTypes)187 public static void verifyType(String inputType, String supportTypes) { 188 String[] types = inputType.split(","); 189 List<String> supportList = Arrays.asList(supportTypes.split(",")); 190 for (String type : types) { 191 if (StringUtils.isEmpty(type)) { 192 continue; 193 } 194 if (!supportList.contains(type.trim())) { 195 CustomException.throwException(ERROR.COMMAND_ERROR, 196 "'" + type + "' in params '" + inputType + "' is not support"); 197 } 198 } 199 } 200 201 /** 202 * Convert passed in args to 'integer'. 203 * 204 * @param size String passed in 205 * @return 'integer' String 206 */ convertAlgSize(String size)207 public static String convertAlgSize(String size) { 208 if (size.startsWith("NIST-P-")) { 209 return size.replace("NIST-P-", ""); 210 } else if (INTEGER_PATTERN.matcher(size).matches()) { 211 return size; 212 } else { 213 CustomException.throwException(ERROR.COMMAND_ERROR, 214 String.format("KeySize '%s' is incorrect", size)); 215 return size; 216 } 217 } 218 219 /** 220 * Command parameter constant 221 * 222 */ 223 public static final class Method { 224 /** 225 * Generate app cert method name. 226 */ 227 public static final String GENERATE_APP_CERT = "generate-app-cert"; 228 229 /** 230 * Generate ca method name. 231 */ 232 public static final String GENERATE_CA = "generate-ca"; 233 234 /** 235 * Generate cert method name. 236 */ 237 public static final String GENERATE_CERT = "generate-cert"; 238 239 /** 240 * Generate csr method name. 241 */ 242 public static final String GENERATE_CSR = "generate-csr"; 243 244 /** 245 * Generate key pair method name. 246 */ 247 public static final String GENERATE_KEYPAIR = "generate-keypair"; 248 249 /** 250 * Generate profile cert method name. 251 */ 252 public static final String GENERATE_PROFILE_CERT = "generate-profile-cert"; 253 254 /** 255 * Sign app method name. 256 */ 257 public static final String SIGN_APP = "sign-app"; 258 259 /** 260 * Sign profile method name. 261 */ 262 public static final String SIGN_PROFILE = "sign-profile"; 263 264 /** 265 * Verify app method name. 266 */ 267 public static final String VERIFY_APP = "verify-app"; 268 269 /** 270 * Verify profile method name. 271 */ 272 public static final String VERIFY_PROFILE = "verify-profile"; 273 } 274 } 275