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(¶mSet);
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(¶mSet);
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(¶mSet);
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(¶mSet);
557 return nullptr;
558 }
559
560 ret = HksBuildParamSet(¶mSet);
561 if (ret != HKS_SUCCESS) {
562 LOGE("HksBuildParamSet failed ret %{public}d", ret);
563 HksFreeParamSet(¶mSet);
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(¶mSet);
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(¶mSet);
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(¶mSet);
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(¶mSet);
612 return nullptr;
613 }
614
615 ret = HksBuildParamSet(¶mSet);
616 if (ret != HKS_SUCCESS) {
617 LOGE("HksBuildParamSet failed ret %{public}d", ret);
618 HksFreeParamSet(¶mSet);
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(¶mSet);
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(¶mSet);
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(¶mSet);
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(¶mSet2);
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(¶mSet2);
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(¶mSet2);
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(¶mSet2);
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(¶mSet);
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(¶mSet);
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(¶mSet);
917 return ret;
918 #endif
919 return false;
920 }
921
922 } // namespace StorageDaemon
923 } // namespace OHOS
924