• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&paramSet);
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(&paramSet);
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(&paramSet);
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(&paramSet);
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(&paramSet);
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(&paramSet);
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(&paramSet);
573         return nullptr;
574     }
575 
576     ret = HksBuildParamSet(&paramSet);
577     if (ret != HKS_SUCCESS) {
578         LOGE("HksBuildParamSet failed ret %{public}d", ret);
579         HksFreeParamSet(&paramSet);
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(&paramSet);
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(&paramSet);
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(&paramSet);
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(&paramSet);
628         return nullptr;
629     }
630 
631     ret = HksBuildParamSet(&paramSet);
632     if (ret != HKS_SUCCESS) {
633         LOGE("HksBuildParamSet failed ret %{public}d", ret);
634         HksFreeParamSet(&paramSet);
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(&paramSet2);
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(&paramSet2);
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(&paramSet2);
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(&paramSet2);
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(&paramSet);
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(&paramSet);
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(&paramSet);
877     return ret;
878 }
879 
880 } // namespace StorageDaemon
881 } // namespace OHOS
882