1 /*
2 * Copyright (c) 2021-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 "huks_master.h"
17
18 #include <dlfcn.h>
19 #include <unistd.h>
20 #include <openssl/err.h>
21 #include <openssl/rand.h>
22 #include <openssl/sha.h>
23
24 #include "key_crypto_utils.h"
25 #include "storage_service_log.h"
26 #include "storage_service_errno.h"
27 #include "utils/storage_radar.h"
28
29 using namespace OHOS::StorageService;
30 namespace OHOS {
31 namespace StorageDaemon {
32 constexpr uint8_t MAX_RETRY_TIME = 3;
33 constexpr uint16_t RETRY_INTERVAL_MS = 50 * 1000;
34 constexpr uint32_t CRYPTO_KEY_ALIAS_SIZE = 16;
35 constexpr uint32_t CRYPTO_AES_AAD_LEN = 16;
36 constexpr uint32_t CRYPTO_AES_NONCE_LEN = 64;
37 constexpr uint32_t CRYPTO_HKS_NONCE_LEN = 12;
38 constexpr uint32_t CRYPTO_KEY_SHIELD_MAX_SIZE = 2048;
39 constexpr uint32_t CRYPTO_AES_256_KEY_ENCRYPTED_SIZE = 80;
40 constexpr uint32_t CRYPTO_TOKEN_SIZE = TOKEN_CHALLENGE_LEN; // 32
HuksMaster()41 HuksMaster::HuksMaster()
42 {
43 LOGI("enter");
44 HdiCreate();
45 HdiModuleInit();
46 LOGI("finish");
47 }
48
~HuksMaster()49 HuksMaster::~HuksMaster()
50 {
51 LOGI("enter");
52 HdiModuleDestroy();
53 HdiDestroy();
54 LOGI("finish");
55 }
56
HdiCreate()57 bool HuksMaster::HdiCreate()
58 {
59 LOGI("enter");
60 if (hdiHandle_ != nullptr || halDevice_ != nullptr) {
61 return true;
62 }
63
64 hdiHandle_ = dlopen("libhuks_engine_core_standard.z.so", RTLD_LAZY);
65 if (hdiHandle_ == nullptr) {
66 LOGE("dlopen failed %{public}s", dlerror());
67 return false;
68 }
69
70 auto createHdi = reinterpret_cast<HkmHalCreateHandle>(dlsym(hdiHandle_, "HuksCreateHdiDevicePtr"));
71 if (createHdi == nullptr) {
72 LOGE("dlsym failed %{public}s", dlerror());
73 dlclose(hdiHandle_);
74 hdiHandle_ = nullptr;
75 return false;
76 }
77
78 halDevice_ = (*createHdi)();
79 if (halDevice_ == nullptr) {
80 LOGE("HuksHdiCreate failed");
81 dlclose(hdiHandle_);
82 hdiHandle_ = nullptr;
83 return false;
84 }
85 LOGI("success");
86 return true;
87 }
88
HdiDestroy()89 void HuksMaster::HdiDestroy()
90 {
91 LOGI("enter");
92 if (hdiHandle_ == nullptr) {
93 LOGI("hdiHandle_ is nullptr, already destroyed");
94 return;
95 }
96
97 auto destroyHdi = reinterpret_cast<HkmHalDestroyHandle>(dlsym(hdiHandle_, "HuksDestoryHdiDevicePtr"));
98 if ((destroyHdi != nullptr) && (halDevice_ != nullptr)) {
99 (*destroyHdi)(halDevice_);
100 }
101
102 dlclose(hdiHandle_);
103 hdiHandle_ = nullptr;
104 halDevice_ = nullptr;
105 LOGI("finish");
106 }
107
HdiModuleInit()108 int HuksMaster::HdiModuleInit()
109 {
110 LOGI("enter");
111 if (halDevice_ == nullptr) {
112 LOGE("halDevice_ is nullptr");
113 return HKS_ERROR_NULL_POINTER;
114 }
115 if (halDevice_->HuksHdiModuleInit == nullptr) {
116 LOGE("HuksHdiModuleInit is nullptr");
117 return HKS_ERROR_NULL_POINTER;
118 }
119
120 int ret = halDevice_->HuksHdiModuleInit();
121 if (ret == HKS_SUCCESS) {
122 LOGI("HuksHdiModuleInit success, ret %{public}d", ret);
123 return ret;
124 }
125
126 if (ret != HKS_ERROR_RETRYABLE_ERROR) {
127 LOGE("HuksHdiModuleInit failed, ret %{public}d", ret);
128 StorageRadar::ReportHuksResult("HuksHdiModuleInit", ret);
129 return ret;
130 }
131 int retryRet = 0;
132 for (int i = 0; i < MAX_RETRY_TIME; ++i) {
133 usleep(RETRY_INTERVAL_MS);
134 retryRet = halDevice_->HuksHdiModuleInit();
135 LOGE("HuksHdiModuleInit has retry %{public}d times, retryRet %{public}d", i, retryRet);
136 if (retryRet == HKS_SUCCESS) {
137 break;
138 }
139 }
140 LOGE("HuksHdiModuleInit end, retryRet %{public}d", retryRet);
141 if (retryRet != HKS_SUCCESS) {
142 StorageRadar::ReportHuksResult("HuksHdiModuleInit_Retry", retryRet);
143 }
144 return retryRet;
145 }
146
HdiModuleDestroy()147 int HuksMaster::HdiModuleDestroy()
148 {
149 LOGI("enter");
150 if (halDevice_ == nullptr) {
151 LOGE("halDevice_ is nullptr");
152 return HKS_ERROR_NULL_POINTER;
153 }
154 if (halDevice_->HuksHdiModuleDestroy == nullptr) {
155 LOGE("HuksHdiModuleDestroy is nullptr");
156 return HKS_ERROR_NULL_POINTER;
157 }
158
159 int ret = halDevice_->HuksHdiModuleDestroy();
160 if (ret == HKS_SUCCESS) {
161 LOGI("HuksHdiModuleDestroy success, ret %{public}d", ret);
162 return ret;
163 }
164
165 if (ret != HKS_ERROR_RETRYABLE_ERROR) {
166 LOGE("HuksHdiModuleDestroy failed, ret %{public}d", ret);
167 StorageRadar::ReportHuksResult("HuksHdiModuleDestroy", ret);
168 return ret;
169 }
170 int retryRet = 0;
171 for (int i = 0; i < MAX_RETRY_TIME; ++i) {
172 usleep(RETRY_INTERVAL_MS);
173 retryRet = halDevice_->HuksHdiModuleDestroy();
174 LOGE("HuksHdiModuleDestroy has retry %{public}d times, retryRet %{public}d", i, retryRet);
175 if (retryRet == HKS_SUCCESS) {
176 break;
177 }
178 }
179 LOGE("HuksHdiModuleDestroy end, retryRet %{public}d", retryRet);
180 if (retryRet != HKS_SUCCESS) {
181 StorageRadar::ReportHuksResult("HuksHdiModuleDestroy_Retry", retryRet);
182 }
183 return retryRet;
184 }
185
HdiGenerateKey(const HksBlob & keyAlias,const HksParamSet * paramSetIn,HksBlob & keyOut)186 int HuksMaster::HdiGenerateKey(const HksBlob &keyAlias, const HksParamSet *paramSetIn,
187 HksBlob &keyOut)
188 {
189 LOGI("enter");
190 if (halDevice_ == nullptr) {
191 LOGE("halDevice_ is nullptr");
192 return HKS_ERROR_NULL_POINTER;
193 }
194 if (halDevice_->HuksHdiGenerateKey == nullptr) {
195 LOGE("HuksHdiAccessGenerateKey is nullptr");
196 return HKS_ERROR_NULL_POINTER;
197 }
198
199 uint8_t data = 0;
200 HksBlob keyIn = {1, &data};
201 auto ret = halDevice_->HuksHdiGenerateKey(&keyAlias, paramSetIn, &keyIn, &keyOut);
202 if (ret == HKS_SUCCESS) {
203 LOGI("HuksHdiGenerateKey success, ret %{public}d", ret);
204 return ret;
205 }
206
207 if (ret != HKS_ERROR_RETRYABLE_ERROR) {
208 LOGE("HuksHdiGenerateKey failed, ret %{public}d", ret);
209 StorageRadar::ReportHuksResult("HuksHdiGenerateKey", ret);
210 return ret;
211 }
212 int retryRet = 0;
213 for (int i = 0; i < MAX_RETRY_TIME; ++i) {
214 usleep(RETRY_INTERVAL_MS);
215 retryRet = halDevice_->HuksHdiGenerateKey(&keyAlias, paramSetIn, &keyIn, &keyOut);
216 LOGE("HuksHdiGenerateKey has retry %{public}d times, retryRet %{public}d", i, retryRet);
217 if (retryRet == HKS_SUCCESS) {
218 break;
219 }
220 }
221 LOGE("HuksHdiGenerateKey end, retryRet %{public}d", retryRet);
222 if (retryRet != HKS_SUCCESS) {
223 StorageRadar::ReportHuksResult("HuksHdiGenerateKey_Retry", retryRet);
224 }
225 return retryRet;
226 }
227
HdiAccessInit(const HksBlob & key,const HksParamSet * paramSet,HksBlob & handle,HksBlob & token)228 int HuksMaster::HdiAccessInit(const HksBlob &key, const HksParamSet *paramSet,
229 HksBlob &handle, HksBlob &token)
230 {
231 LOGI("enter");
232 if (halDevice_ == nullptr) {
233 LOGE("halDevice_ is nullptr");
234 return HKS_ERROR_NULL_POINTER;
235 }
236 if (halDevice_->HuksHdiInit == nullptr) {
237 LOGE("HuksHdiAccessInit is nullptr");
238 return HKS_ERROR_NULL_POINTER;
239 }
240
241 auto ret = halDevice_->HuksHdiInit(&key, paramSet, &handle, &token);
242 if (ret == HKS_SUCCESS) {
243 LOGI("HuksHdiInit success, ret %{public}d", ret);
244 return ret;
245 }
246
247 if (ret != HKS_ERROR_RETRYABLE_ERROR) {
248 LOGE("HuksHdiInit failed, ret %{public}d", ret);
249 return ret;
250 }
251 int retryRet = 0;
252 for (int i = 0; i < MAX_RETRY_TIME; ++i) {
253 usleep(RETRY_INTERVAL_MS);
254 retryRet = halDevice_->HuksHdiInit(&key, paramSet, &handle, &token);
255 LOGE("HuksHdiInit has retry %{public}d times, retryRet %{public}d", i, retryRet);
256 if (retryRet == HKS_SUCCESS) {
257 break;
258 }
259 }
260 LOGE("HuksHdiInit end, retryRet %{public}d", retryRet);
261 if (retryRet != HKS_SUCCESS) {
262 StorageRadar::ReportHuksResult("HuksHdiInit_Retry", retryRet);
263 }
264 return retryRet;
265 }
266
HdiAccessFinish(const HksBlob & handle,const HksParamSet * paramSet,const HksBlob & inData,HksBlob & outData)267 int HuksMaster::HdiAccessFinish(const HksBlob &handle, const HksParamSet *paramSet,
268 const HksBlob &inData, HksBlob &outData)
269 {
270 LOGI("enter");
271 if (halDevice_ == nullptr) {
272 LOGE("halDevice_ is nullptr");
273 return HKS_ERROR_NULL_POINTER;
274 }
275 if (halDevice_->HuksHdiFinish == nullptr) {
276 LOGE("HuksHdiAccessFinish is nullptr");
277 return HKS_ERROR_NULL_POINTER;
278 }
279
280 auto ret = halDevice_->HuksHdiFinish(&handle, paramSet, &inData, &outData);
281 if (ret == HKS_SUCCESS) {
282 LOGI("HuksHdiFinish success, ret %{public}d", ret);
283 return ret;
284 }
285
286 if (ret != HKS_ERROR_RETRYABLE_ERROR) {
287 LOGE("HuksHdiFinish failed, ret %{public}d", ret);
288 return ret;
289 }
290 int retryRet = 0;
291 for (int i = 0; i < MAX_RETRY_TIME; ++i) {
292 usleep(RETRY_INTERVAL_MS);
293 retryRet = halDevice_->HuksHdiFinish(&handle, paramSet, &inData, &outData);
294 LOGE("HuksHdiFinish has retry %{public}d times, retryRet %{public}d", i, retryRet);
295 if (retryRet == HKS_SUCCESS) {
296 break;
297 }
298 }
299 LOGE("HuksHdiFinish end, retryRet %{public}d", retryRet);
300 if (retryRet != HKS_SUCCESS) {
301 StorageRadar::ReportHuksResult("HuksHdiFinish_Retry", retryRet);
302 }
303 return retryRet;
304 }
305
HdiAccessUpgradeKey(const HksBlob & oldKey,const HksParamSet * paramSet,struct HksBlob & newKey)306 int HuksMaster::HdiAccessUpgradeKey(const HksBlob &oldKey, const HksParamSet *paramSet, struct HksBlob &newKey)
307 {
308 LOGI("enter");
309 if (halDevice_ == nullptr) {
310 LOGE("halDevice_ is nullptr");
311 return HKS_ERROR_NULL_POINTER;
312 }
313 if (halDevice_->HuksHdiUpgradeKey == nullptr) {
314 LOGE("HuksHdiUpgradeKey is nullptr");
315 return HKS_ERROR_NULL_POINTER;
316 }
317
318 auto ret = halDevice_->HuksHdiUpgradeKey(&oldKey, paramSet, &newKey);
319 if (ret == HKS_SUCCESS) {
320 LOGI("HuksHdiUpgradeKey success, ret %{public}d", ret);
321 return ret;
322 }
323
324 if (ret != HKS_ERROR_RETRYABLE_ERROR) {
325 LOGE("HuksHdiUpgradeKey failed, ret %{public}d", ret);
326 StorageRadar::ReportHuksResult("HuksHdiUpgradeKey", ret);
327 return ret;
328 }
329 int retryRet = 0;
330 for (int i = 0; i < MAX_RETRY_TIME; ++i) {
331 usleep(RETRY_INTERVAL_MS);
332 retryRet = halDevice_->HuksHdiUpgradeKey(&oldKey, paramSet, &newKey);
333 LOGE("HuksHdiUpgradeKey has retry %{public}d times, retryRet %{public}d", i, retryRet);
334 if (retryRet == HKS_SUCCESS) {
335 break;
336 }
337 }
338 LOGE("HuksHdiUpgradeKey end, retryRet %{public}d", retryRet);
339 if (retryRet != HKS_SUCCESS) {
340 StorageRadar::ReportHuksResult("HuksHdiUpgradeKey_Retry", retryRet);
341 }
342 return retryRet;
343 }
344
GenerateRandomKey(uint32_t keyLen)345 KeyBlob HuksMaster::GenerateRandomKey(uint32_t keyLen)
346 {
347 LOGI("enter, size %{public}d", keyLen);
348 KeyBlob out(keyLen);
349 if (out.IsEmpty()) {
350 return out;
351 }
352
353 auto ret = RAND_bytes(out.data.get(), out.size);
354 if (ret <= 0) {
355 LOGE("RAND_bytes failed return %{public}d, errno %{public}lu", ret, ERR_get_error());
356 out.Clear();
357 }
358 return out;
359 }
360
AppendSecureAccessParams(const UserAuth & auth,HksParamSet * paramSet)361 static int AppendSecureAccessParams(const UserAuth &auth, HksParamSet *paramSet)
362 {
363 if (auth.secret.IsEmpty() || auth.token.IsEmpty()) {
364 LOGI("auth is empty, not to enable secure access for the key");
365 return HKS_SUCCESS;
366 }
367
368 LOGI("append the secure access params when generate key");
369
370 HksParam param[] = {
371 { .tag = HKS_TAG_USER_AUTH_TYPE,
372 .uint32Param = HKS_USER_AUTH_TYPE_PIN | HKS_USER_AUTH_TYPE_FACE | HKS_USER_AUTH_TYPE_FINGERPRINT },
373 { .tag = HKS_TAG_KEY_AUTH_ACCESS_TYPE, .uint32Param = HKS_AUTH_ACCESS_INVALID_CLEAR_PASSWORD },
374 { .tag = HKS_TAG_CHALLENGE_TYPE, .uint32Param = HKS_CHALLENGE_TYPE_NONE },
375 { .tag = HKS_TAG_USER_AUTH_SECURE_UID, .blob = { sizeof(auth.secureUid), (uint8_t *)&auth.secureUid } },
376 { .tag = HKS_TAG_AUTH_TIMEOUT, .uint32Param = 30 } // token timeout is 30 seconds when no challenge
377 };
378 return HksAddParams(paramSet, param, HKS_ARRAY_SIZE(param));
379 }
380
381 static uint8_t g_processName[sizeof(uint32_t)] = {0};
382 static const HksParam g_generateKeyParam[] = {
383 { .tag = HKS_TAG_KEY_GENERATE_TYPE, .uint32Param = HKS_KEY_GENERATE_TYPE_DEFAULT },
384 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT },
385 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
386 { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 },
387 { .tag = HKS_TAG_DIGEST, .uint32Param = HKS_DIGEST_SHA256 },
388 { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
389 { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
390 { .tag = HKS_TAG_PROCESS_NAME,
391 .blob =
392 { sizeof(g_processName), g_processName }
393 },
394 };
395
GenerateKey(const UserAuth & auth,KeyBlob & keyOut)396 int32_t HuksMaster::GenerateKey(const UserAuth &auth, KeyBlob &keyOut)
397 {
398 LOGI("enter");
399
400 HksParamSet *paramSet = nullptr;
401 int ret = HKS_SUCCESS;
402 do {
403 ret = HksInitParamSet(¶mSet);
404 if (ret != HKS_SUCCESS) {
405 LOGE("HksInitParamSet failed ret %{public}d", ret);
406 break;
407 }
408 ret = HksAddParams(paramSet, g_generateKeyParam, HKS_ARRAY_SIZE(g_generateKeyParam));
409 if (ret != HKS_SUCCESS) {
410 LOGE("HksAddParams failed ret %{public}d", ret);
411 break;
412 }
413 ret = AppendSecureAccessParams(auth, paramSet);
414 if (ret != HKS_SUCCESS) {
415 LOGE("AppendSecureAccessParams failed ret %{public}d", ret);
416 break;
417 }
418 ret = HksBuildParamSet(¶mSet);
419 if (ret != HKS_SUCCESS) {
420 LOGE("HksBuildParamSet failed ret %{public}d", ret);
421 break;
422 }
423 KeyBlob alias = GenerateRandomKey(CRYPTO_KEY_ALIAS_SIZE);
424 HksBlob hksAlias = alias.ToHksBlob();
425 keyOut.Alloc(CRYPTO_KEY_SHIELD_MAX_SIZE);
426 HksBlob hksKeyOut = keyOut.ToHksBlob();
427 ret = HdiGenerateKey(hksAlias, paramSet, hksKeyOut);
428 if (ret != HKS_SUCCESS) {
429 LOGE("HdiGenerateKey failed ret %{public}d", ret);
430 break;
431 }
432 keyOut.size = hksKeyOut.size;
433 LOGI("HdiGenerateKey success, out size %{public}d", keyOut.size);
434 } while (0);
435
436 HksFreeParamSet(¶mSet);
437 return ret;
438 }
439
HashWithPrefix(const std::string & prefix,const KeyBlob & payload,uint32_t length)440 static KeyBlob HashWithPrefix(const std::string &prefix, const KeyBlob &payload, uint32_t length)
441 {
442 KeyBlob res(SHA512_DIGEST_LENGTH);
443 std::string header = prefix;
444 if (header.empty()) {
445 header = "dummy SHA512 header";
446 }
447
448 SHA512_CTX c;
449 SHA512_Init(&c);
450 SHA512_Update(&c, header.data(), header.size());
451 if (!payload.IsEmpty()) {
452 SHA512_Update(&c, payload.data.get(), payload.size);
453 }
454 SHA512_Final(res.data.get(), &c);
455
456 res.size = length;
457 return res;
458 }
459
GenHuksKeyBlobParam(KeyContext & ctx)460 static HksParamSet *GenHuksKeyBlobParam(KeyContext &ctx)
461 {
462 return reinterpret_cast<HksParamSet *>(ctx.shield.data.get());
463 }
464
AppendAeTag(KeyBlob & cipherText,HksParamSet * paramSet)465 static int AppendAeTag(KeyBlob &cipherText, HksParamSet *paramSet)
466 {
467 if (cipherText.size <= HKS_AE_TAG_LEN) {
468 LOGE("cipherText size %{public}d is too small", cipherText.size);
469 return HKS_ERROR_INVALID_KEY_INFO;
470 }
471 if (cipherText.data.get() == nullptr) {
472 LOGE("cipherText data pointer is null");
473 return HKS_ERROR_INVALID_KEY_INFO;
474 }
475
476 HksParam param[] = {
477 { .tag = HKS_TAG_AE_TAG,
478 .blob =
479 { HKS_AE_TAG_LEN, cipherText.data.get() + cipherText.size - HKS_AE_TAG_LEN }
480 },
481 };
482 cipherText.size -= HKS_AE_TAG_LEN;
483 return HksAddParams(paramSet, param, HKS_ARRAY_SIZE(param));
484 }
485
AppendNonceAad(KeyContext & ctx,HksParamSet * paramSet)486 static int AppendNonceAad(KeyContext &ctx, HksParamSet *paramSet)
487 {
488 ctx.nonce = HashWithPrefix("NONCE SHA512 prefix", ctx.secDiscard, CRYPTO_AES_NONCE_LEN);
489 ctx.aad = HashWithPrefix("AAD SHA512 prefix", ctx.secDiscard, CRYPTO_AES_AAD_LEN);
490 HksParam addParam[] = {
491 { .tag = HKS_TAG_NONCE, .blob = { ctx.nonce.size, ctx.nonce.data.get() } },
492 { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = { ctx.aad.size, ctx.aad.data.get() } }
493 };
494 return HksAddParams(paramSet, addParam, HKS_ARRAY_SIZE(addParam));
495 }
496
AppendNonceAadTokenEx(KeyContext & ctx,const UserAuth & auth,HksParamSet * paramSet,bool isEncrypt)497 static int AppendNonceAadTokenEx(KeyContext &ctx, const UserAuth &auth, HksParamSet *paramSet, bool isEncrypt)
498 {
499 if (auth.secret.IsEmpty() || auth.token.IsEmpty()) {
500 LOGI("auth is empty, not to use secure access tag");
501 HksParam addParam[] = {
502 { .tag = HKS_TAG_NONCE, .blob = { ctx.nonce.size, ctx.nonce.data.get() } },
503 { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = { ctx.aad.size, ctx.aad.data.get() } }
504 };
505 return HksAddParams(paramSet, addParam, HKS_ARRAY_SIZE(addParam));
506 }
507
508 HksParam addParam[] = {
509 { .tag = HKS_TAG_NONCE, .blob = { ctx.nonce.size, ctx.nonce.data.get() } },
510 { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = { ctx.aad.size, ctx.aad.data.get() } },
511 { .tag = HKS_TAG_AUTH_TOKEN, .blob = { auth.token.size, auth.token.data.get() } }
512 };
513 return HksAddParams(paramSet, addParam, HKS_ARRAY_SIZE(addParam));
514 }
515
AppendNewNonceAadToken(KeyContext & ctx,const UserAuth & auth,HksParamSet * paramSet,const bool isEncrypt)516 static int AppendNewNonceAadToken(KeyContext &ctx, const UserAuth &auth, HksParamSet *paramSet, const bool isEncrypt)
517 {
518 LOGI("append the secure access params when encrypt/decrypt");
519 if (isEncrypt) {
520 ctx.nonce = HuksMaster::GenerateRandomKey(CRYPTO_HKS_NONCE_LEN);
521 LOGI("Encrypt generate new nonce size: %{public}d", ctx.nonce.size);
522 }
523 ctx.aad = HashWithPrefix("AAD SHA512 prefix", ctx.secDiscard, CRYPTO_AES_AAD_LEN);
524 LOGI("secret/token is empty : %{public}d / %{public}d", auth.secret.IsEmpty(), auth.token.IsEmpty());
525 if (auth.secret.IsEmpty() && auth.token.IsEmpty()) {
526 LOGI("token & secret is empty, Only append nonce & aad!");
527 return AppendNonceAad(ctx, paramSet);
528 }
529 HksParam addParam[] = {
530 { .tag = HKS_TAG_NONCE, .blob = { ctx.nonce.size, ctx.nonce.data.get() } },
531 { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = {ctx.aad.size, ctx.aad.data.get() } },
532 { .tag = HKS_TAG_AUTH_TOKEN, .blob = {auth.token.size, auth.token.data.get() } }
533 };
534 return HksAddParams(paramSet, addParam, HKS_ARRAY_SIZE(addParam));
535 }
536
AppendNonceAadToken(KeyContext & ctx,const UserAuth & auth,HksParamSet * paramSet)537 static int AppendNonceAadToken(KeyContext &ctx, const UserAuth &auth, HksParamSet *paramSet)
538 {
539 if (auth.secret.IsEmpty() || auth.token.IsEmpty()) {
540 LOGI("auth is empty, not to use secure access tag");
541 return AppendNonceAad(ctx, paramSet);
542 }
543
544 LOGI("append the secure access params when encrypt/decrypt");
545 ctx.nonce = HashWithPrefix("NONCE SHA512 prefix", auth.secret, CRYPTO_AES_NONCE_LEN);
546 ctx.aad = HashWithPrefix("AAD SHA512 prefix", ctx.secDiscard, CRYPTO_AES_AAD_LEN);
547 HksParam addParam[] = {
548 { .tag = HKS_TAG_USER_AUTH_TYPE, .uint32Param = HKS_USER_AUTH_TYPE_PIN },
549 { .tag = HKS_TAG_KEY_AUTH_ACCESS_TYPE, .uint32Param = HKS_AUTH_ACCESS_INVALID_CLEAR_PASSWORD },
550 { .tag = HKS_TAG_NONCE,
551 .blob =
552 { ctx.nonce.size, ctx.nonce.data.get() }
553 },
554 { .tag = HKS_TAG_ASSOCIATED_DATA,
555 .blob =
556 { ctx.aad.size, ctx.aad.data.get() }
557 },
558 { .tag = HKS_TAG_AUTH_TOKEN,
559 .blob =
560 { auth.token.size, auth.token.data.get() }
561 }
562 };
563 return HksAddParams(paramSet, addParam, HKS_ARRAY_SIZE(addParam));
564 }
565
GenHuksOptionParamEx(KeyContext & ctx,const UserAuth & auth,const bool isEncrypt)566 static HksParamSet *GenHuksOptionParamEx(KeyContext &ctx, const UserAuth &auth, const bool isEncrypt)
567 {
568 HksParam encryptParam[] = {
569 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
570 { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
571 { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
572 { .tag = HKS_TAG_IS_KEY_ALIAS, .boolParam = false },
573 { .tag = HKS_TAG_PURPOSE, .uint32Param = isEncrypt ? HKS_KEY_PURPOSE_ENCRYPT : HKS_KEY_PURPOSE_DECRYPT},
574 { .tag = HKS_TAG_CHALLENGE_TYPE, .uint32Param = HKS_CHALLENGE_TYPE_NONE },
575 { .tag = HKS_TAG_PROCESS_NAME, .blob = { sizeof(g_processName), g_processName } }
576 };
577
578 HksParamSet *paramSet = nullptr;
579 auto ret = HksInitParamSet(¶mSet);
580 if (ret != HKS_SUCCESS) {
581 LOGE("HksInitParamSet failed ret %{public}d", ret);
582 return nullptr;
583 }
584 ret = HksAddParams(paramSet, encryptParam, HKS_ARRAY_SIZE(encryptParam));
585 if (ret != HKS_SUCCESS) {
586 LOGE("HksAddParams failed ret %{public}d", ret);
587 HksFreeParamSet(¶mSet);
588 return nullptr;
589 }
590
591 if (!isEncrypt) {
592 ret = AppendAeTag(ctx.rndEnc, paramSet);
593 if (ret != HKS_SUCCESS) {
594 LOGE("AppendAeTag failed ret %{public}d", ret);
595 HksFreeParamSet(¶mSet);
596 return nullptr;
597 }
598 }
599
600 ret = AppendNonceAadTokenEx(ctx, auth, paramSet, isEncrypt);
601 if (ret != HKS_SUCCESS) {
602 LOGE("AppendNonceAad failed ret %{public}d", ret);
603 HksFreeParamSet(¶mSet);
604 return nullptr;
605 }
606
607 ret = HksBuildParamSet(¶mSet);
608 if (ret != HKS_SUCCESS) {
609 LOGE("HksBuildParamSet failed ret %{public}d", ret);
610 HksFreeParamSet(¶mSet);
611 return nullptr;
612 }
613
614 return paramSet;
615 }
616
GenHuksOptionParam(KeyContext & ctx,const UserAuth & auth,const bool isEncrypt,const bool isNeedNewNonce)617 static HksParamSet *GenHuksOptionParam(KeyContext &ctx,
618 const UserAuth &auth,
619 const bool isEncrypt,
620 const bool isNeedNewNonce)
621 {
622 HksParam encryptParam[] = {
623 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
624 { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
625 { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
626 { .tag = HKS_TAG_IS_KEY_ALIAS, .boolParam = false },
627 { .tag = HKS_TAG_PURPOSE, .uint32Param = isEncrypt ? HKS_KEY_PURPOSE_ENCRYPT : HKS_KEY_PURPOSE_DECRYPT },
628 { .tag = HKS_TAG_CHALLENGE_TYPE, .uint32Param = HKS_CHALLENGE_TYPE_NONE },
629 { .tag = HKS_TAG_PROCESS_NAME, .blob = { sizeof(g_processName), g_processName } }
630 };
631
632 HksParamSet *paramSet = nullptr;
633 auto ret = HksInitParamSet(¶mSet);
634 if (ret != HKS_SUCCESS) {
635 LOGE("HksInitParamSet failed ret %{public}d", ret);
636 return nullptr;
637 }
638 ret = HksAddParams(paramSet, encryptParam, HKS_ARRAY_SIZE(encryptParam));
639 if (ret != HKS_SUCCESS) {
640 LOGE("HksAddParams failed ret %{public}d", ret);
641 HksFreeParamSet(¶mSet);
642 return nullptr;
643 }
644
645 if (!isEncrypt) {
646 ret = AppendAeTag(ctx.rndEnc, paramSet);
647 if (ret != HKS_SUCCESS) {
648 LOGE("AppendAeTag failed ret %{public}d", ret);
649 HksFreeParamSet(¶mSet);
650 return nullptr;
651 }
652 }
653
654 ret = isNeedNewNonce ? AppendNonceAadToken(ctx, auth, paramSet)
655 : AppendNewNonceAadToken(ctx, auth, paramSet, isEncrypt);
656 if (ret != HKS_SUCCESS) {
657 LOGE("AppendNonceAad failed ret %{public}d", ret);
658 HksFreeParamSet(¶mSet);
659 return nullptr;
660 }
661
662 ret = HksBuildParamSet(¶mSet);
663 if (ret != HKS_SUCCESS) {
664 LOGE("HksBuildParamSet failed ret %{public}d", ret);
665 HksFreeParamSet(¶mSet);
666 return nullptr;
667 }
668
669 return paramSet;
670 }
671
HuksHalTripleStage(HksParamSet * paramSet1,const HksParamSet * paramSet2,const KeyBlob & keyIn,KeyBlob & keyOut)672 int HuksMaster::HuksHalTripleStage(HksParamSet *paramSet1, const HksParamSet *paramSet2,
673 const KeyBlob &keyIn, KeyBlob &keyOut)
674 {
675 LOGI("enter");
676 HksBlob hksKey = { paramSet1->paramSetSize, reinterpret_cast<uint8_t *>(paramSet1) };
677 HksBlob hksIn = keyIn.ToHksBlob();
678 HksBlob hksOut = keyOut.ToHksBlob();
679 uint8_t h[sizeof(uint64_t)] = {0};
680 HksBlob hksHandle = { sizeof(uint64_t), h };
681 uint8_t t[CRYPTO_TOKEN_SIZE] = {0};
682 HksBlob hksToken = { sizeof(t), t }; // would not use the challenge here
683
684 int ret = HdiAccessInit(hksKey, paramSet2, hksHandle, hksToken);
685 if (ret != HKS_SUCCESS) {
686 LOGE("HdiAccessInit failed ret %{public}d", ret);
687 return ret;
688 }
689
690 ret = HdiAccessFinish(hksHandle, paramSet2, hksIn, hksOut);
691 if (ret != HKS_SUCCESS) {
692 if (ret == HKS_ERROR_KEY_AUTH_TIME_OUT) {
693 StorageService::KeyCryptoUtils::ForceLockUserScreen();
694 LOGE("HdiAccessFinish failed because authToken timeout, force lock user screen.");
695 }
696 LOGE("HdiAccessFinish failed ret %{public}d", ret);
697 return ret;
698 }
699
700 keyOut.size = hksOut.size;
701 LOGI("finish");
702 return E_OK;
703 }
704
EncryptKeyEx(const UserAuth & auth,const KeyBlob & rnd,KeyContext & ctx)705 int32_t HuksMaster::EncryptKeyEx(const UserAuth &auth, const KeyBlob &rnd, KeyContext &ctx)
706 {
707 LOGI("enter");
708 if (ctx.shield.IsEmpty()) {
709 LOGE("bad shield input, size %{public}d", ctx.shield.size);
710 return E_KEY_CTX_ERROR;
711 }
712 if (rnd.IsEmpty()) {
713 LOGE("bad rawKey input, size %{public}d", rnd.size);
714 return E_KEY_BLOB_ERROR;
715 }
716
717 HksParamSet *paramSet1 = GenHuksKeyBlobParam(ctx);
718 if (paramSet1 == nullptr) {
719 LOGE("GenHuksKeyBlobParam failed");
720 return E_GEN_HUKS_PARAM_ERROR;
721 }
722 HksParamSet *paramSet2 = GenHuksOptionParamEx(ctx, auth, true);
723 if (paramSet2 == nullptr) {
724 LOGE("GenHuksOptionParam failed");
725 return E_GEN_HUKS_PARAM_ERROR;
726 }
727
728 ctx.rndEnc.Alloc(rnd.size + CRYPTO_AES_AAD_LEN);
729 auto ret = HuksHalTripleStage(paramSet1, paramSet2, rnd, ctx.rndEnc);
730 if (ret != E_OK) {
731 LOGE("HuksHalTripleStage failed");
732 }
733
734 HksFreeParamSet(¶mSet2);
735 LOGI("finish");
736 return ret;
737 }
738
EncryptKey(KeyContext & ctx,const UserAuth & auth,const KeyInfo & key,bool isNeedNewNonce)739 int32_t HuksMaster::EncryptKey(KeyContext &ctx, const UserAuth &auth, const KeyInfo &key, bool isNeedNewNonce)
740 {
741 LOGI("enter");
742 if (ctx.shield.IsEmpty()) {
743 LOGE("bad shield input, size %{public}d", ctx.shield.size);
744 return E_KEY_CTX_ERROR;
745 }
746 if (key.key.IsEmpty()) {
747 LOGE("bad rawKey input, size %{public}d", key.key.size);
748 return E_KEY_EMPTY_ERROR;
749 }
750
751 HksParamSet *paramSet1 = GenHuksKeyBlobParam(ctx);
752 if (paramSet1 == nullptr) {
753 LOGE("GenHuksKeyBlobParam failed");
754 return E_GEN_HUKS_PARAM_ERROR;
755 }
756 HksParamSet *paramSet2 = GenHuksOptionParam(ctx, auth, true, isNeedNewNonce);
757 if (paramSet2 == nullptr) {
758 LOGE("GenHuksOptionParam failed");
759 return E_GEN_HUKS_PARAM_ERROR;
760 }
761
762 ctx.rndEnc.Alloc(CRYPTO_AES_256_KEY_ENCRYPTED_SIZE);
763 auto ret = HuksHalTripleStage(paramSet1, paramSet2, key.key, ctx.rndEnc);
764 if (ret != E_OK) {
765 LOGE("HuksHalTripleStage failed");
766 }
767 HksFreeParamSet(¶mSet2);
768 LOGI("finish");
769 return ret;
770 }
771
DecryptKey(KeyContext & ctx,const UserAuth & auth,KeyInfo & key,bool isNeedNewNonce)772 int32_t HuksMaster::DecryptKey(KeyContext &ctx, const UserAuth &auth, KeyInfo &key, bool isNeedNewNonce)
773 {
774 LOGI("enter");
775 if (ctx.shield.IsEmpty()) {
776 LOGE("bad shield input, size %{public}d", ctx.shield.size);
777 return E_KEY_CTX_ERROR;
778 }
779 if (ctx.rndEnc.IsEmpty()) {
780 LOGE("bad encrypted input, size %{public}d", ctx.rndEnc.size);
781 return E_KEY_CTX_ERROR;
782 }
783
784 HksParamSet *paramSet1 = GenHuksKeyBlobParam(ctx);
785 if (paramSet1 == nullptr) {
786 LOGE("GenHuksKeyBlobParam failed");
787 return E_GEN_HUKS_PARAM_ERROR;
788 }
789 HksParamSet *paramSet2 = GenHuksOptionParam(ctx, auth, false, isNeedNewNonce);
790 if (paramSet2 == nullptr) {
791 LOGE("GenHuksOptionParam failed");
792 return E_GEN_HUKS_PARAM_ERROR;
793 }
794
795 key.key.Alloc(ctx.rndEnc.size);
796 auto ret = HuksHalTripleStage(paramSet1, paramSet2, ctx.rndEnc, key.key);
797 if (ret != E_OK) {
798 LOGE("HuksHalTripleStage failed");
799 }
800
801 HksFreeParamSet(¶mSet2);
802 LOGI("finish");
803 return ret;
804 }
805
DecryptKeyEx(KeyContext & ctx,const UserAuth & auth,KeyBlob & rnd)806 int32_t HuksMaster::DecryptKeyEx(KeyContext &ctx, const UserAuth &auth, KeyBlob &rnd)
807 {
808 LOGI("enter");
809 if (ctx.shield.IsEmpty()) {
810 LOGE("bad shield input, size %{public}d", ctx.shield.size);
811 return E_KEY_CTX_ERROR;
812 }
813 if (ctx.rndEnc.IsEmpty()) {
814 LOGE("bad encrypted input, size %{public}d", ctx.rndEnc.size);
815 return E_KEY_CTX_ERROR;
816 }
817
818 HksParamSet *paramSet1 = GenHuksKeyBlobParam(ctx);
819 if (paramSet1 == nullptr) {
820 LOGE("GenHuksKeyBlobParam failed");
821 return E_GEN_HUKS_PARAM_ERROR;
822 }
823 HksParamSet *paramSet2 = GenHuksOptionParamEx(ctx, auth, false);
824 if (paramSet2 == nullptr) {
825 LOGE("GenHuksOptionParam failed");
826 return E_GEN_HUKS_PARAM_ERROR;
827 }
828
829 rnd.Alloc(ctx.rndEnc.size);
830 auto ret = HuksHalTripleStage(paramSet1, paramSet2, ctx.rndEnc, rnd);
831 if (ret != E_OK) {
832 LOGE("HuksHalTripleStage failed");
833 }
834
835 HksFreeParamSet(¶mSet2);
836 LOGI("finish");
837 return ret;
838 }
839
CheckNeedUpgrade(KeyBlob & inData)840 static bool CheckNeedUpgrade(KeyBlob &inData)
841 {
842 constexpr uint32_t HKS_KEY_VERSION = 3;
843 HksParamSet *keyBlobParamSet = nullptr;
844 int ret = HksGetParamSet(reinterpret_cast<HksParamSet *>(inData.data.get()), inData.size, &keyBlobParamSet);
845 if (ret != HKS_SUCCESS) {
846 LOGE("HksGetParamSet failed %{public}d", ret);
847 return false;
848 }
849
850 struct HksParam *keyVersion = nullptr;
851 ret = HksGetParam(keyBlobParamSet, HKS_TAG_KEY_VERSION, &keyVersion);
852 if (ret != HKS_SUCCESS) {
853 LOGE("version get key param failed!");
854 HksFreeParamSet(&keyBlobParamSet);
855 return false;
856 }
857
858 if (keyVersion->uint32Param >= HKS_KEY_VERSION) {
859 HksFreeParamSet(&keyBlobParamSet);
860 return false;
861 }
862 HksFreeParamSet(&keyBlobParamSet);
863 return true;
864 }
865
UpgradeKey(KeyContext & ctx)866 bool HuksMaster::UpgradeKey(KeyContext &ctx)
867 {
868 struct HksParamSet *paramSet = nullptr;
869 bool ret = false;
870
871 if (!CheckNeedUpgrade(ctx.shield)) {
872 LOGI("no need to upgrade");
873 return false;
874 }
875
876 LOGI("Do upgradekey");
877 do {
878 int err = HksInitParamSet(¶mSet);
879 if (err != HKS_SUCCESS) {
880 LOGE("HksInitParamSet failed ret %{public}d", err);
881 break;
882 }
883 err = HksAddParams(paramSet, g_generateKeyParam, HKS_ARRAY_SIZE(g_generateKeyParam));
884 if (err != HKS_SUCCESS) {
885 LOGE("HksAddParams failed ret %{public}d", err);
886 break;
887 }
888 err = HksBuildParamSet(¶mSet);
889 if (err != HKS_SUCCESS) {
890 LOGE("HksBuildParamSet failed ret %{public}d", err);
891 break;
892 }
893
894 KeyBlob keyOut(CRYPTO_KEY_SHIELD_MAX_SIZE);
895 HksBlob hksIn = ctx.shield.ToHksBlob();
896 HksBlob hksOut = keyOut.ToHksBlob();
897
898 err = HdiAccessUpgradeKey(hksIn, paramSet, hksOut);
899 if (err == HKS_SUCCESS) {
900 LOGI("Shield upgraded successfully");
901 keyOut.size = hksOut.size;
902 ctx.shield.Clear();
903 ctx.shield = std::move(keyOut);
904 ret = true;
905 }
906 } while (0);
907 HksFreeParamSet(¶mSet);
908 return ret;
909 }
910
911 } // namespace StorageDaemon
912 } // namespace OHOS
913