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(&paramSet);
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(&paramSet);
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(&paramSet);
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(&paramSet);
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(&paramSet);
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(&paramSet);
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(&paramSet);
597         return nullptr;
598     }
599 
600     ret = HksBuildParamSet(&paramSet);
601     if (ret != HKS_SUCCESS) {
602         LOGE("HksBuildParamSet failed ret %{public}d", ret);
603         HksFreeParamSet(&paramSet);
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(&paramSet);
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(&paramSet);
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(&paramSet);
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(&paramSet);
652         return nullptr;
653     }
654 
655     ret = HksBuildParamSet(&paramSet);
656     if (ret != HKS_SUCCESS) {
657         LOGE("HksBuildParamSet failed ret %{public}d", ret);
658         HksFreeParamSet(&paramSet);
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(&paramSet2);
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(&paramSet2);
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(&paramSet2);
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(&paramSet2);
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(&paramSet);
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(&paramSet);
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(&paramSet);
901     return ret;
902 }
903 
904 } // namespace StorageDaemon
905 } // namespace OHOS
906