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