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