1 /*
2 * Copyright (c) 2025 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_adapt_manager.h"
17
18 #include "hks_api.h"
19 #include "hks_param.h"
20 #include "securec.h"
21
22 #include "alg_utils.h"
23 #include "dlp_permission.h"
24 #include "dlp_permission_log.h"
25
26 namespace OHOS {
27 namespace Security {
28 namespace DlpPermission {
29 namespace {
30 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, SECURITY_DOMAIN_DLP_PERMISSION, "HuksAdaptManager" };
31 }
32 static const uint32_t HMAC_KEY_SIZE_256 = 256;
33
CheckHMACParams(const HuksKeyInfo * keyInfo,const BlobData * data,const BlobData * outData)34 static bool CheckHMACParams(const HuksKeyInfo *keyInfo, const BlobData *data, const BlobData *outData)
35 {
36 if (keyInfo == nullptr || !IsBlobDataValid(&(keyInfo->keyAlias))) {
37 DLP_LOG_ERROR(LABEL, "Mac keyInfo is invalid!");
38 return false;
39 }
40 if (!IsBlobDataValid(data) || data->dataSize > MAX_DATABASE_FILE_SIZE) {
41 DLP_LOG_ERROR(LABEL, "Mac data is invalid!");
42 return false;
43 }
44 if (outData == nullptr) {
45 DLP_LOG_ERROR(LABEL, "Mac outData is invalid!");
46 return false;
47 }
48 return true;
49 }
50
ConstructParamSet(struct HksParamSet ** outParamSet,struct HksParam * params,uint32_t paramcount)51 static int32_t ConstructParamSet(struct HksParamSet **outParamSet, struct HksParam *params,
52 uint32_t paramcount)
53 {
54 int32_t res = HksInitParamSet(outParamSet);
55 if (res != HKS_SUCCESS) {
56 DLP_LOG_ERROR(LABEL, "HksInitParamSet failed, error code: %{public}d.", res);
57 return DLP_SERVICE_ERROR_VALUE_INVALID;
58 }
59
60 res = HksAddParams(*outParamSet, params, paramcount);
61 if (res != HKS_SUCCESS) {
62 DLP_LOG_ERROR(LABEL, "HksAddParams failed, error code: %{public}d.", res);
63 HksFreeParamSet(outParamSet);
64 return DLP_SERVICE_ERROR_VALUE_INVALID;
65 }
66
67 res = HksBuildParamSet(outParamSet);
68 if (res != HKS_SUCCESS) {
69 DLP_LOG_ERROR(LABEL, "HksBuildParamSet failed, error code: %{public}d.", res);
70 HksFreeParamSet(outParamSet);
71 return DLP_SERVICE_ERROR_VALUE_INVALID;
72 }
73 return DLP_OK;
74 }
75
MallocAndCheckBlobData(struct HksBlob * blob,uint32_t blobSize)76 static int32_t MallocAndCheckBlobData(struct HksBlob *blob, uint32_t blobSize)
77 {
78 blob->data = (uint8_t *)HcMalloc(blobSize, 0);
79 if (blob->data == nullptr) {
80 DLP_LOG_ERROR(LABEL, "Allocate blob data memory failed!");
81 return HKS_FAILURE;
82 }
83 return HKS_SUCCESS;
84 }
85
LessThanMaxSeg(const struct HksBlob * handle,const struct HksParamSet * paramSet,const struct HksBlob * inData,struct HksBlob * outData)86 static int32_t LessThanMaxSeg(const struct HksBlob *handle, const struct HksParamSet *paramSet,
87 const struct HksBlob *inData, struct HksBlob *outData)
88 {
89 struct HksBlob tmpOutData = { MAX_OUTDATA_SIZE, nullptr };
90 if (MallocAndCheckBlobData(&tmpOutData, tmpOutData.size) != HKS_SUCCESS) {
91 return HKS_FAILURE;
92 }
93 int32_t ret = HksUpdate(handle, paramSet, inData, &tmpOutData);
94 HcFree(tmpOutData.data);
95 if (ret != HKS_SUCCESS) {
96 DLP_LOG_ERROR(LABEL, "HksUpdate Failed.");
97 return HKS_FAILURE;
98 }
99 struct HksBlob tmpInData = { 0, nullptr };
100 if (MallocAndCheckBlobData(&tmpInData, MAX_UPDATE_SIZE) != HKS_SUCCESS) {
101 return HKS_FAILURE;
102 }
103
104 ret = HksFinish(handle, paramSet, &tmpInData, outData);
105 HcFree(tmpInData.data);
106 if (ret != HKS_SUCCESS) {
107 DLP_LOG_ERROR(LABEL, "HksFinish Failed.");
108 return HKS_FAILURE;
109 }
110 return HKS_SUCCESS;
111 }
112
HksShardingUpdateAndFinish(const struct HksBlob * handle,const struct HksParamSet * paramSet,const struct HksBlob * inData,struct HksBlob * outData)113 static int32_t HksShardingUpdateAndFinish(const struct HksBlob *handle, const struct HksParamSet *paramSet,
114 const struct HksBlob *inData, struct HksBlob *outData)
115 {
116 struct HksBlob inDataSeg = *inData;
117 inDataSeg.size = MAX_UPDATE_SIZE;
118 uint8_t *lastPtr = inData->data + inData->size - 1;
119 struct HksBlob outDataSeg = { MAX_OUTDATA_SIZE, nullptr };
120
121 if (inData->size <= MAX_UPDATE_SIZE) {
122 return LessThanMaxSeg(handle, paramSet, inData, outData);
123 }
124
125 while (inDataSeg.data <= lastPtr) {
126 if (inDataSeg.data + MAX_UPDATE_SIZE <= lastPtr) {
127 outDataSeg.size = MAX_OUTDATA_SIZE;
128 if (MallocAndCheckBlobData(&outDataSeg, outDataSeg.size) != HKS_SUCCESS) {
129 return HKS_FAILURE;
130 }
131 } else {
132 inDataSeg.size = lastPtr - inDataSeg.data + 1;
133 break;
134 }
135 if (HksUpdate(handle, paramSet, &inDataSeg, &outDataSeg) != HKS_SUCCESS) {
136 DLP_LOG_ERROR(LABEL, "HksUpdate Failed.");
137 DLP_FREE_PTR(outDataSeg.data);
138 return HKS_FAILURE;
139 }
140 DLP_FREE_PTR(outDataSeg.data);
141 if (inDataSeg.data + MAX_UPDATE_SIZE > lastPtr) {
142 return HKS_FAILURE;
143 }
144 inDataSeg.data += MAX_UPDATE_SIZE;
145 }
146 if (HksFinish(handle, paramSet, &inDataSeg, outData) != HKS_SUCCESS) {
147 DLP_LOG_ERROR(LABEL, "Finish stage failed.");
148 return HKS_FAILURE;
149 }
150 return HKS_SUCCESS;
151 }
152
HksHMACThreeStages(const BlobData * keyAlias,struct HksParamSet * hmacParamSet,const BlobData * data,BlobData * outData)153 static int32_t HksHMACThreeStages(const BlobData *keyAlias, struct HksParamSet *hmacParamSet,
154 const BlobData *data, BlobData *outData)
155 {
156 uint8_t handle[SIZE_OF_UINT64] = { 0 };
157 struct HksBlob handleHMAC = { SIZE_OF_UINT64, handle };
158 int32_t ret = HksInit((struct HksBlob *)keyAlias, hmacParamSet, &handleHMAC, nullptr);
159 if (ret != HKS_SUCCESS) {
160 return ret;
161 }
162
163 ret = HksShardingUpdateAndFinish(&handleHMAC, hmacParamSet, (struct HksBlob *)data, (struct HksBlob *)outData);
164 if (ret != HKS_SUCCESS) {
165 DLP_LOG_ERROR(LABEL, "Update and finish stage failed, error code: %{public}d", ret);
166 HksAbort(&handleHMAC, hmacParamSet);
167 return DLP_SERVICE_ERROR_VALUE_INVALID;
168 }
169 return DLP_OK;
170 }
171
IsHuksMgrKeyExist(const HuksKeyInfo * keyInfo)172 bool IsHuksMgrKeyExist(const HuksKeyInfo *keyInfo)
173 {
174 if (keyInfo == nullptr || !IsBlobDataValid(&(keyInfo->keyAlias))) {
175 DLP_LOG_ERROR(LABEL, "keyInfo is invalid!");
176 return false;
177 }
178 struct HksParamSet *paramSet = nullptr;
179 struct HksParam deHmacParams[] = {
180 { .tag = HKS_TAG_SPECIFIC_USER_ID, .uint32Param = keyInfo->osAccountId },
181 { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE },
182 };
183 int32_t res = ConstructParamSet(¶mSet, deHmacParams, sizeof(deHmacParams) / sizeof(deHmacParams[0]));
184 if (res != DLP_OK) {
185 DLP_LOG_ERROR(LABEL, "construct param set failed!");
186 return false;
187 }
188 res = HksKeyExist((struct HksBlob *)(&(keyInfo->keyAlias)), paramSet);
189 HksFreeParamSet(¶mSet);
190 if (res != HKS_SUCCESS) {
191 DLP_LOG_ERROR(LABEL, "Key is not exist, error code: %{public}d.", res);
192 return false;
193 }
194 return true;
195 }
196
HuksGenerateMacKey(const HuksKeyInfo * keyInfo)197 int32_t HuksGenerateMacKey(const HuksKeyInfo *keyInfo)
198 {
199 if (keyInfo == nullptr || !IsBlobDataValid(&(keyInfo->keyAlias))) {
200 DLP_LOG_ERROR(LABEL, "keyInfo is invalid!");
201 return DLP_SERVICE_ERROR_VALUE_INVALID;
202 }
203
204 struct HksParamSet *paramSet = nullptr;
205 struct HksParam deGenParams[] = {
206 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_HMAC },
207 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_MAC },
208 { .tag = HKS_TAG_DIGEST, .uint32Param = HKS_DIGEST_SHA256 },
209 { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HMAC_KEY_SIZE_256 },
210 { .tag = HKS_TAG_SPECIFIC_USER_ID, .uint32Param = keyInfo->osAccountId },
211 { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE },
212 };
213 int32_t ret = ConstructParamSet(¶mSet, deGenParams, sizeof(deGenParams) / sizeof(deGenParams[0]));
214 if (ret != DLP_OK) {
215 DLP_LOG_ERROR(LABEL, "Construct MacKey ParamSet failed!");
216 return DLP_SERVICE_ERROR_VALUE_INVALID;
217 }
218 ret = HksGenerateKey((struct HksBlob *)(&(keyInfo->keyAlias)), paramSet, nullptr);
219 HksFreeParamSet(¶mSet);
220 if (ret != HKS_SUCCESS) {
221 DLP_LOG_ERROR(LABEL, "HksGenerateKey for mac key failed, error code: %{public}d.", ret);
222 return DLP_SERVICE_ERROR_VALUE_INVALID;
223 }
224 return DLP_OK;
225 }
226
HuksGenerateHmac(const HuksKeyInfo * keyInfo,const BlobData * data,BlobData * outData)227 int32_t HuksGenerateHmac(const HuksKeyInfo *keyInfo, const BlobData *data, BlobData *outData)
228 {
229 if (!CheckHMACParams(keyInfo, data, outData)) {
230 return DLP_SERVICE_ERROR_VALUE_INVALID;
231 }
232 outData->value = (uint8_t *)HcMalloc(HASH_SIZE_SHA_256, 0);
233 if (outData->value == nullptr) {
234 DLP_LOG_ERROR(LABEL, "Allocate outData memory failed");
235 return DLP_SERVICE_ERROR_MEMORY_OPERATE_FAIL;
236 }
237 outData->dataSize = HASH_SIZE_SHA_256;
238
239 struct HksParamSet *hmacParamSet = nullptr;
240 struct HksParam deHmacParams[] = {
241 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_HMAC },
242 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_MAC },
243 { .tag = HKS_TAG_DIGEST, .uint32Param = HKS_DIGEST_SHA256 },
244 { .tag = HKS_TAG_SPECIFIC_USER_ID, .uint32Param = keyInfo->osAccountId },
245 { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE },
246 };
247 int32_t res = ConstructParamSet(&hmacParamSet, deHmacParams, sizeof(deHmacParams) / sizeof(deHmacParams[0]));
248 if (res != DLP_OK) {
249 DLP_LOG_ERROR(LABEL, "construct hmac param set failed!");
250 FreeBlobData(outData);
251 return DLP_SERVICE_ERROR_VALUE_INVALID;
252 }
253 res = HksHMACThreeStages(&(keyInfo->keyAlias), hmacParamSet, data, outData);
254 HksFreeParamSet(&hmacParamSet);
255 if (res != DLP_OK) {
256 FreeBlobData(outData);
257 res = DLP_SERVICE_ERROR_VALUE_INVALID;
258 }
259 return res;
260 }
261 } // namespace DlpPermission
262 } // namespace Security
263 } // namespace OHOS