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