1/* 2 * Copyright (c) 2023 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 <stdint.h> 17 18#include "hks_api.h" 19#include "hks_param.h" 20 21#include "asset_log.h" 22#include "asset_type.h" 23#include "huks_wrapper.h" 24 25static enum HksAuthStorageLevel AccessibilityToHksAuthStorageLevel(enum Accessibility accessibility) 26{ 27 switch (accessibility) { 28 case DEVICE_POWERED_ON: 29 return HKS_AUTH_STORAGE_LEVEL_DE; 30 case DEVICE_FIRST_UNLOCKED: 31 return HKS_AUTH_STORAGE_LEVEL_CE; 32 default: 33 return HKS_AUTH_STORAGE_LEVEL_ECE; 34 } 35} 36 37static int32_t HuksErrorTransfer(int32_t ret) 38{ 39 switch (ret) { 40 case HKS_SUCCESS: 41 return ASSET_SUCCESS; 42 case HKS_ERROR_NO_PERMISSION: 43 case HKS_ERROR_DEVICE_PASSWORD_UNSET: 44 return ASSET_STATUS_MISMATCH; 45 case HKS_ERROR_NOT_EXIST: 46 return ASSET_NOT_FOUND; 47 case HKS_ERROR_KEY_AUTH_FAILED: 48 case HKS_ERROR_KEY_AUTH_VERIFY_FAILED: 49 return ASSET_ACCESS_DENIED; 50 case HKS_ERROR_CRYPTO_ENGINE_ERROR: 51 return ASSET_DATA_CORRUPTED; 52 default: 53 return ASSET_CRYPTO_ERROR; 54 } 55} 56 57static int32_t AddSpecificUserIdParams(struct HksParamSet *paramSet, int32_t userId) 58{ 59 struct HksParam specificUserIdParams[] = { 60 { .tag = HKS_TAG_SPECIFIC_USER_ID, .int32Param = userId }, 61 }; 62 return HksAddParams(paramSet, specificUserIdParams, ARRAY_SIZE(specificUserIdParams)); 63} 64 65static int32_t BuildParamSet(struct HksParamSet **paramSet, const struct HksParam *params, uint32_t paramCount, 66 int32_t userId) 67{ 68 int32_t ret = HksInitParamSet(paramSet); 69 if (ret != HKS_SUCCESS) { 70 LOGE("[FATAL]HUKS init param set failed. error=%{public}d", ret); 71 return ret; 72 } 73 74 if (paramCount != 0) { 75 ret = HksAddParams(*paramSet, params, paramCount); 76 if (ret != HKS_SUCCESS) { 77 LOGE("[FATAL]HUKS add params failed. error=%{public}d", ret); 78 HksFreeParamSet(paramSet); 79 return ret; 80 } 81 82 if (userId > ASSET_ROOT_USER_UPPERBOUND) { 83 ret = AddSpecificUserIdParams(*paramSet, userId); 84 if (ret != HKS_SUCCESS) { 85 LOGE("[FATAL]HUKS add specific userId failed. error=%{public}d", ret); 86 HksFreeParamSet(paramSet); 87 return ret; 88 } 89 } 90 } 91 92 ret = HksBuildParamSet(paramSet); 93 if (ret != HKS_SUCCESS) { 94 LOGE("[FATAL]HUKS build param set failed. error=%{public}d", ret); 95 HksFreeParamSet(paramSet); 96 } 97 return ret; 98} 99 100static int32_t AddCommonGenParams(struct HksParamSet *paramSet, const struct KeyId *keyId) 101{ 102 struct HksParam commonParams[] = { 103 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, 104 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT }, 105 { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 }, 106 { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, 107 { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, 108 { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = AccessibilityToHksAuthStorageLevel(keyId->accessibility) }, 109 { .tag = HKS_TAG_IS_ALLOWED_DATA_WRAP, .boolParam = true }, 110 }; 111 return HksAddParams(paramSet, commonParams, ARRAY_SIZE(commonParams)); 112} 113 114static int32_t AddAuthGenParams(struct HksParamSet *paramSet) 115{ 116 struct HksParam authParams[] = { 117 { .tag = HKS_TAG_KEY_AUTH_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_DECRYPT }, 118 { .tag = HKS_TAG_KEY_AUTH_ACCESS_TYPE, .uint32Param = HKS_AUTH_ACCESS_ALWAYS_VALID }, 119 { .tag = HKS_TAG_BATCH_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_DECRYPT }, 120 { .tag = HKS_TAG_CHALLENGE_TYPE, .uint32Param = HKS_CHALLENGE_TYPE_NORMAL }, 121 { .tag = HKS_TAG_USER_AUTH_TYPE, .uint32Param = 122 HKS_USER_AUTH_TYPE_FINGERPRINT | HKS_USER_AUTH_TYPE_FACE | HKS_USER_AUTH_TYPE_PIN } 123 }; 124 return HksAddParams(paramSet, authParams, ARRAY_SIZE(authParams)); 125} 126 127int32_t GenerateKey(const struct KeyId *keyId, bool needAuth, bool requirePasswordSet) 128{ 129 struct HksParamSet *paramSet = NULL; 130 int32_t ret = HKS_SUCCESS; 131 do { 132 ret = HksInitParamSet(¶mSet); 133 if (ret != HKS_SUCCESS) { 134 LOGE("[FATAL]HUKS init param set failed. error=%{public}d", ret); 135 break; 136 } 137 138 ret = AddCommonGenParams(paramSet, keyId); 139 if (ret != HKS_SUCCESS) { 140 LOGE("[FATAL]HUKS add common params failed. error=%{public}d", ret); 141 break; 142 } 143 144 if (keyId->userId > ASSET_ROOT_USER_UPPERBOUND) { 145 ret = AddSpecificUserIdParams(paramSet, keyId->userId); 146 if (ret != HKS_SUCCESS) { 147 LOGE("[FATAL]HUKS add specific userId failed. error=%{public}d", ret); 148 break; 149 } 150 } 151 152 if (needAuth) { 153 ret = AddAuthGenParams(paramSet); 154 if (ret != HKS_SUCCESS) { 155 LOGE("[FATAL]HUKS add auth params failed. error=%{public}d", ret); 156 break; 157 } 158 } 159 160 if (requirePasswordSet) { 161 struct HksParam tempParam = { .tag = HKS_TAG_IS_DEVICE_PASSWORD_SET, .boolParam = true }; 162 ret = HksAddParams(paramSet, &tempParam, 1); // 1: add one param to paramSet 163 if (ret != HKS_SUCCESS) { 164 LOGE("[FATAL]HUKS add requirePasswordSet param failed. error=%{public}d", ret); 165 break; 166 } 167 } 168 169 ret = HksBuildParamSet(¶mSet); 170 if (ret != HKS_SUCCESS) { 171 LOGE("[FATAL]HUKS build param set failed. error=%{public}d", ret); 172 break; 173 } 174 175 ret = HksGenerateKey(&keyId->alias, paramSet, NULL); 176 if (ret != HKS_SUCCESS) { 177 LOGE("[FATAL]HUKS generate key failed. error=%{public}d", ret); 178 } 179 } while (0); 180 181 HksFreeParamSet(¶mSet); 182 return HuksErrorTransfer(ret); 183} 184 185int32_t DeleteKey(const struct KeyId *keyId) 186{ 187 struct HksParam params[] = { 188 { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = AccessibilityToHksAuthStorageLevel(keyId->accessibility) }, 189 }; 190 struct HksParamSet *paramSet = NULL; 191 int32_t ret = BuildParamSet(¶mSet, params, ARRAY_SIZE(params), keyId->userId); 192 if (ret != HKS_SUCCESS) { 193 return HuksErrorTransfer(ret); 194 } 195 196 ret = HksDeleteKey(&keyId->alias, paramSet); 197 HksFreeParamSet(¶mSet); 198 return HuksErrorTransfer(ret); 199} 200 201int32_t IsKeyExist(const struct KeyId *keyId) 202{ 203 struct HksParam params[] = { 204 { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = AccessibilityToHksAuthStorageLevel(keyId->accessibility) }, 205 }; 206 struct HksParamSet *paramSet = NULL; 207 int32_t ret = BuildParamSet(¶mSet, params, ARRAY_SIZE(params), keyId->userId); 208 if (ret != HKS_SUCCESS) { 209 return HuksErrorTransfer(ret); 210 } 211 212 ret = HksKeyExist(&keyId->alias, paramSet); 213 HksFreeParamSet(¶mSet); 214 return HuksErrorTransfer(ret); 215} 216 217int32_t EncryptData(const struct KeyId *keyId, const struct HksBlob *aad, const struct HksBlob *inData, 218 struct HksBlob *outData) 219{ 220 struct HksParam encryptParams[] = { 221 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, 222 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT }, 223 { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 }, 224 { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, 225 { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, 226 { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = *aad }, 227 { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = AccessibilityToHksAuthStorageLevel(keyId->accessibility) }, 228 }; 229 struct HksParamSet *encryptParamSet = NULL; 230 int32_t ret = BuildParamSet(&encryptParamSet, encryptParams, ARRAY_SIZE(encryptParams), keyId->userId); 231 if (ret != HKS_SUCCESS) { 232 return HuksErrorTransfer(ret); 233 } 234 235 uint8_t handle[sizeof(uint64_t)] = { 0 }; 236 struct HksBlob handleBlob = { sizeof(uint64_t), handle }; 237 ret = HksInit(&keyId->alias, encryptParamSet, &handleBlob, NULL); 238 if (ret != HKS_SUCCESS) { 239 LOGE("[FATAL]HUKS encrypt init failed. error=%{public}d", ret); 240 HksFreeParamSet(&encryptParamSet); 241 return HuksErrorTransfer(ret); 242 } 243 244 ret = HksFinish(&handleBlob, encryptParamSet, inData, outData); 245 HksFreeParamSet(&encryptParamSet); 246 if (ret != HKS_SUCCESS) { 247 LOGE("[FATAL]HUKS encrypt finish failed. error=%{public}d", ret); 248 } 249 return HuksErrorTransfer(ret); 250} 251 252int32_t DecryptData(const struct KeyId *keyId, const struct HksBlob *aad, const struct HksBlob *inData, 253 struct HksBlob *outData) 254{ 255 struct HksBlob cipher = { inData->size - NONCE_SIZE - TAG_SIZE, inData->data }; 256 struct HksBlob tag = { TAG_SIZE, inData->data + (inData->size - NONCE_SIZE - TAG_SIZE) }; 257 struct HksBlob nonce = { NONCE_SIZE, inData->data + (inData->size - NONCE_SIZE) }; 258 259 struct HksParamSet *decryptParamSet = NULL; 260 struct HksParam decryptParams[] = { 261 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, 262 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_DECRYPT }, 263 { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 }, 264 { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, 265 { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, 266 { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = *aad }, 267 { .tag = HKS_TAG_NONCE, .blob = nonce }, 268 { .tag = HKS_TAG_AE_TAG, .blob = tag }, 269 { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = AccessibilityToHksAuthStorageLevel(keyId->accessibility) }, 270 }; 271 272 int32_t ret = BuildParamSet(&decryptParamSet, decryptParams, ARRAY_SIZE(decryptParams), keyId->userId); 273 if (ret != HKS_SUCCESS) { 274 return HuksErrorTransfer(ret); 275 } 276 277 uint8_t handle[sizeof(uint64_t)] = { 0 }; 278 struct HksBlob handleBlob = { sizeof(uint64_t), handle }; 279 ret = HksInit(&keyId->alias, decryptParamSet, &handleBlob, NULL); 280 if (ret != HKS_SUCCESS) { 281 LOGE("[FATAL]HUKS decrypt init failed. error=%{public}d", ret); 282 HksFreeParamSet(&decryptParamSet); 283 return HuksErrorTransfer(ret); 284 } 285 286 ret = HksFinish(&handleBlob, decryptParamSet, &cipher, outData); 287 HksFreeParamSet(&decryptParamSet); 288 if (ret != HKS_SUCCESS) { 289 LOGE("[FATAL]HUKS decrypt finish failed. error=%{public}d", ret); 290 } 291 return HuksErrorTransfer(ret); 292} 293 294int32_t InitKey(const struct KeyId *keyId, uint32_t validTime, struct HksBlob *challenge, struct HksBlob *handle) 295{ 296 struct HksParam initParams[] = { 297 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES}, 298 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_DECRYPT }, 299 { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 }, 300 { .tag = HKS_TAG_IS_BATCH_OPERATION, .boolParam = true }, 301 { .tag = HKS_TAG_BATCH_OPERATION_TIMEOUT, .uint32Param = validTime }, 302 { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = AccessibilityToHksAuthStorageLevel(keyId->accessibility) }, 303 }; 304 struct HksParamSet *paramSet = NULL; 305 int32_t ret = BuildParamSet(¶mSet, initParams, ARRAY_SIZE(initParams), keyId->userId); 306 if (ret != HKS_SUCCESS) { 307 return HuksErrorTransfer(ret); 308 } 309 310 ret = HksInit(&keyId->alias, paramSet, handle, challenge); 311 HksFreeParamSet(¶mSet); 312 if (ret != HKS_SUCCESS) { 313 LOGE("[FATAL]HUKS batch decrypt init failed. error=%{public}d", ret); 314 } 315 return HuksErrorTransfer(ret); 316} 317 318int32_t ExecCrypt(const struct HksBlob *handle, const struct HksBlob *aad, const struct HksBlob *authToken, 319 const struct HksBlob *inData, struct HksBlob *outData) 320{ 321 struct HksBlob tag = { TAG_SIZE, inData->data + (inData->size - NONCE_SIZE - TAG_SIZE) }; 322 struct HksBlob nonce = { NONCE_SIZE, inData->data + (inData->size - NONCE_SIZE) }; 323 324 struct HksParam updateParams[] = { 325 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, 326 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_DECRYPT }, 327 { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 }, 328 { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, 329 { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, 330 { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = { .size = aad->size, .data = aad->data } }, 331 { .tag = HKS_TAG_NONCE, .blob = nonce }, 332 { .tag = HKS_TAG_AE_TAG, .blob = tag }, 333 { .tag = HKS_TAG_AUTH_TOKEN, .blob = *authToken }, 334 }; 335 336 struct HksParamSet *paramSet = NULL; 337 int32_t ret = BuildParamSet(¶mSet, updateParams, ARRAY_SIZE(updateParams), 0); 338 if (ret != HKS_SUCCESS) { 339 return HuksErrorTransfer(ret); 340 } 341 342 struct HksBlob cipher = { inData->size - NONCE_SIZE - TAG_SIZE, inData->data }; 343 ret = HksUpdate(handle, paramSet, &cipher, outData); 344 HksFreeParamSet(¶mSet); 345 if (ret != HKS_SUCCESS) { 346 LOGE("[FATAL]HUKS batch decrypt update failed. error=%{public}d", ret); 347 } 348 return HuksErrorTransfer(ret); 349} 350 351int32_t Drop(const struct HksBlob *handle) 352{ 353 struct HksBlob inData = { 0, NULL }; 354 struct HksBlob outData = { 0, NULL }; 355 356 struct HksParamSet *paramSet = NULL; 357 int32_t ret = BuildParamSet(¶mSet, NULL, 0, 0); 358 if (ret != HKS_SUCCESS) { 359 return HuksErrorTransfer(ret); 360 } 361 362 ret = HksFinish(handle, paramSet, &inData, &outData); 363 HksFreeParamSet(¶mSet); 364 if (ret != HKS_SUCCESS) { 365 LOGE("[FATAL]HUKS batch decrypt finish failed. error=%{public}d", ret); 366 } 367 return HuksErrorTransfer(ret); 368} 369 370int32_t RenameKeyAlias(const struct KeyId *keyId, const struct HksBlob *newKeyAlias) 371{ 372 struct HksParam params[] = { 373 { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = AccessibilityToHksAuthStorageLevel(keyId->accessibility) }, 374 { .tag = HKS_TAG_IS_COPY_NEW_KEY, .boolParam = true }, 375 }; 376 struct HksParamSet *paramSet = NULL; 377 int32_t ret = BuildParamSet(¶mSet, params, ARRAY_SIZE(params), keyId->userId); 378 if (ret != HKS_SUCCESS) { 379 return HuksErrorTransfer(ret); 380 } 381 382 ret = HksRenameKeyAlias(&keyId->alias, paramSet, newKeyAlias); 383 HksFreeParamSet(¶mSet); 384 if (ret != HKS_SUCCESS) { 385 LOGE("[FATAL]HUKS rename key alias failed. error=%{public}d", ret); 386 } 387 return HuksErrorTransfer(ret); 388}