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