1 /*
2 * Copyright (c) 2022 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 "cert_manager_key_operation.h"
17
18 #include "cert_manager_mem.h"
19 #include "cert_manager_session_mgr.h"
20 #include "cm_log.h"
21 #include "cm_type.h"
22
23 #include "hks_api.h"
24 #include "hks_param.h"
25 #include "hks_type.h"
26
27 struct PropertyToHuks {
28 uint32_t cmProperty;
29 uint32_t huksProperty;
30 };
31
32 static struct PropertyToHuks g_cmPurposeProperty[] = {
33 { CM_KEY_PURPOSE_SIGN, HKS_KEY_PURPOSE_SIGN },
34 { CM_KEY_PURPOSE_VERIFY, HKS_KEY_PURPOSE_VERIFY },
35 };
36
37 static struct PropertyToHuks g_cmPaddingProperty[] = {
38 { CM_PADDING_NONE, HKS_PADDING_NONE },
39 { CM_PADDING_OAEP, HKS_PADDING_OAEP },
40 { CM_PADDING_PSS, HKS_PADDING_PSS },
41 { CM_PADDING_PKCS1_V1_5, HKS_PADDING_PKCS1_V1_5 },
42 { CM_PADDING_PKCS5, HKS_PADDING_PKCS5 },
43 { CM_PADDING_PKCS7, HKS_PADDING_PKCS7 },
44 };
45
46 static struct PropertyToHuks g_cmDigestProperty[] = {
47 { CM_DIGEST_NONE, HKS_DIGEST_NONE },
48 { CM_DIGEST_MD5, HKS_DIGEST_MD5 },
49 { CM_DIGEST_SHA1, HKS_DIGEST_SHA1 },
50 { CM_DIGEST_SHA224, HKS_DIGEST_SHA224 },
51 { CM_DIGEST_SHA256, HKS_DIGEST_SHA256 },
52 { CM_DIGEST_SHA384, HKS_DIGEST_SHA384 },
53 { CM_DIGEST_SHA512, HKS_DIGEST_SHA512 },
54 };
55
56 #define INVALID_PROPERTY_VALUE 0xFFFF
57 #define DEFAULT_LEN_USED_FOR_MALLOC 1024
58
ConstructParamSet(const struct HksParam * params,uint32_t paramCount,struct HksParamSet ** outParamSet)59 static int32_t ConstructParamSet(const struct HksParam *params, uint32_t paramCount, struct HksParamSet **outParamSet)
60 {
61 struct HksParamSet *paramSet = NULL;
62 int32_t ret = HksInitParamSet(¶mSet);
63 if (ret != HKS_SUCCESS) {
64 CM_LOG_E("init paramset failed");
65 return ret;
66 }
67
68 ret = HksAddParams(paramSet, params, paramCount);
69 if (ret != HKS_SUCCESS) {
70 CM_LOG_E("add params failed");
71 HksFreeParamSet(¶mSet);
72 return ret;
73 }
74
75 ret = HksBuildParamSet(¶mSet);
76 if (ret != HKS_SUCCESS) {
77 CM_LOG_E("build paramSet failed");
78 HksFreeParamSet(¶mSet);
79 return ret;
80 }
81
82 *outParamSet = paramSet;
83 return CM_SUCCESS;
84 }
85
CmKeyOpGenMacKey(const struct CmBlob * alias)86 int32_t CmKeyOpGenMacKey(const struct CmBlob *alias)
87 {
88 struct HksParam genMacKeyParams[] = {
89 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_HMAC },
90 { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 },
91 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_MAC },
92 { .tag = HKS_TAG_DIGEST, .uint32Param = HKS_DIGEST_SHA256 },
93 };
94
95 struct HksParamSet *paramSet = NULL;
96 int32_t ret = ConstructParamSet(genMacKeyParams, sizeof(genMacKeyParams) / sizeof(struct HksParam),
97 ¶mSet);
98 if (ret != CM_SUCCESS) {
99 CM_LOG_E("construct gen mac key paramSet failed");
100 return CMR_ERROR_KEY_OPERATION_FAILED;
101 }
102
103 struct HksBlob keyAlias = { alias->size, alias->data };
104 ret = HksGenerateKey(&keyAlias, paramSet, NULL);
105 HksFreeParamSet(¶mSet);
106 if (ret != HKS_SUCCESS) {
107 CM_LOG_E("hks generate key failed, ret = %d", ret);
108 return CMR_ERROR_KEY_OPERATION_FAILED;
109 }
110 return CM_SUCCESS;
111 }
112
CmKeyOpGenMacKeyIfNotExist(const struct CmBlob * alias)113 int32_t CmKeyOpGenMacKeyIfNotExist(const struct CmBlob *alias)
114 {
115 struct HksBlob keyAlias = { alias->size, alias->data };
116 int32_t ret = HksKeyExist(&keyAlias, NULL);
117 if (ret == HKS_SUCCESS) {
118 return ret;
119 }
120 if (ret != HKS_ERROR_NOT_EXIST) {
121 CM_LOG_E("find mac key failed, ret = %d", ret);
122 return CMR_ERROR_KEY_OPERATION_FAILED;
123 }
124
125 return CmKeyOpGenMacKey(alias);
126 }
127
CmKeyOpDeleteKey(const struct CmBlob * alias)128 int32_t CmKeyOpDeleteKey(const struct CmBlob *alias)
129 {
130 struct HksBlob keyAlias = { alias->size, alias->data };
131 int32_t ret = HksDeleteKey(&keyAlias, NULL);
132 if ((ret != HKS_SUCCESS) && (ret != HKS_ERROR_NOT_EXIST)) {
133 CM_LOG_E("hks delete key failed, ret = %d", ret);
134 return CMR_ERROR_KEY_OPERATION_FAILED;
135 }
136
137 return CM_SUCCESS;
138 }
139
CmKeyOpCalcMac(const struct CmBlob * alias,const struct CmBlob * srcData,struct CmBlob * mac)140 int32_t CmKeyOpCalcMac(const struct CmBlob *alias, const struct CmBlob *srcData, struct CmBlob *mac)
141 {
142 struct HksParam macParams[] = {
143 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_HMAC },
144 { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 },
145 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_MAC },
146 { .tag = HKS_TAG_DIGEST, .uint32Param = HKS_DIGEST_SHA256 },
147 };
148
149 struct HksParamSet *paramSet = NULL;
150 int32_t ret = ConstructParamSet(macParams, sizeof(macParams) / sizeof(struct HksParam), ¶mSet);
151 if (ret != CM_SUCCESS) {
152 CM_LOG_E("construct mac init paramSet failed");
153 return CMR_ERROR_KEY_OPERATION_FAILED;
154 }
155
156 do {
157 uint64_t handleValue = 0;
158 struct HksBlob handle = { sizeof(handleValue), (uint8_t *)&handleValue };
159 struct HksBlob keyAlias = { alias->size, alias->data };
160 ret = HksInit(&keyAlias, paramSet, &handle, NULL);
161 if (ret != HKS_SUCCESS) {
162 CM_LOG_E("mac calc init failed, ret = %d", ret);
163 break;
164 }
165
166 struct HksBlob inData = { srcData->size, srcData->data };
167 struct HksBlob outMac = { mac->size, mac->data };
168 ret = HksFinish(&handle, paramSet, &inData, &outMac);
169 if (ret != HKS_SUCCESS) {
170 CM_LOG_E("mac calc finish failed, ret = %d", ret);
171 break;
172 }
173 mac->size = outMac.size;
174 } while (0);
175
176 HksFreeParamSet(¶mSet);
177 return (ret == HKS_SUCCESS) ? CM_SUCCESS : CMR_ERROR_KEY_OPERATION_FAILED;
178 }
179
CmKeyOpImportKey(const struct CmBlob * alias,const struct CmKeyProperties * properties,const struct CmBlob * keyPair)180 int32_t CmKeyOpImportKey(const struct CmBlob *alias, const struct CmKeyProperties *properties,
181 const struct CmBlob *keyPair)
182 {
183 struct HksParam importKeyParams[] = {
184 { .tag = HKS_TAG_IMPORT_KEY_TYPE, .uint32Param = HKS_KEY_TYPE_KEY_PAIR },
185 { .tag = HKS_TAG_ALGORITHM, .uint32Param = properties->algType },
186 { .tag = HKS_TAG_KEY_SIZE, .uint32Param = properties->keySize },
187 { .tag = HKS_TAG_PURPOSE, .uint32Param = properties->purpose },
188 };
189
190 struct HksParamSet *paramSet = NULL;
191 int32_t ret = ConstructParamSet(importKeyParams, sizeof(importKeyParams) / sizeof(struct HksParam), ¶mSet);
192 if (ret != CM_SUCCESS) {
193 CM_LOG_E("construct import key paramSet failed");
194 return CMR_ERROR_KEY_OPERATION_FAILED;
195 }
196
197 struct HksBlob keyAlias = { alias->size, alias->data };
198 struct HksBlob key = { keyPair->size, keyPair->data };
199 ret = HksImportKey(&keyAlias, paramSet, &key);
200 HksFreeParamSet(¶mSet);
201 if (ret != HKS_SUCCESS) {
202 CM_LOG_E("hks import key failed, ret = %d", ret);
203 return CMR_ERROR_KEY_OPERATION_FAILED;
204 }
205 return CM_SUCCESS;
206 }
207
FillKeySpec(const struct HksParamSet * paramSet,struct CmKeyProperties * spec)208 static void FillKeySpec(const struct HksParamSet *paramSet, struct CmKeyProperties *spec)
209 {
210 for (uint32_t i = 0; i < paramSet->paramsCnt; ++i) {
211 switch (paramSet->params[i].tag) {
212 case HKS_TAG_ALGORITHM:
213 spec->algType = paramSet->params[i].uint32Param;
214 break;
215 case HKS_TAG_KEY_SIZE:
216 spec->keySize = paramSet->params[i].uint32Param;
217 break;
218 default:
219 break;
220 }
221 }
222 }
223
TranslateToHuksProperties(const struct CmSignatureSpec * spec,struct CmKeyProperties * keyProperties)224 static void TranslateToHuksProperties(const struct CmSignatureSpec *spec, struct CmKeyProperties *keyProperties)
225 {
226 keyProperties->purpose = INVALID_PROPERTY_VALUE;
227 keyProperties->padding = INVALID_PROPERTY_VALUE;
228 keyProperties->digest = INVALID_PROPERTY_VALUE;
229
230 for (uint32_t i = 0; i < CM_ARRAY_SIZE(g_cmPurposeProperty); ++i) {
231 if (spec->purpose == g_cmPurposeProperty[i].cmProperty) {
232 keyProperties->purpose = g_cmPurposeProperty[i].huksProperty;
233 break;
234 }
235 }
236
237 for (uint32_t i = 0; i < CM_ARRAY_SIZE(g_cmPaddingProperty); ++i) {
238 if (spec->padding == g_cmPaddingProperty[i].cmProperty) {
239 keyProperties->padding = g_cmPaddingProperty[i].huksProperty;
240 break;
241 }
242 }
243
244 for (uint32_t i = 0; i < CM_ARRAY_SIZE(g_cmDigestProperty); ++i) {
245 if (spec->digest == g_cmDigestProperty[i].cmProperty) {
246 keyProperties->digest = g_cmDigestProperty[i].huksProperty;
247 break;
248 }
249 }
250 CM_LOG_I("purpose[%u], digest[%u], padding[%u]", spec->purpose, spec->digest, spec->padding);
251 }
252
AddParamsToParamSet(const struct CmBlob * commonUri,const struct CmSignatureSpec * spec,struct HksParamSet * paramSet)253 static int32_t AddParamsToParamSet(const struct CmBlob *commonUri, const struct CmSignatureSpec *spec,
254 struct HksParamSet *paramSet)
255 {
256 struct CmKeyProperties inputKeyProp = {0};
257 TranslateToHuksProperties(spec, &inputKeyProp);
258
259 struct HksParamSet *outParamSet = (struct HksParamSet*)CMMalloc(DEFAULT_LEN_USED_FOR_MALLOC);
260 if (outParamSet == NULL) {
261 CM_LOG_E("malloc failed");
262 return CMR_ERROR_MALLOC_FAIL;
263 }
264 outParamSet->paramSetSize = DEFAULT_LEN_USED_FOR_MALLOC;
265
266 int32_t ret;
267 do {
268 ret = HksGetKeyParamSet((const struct HksBlob *)commonUri, NULL, outParamSet);
269 if (ret != HKS_SUCCESS) {
270 CM_LOG_E("get paramSet from huks failed, ret = %d", ret);
271 break;
272 }
273
274 struct CmKeyProperties keySpec = {0};
275 FillKeySpec(outParamSet, &keySpec);
276 struct HksParam params[] = {
277 { .tag = HKS_TAG_ALGORITHM, .uint32Param = keySpec.algType },
278 { .tag = HKS_TAG_KEY_SIZE, .uint32Param = keySpec.keySize },
279 { .tag = HKS_TAG_PURPOSE, .uint32Param = inputKeyProp.purpose },
280 { .tag = HKS_TAG_DIGEST, .uint32Param = inputKeyProp.digest },
281 { .tag = HKS_TAG_PADDING, .uint32Param = inputKeyProp.padding },
282 };
283
284 ret = HksAddParams(paramSet, params, sizeof(params) / sizeof(struct HksParam));
285 if (ret != HKS_SUCCESS) {
286 CM_LOG_E("add params failed");
287 break;
288 }
289 } while (0);
290
291 CM_FREE_PTR(outParamSet);
292 return (ret == HKS_SUCCESS) ? CM_SUCCESS : CMR_ERROR_KEY_OPERATION_FAILED;
293 }
294
ConstructInitParamSet(const struct CmBlob * commonUri,const struct CmSignatureSpec * spec,struct HksParamSet ** outParamSet)295 static int32_t ConstructInitParamSet(const struct CmBlob *commonUri, const struct CmSignatureSpec *spec,
296 struct HksParamSet **outParamSet)
297 {
298 struct HksParamSet *paramSet = NULL;
299 int32_t ret = HksInitParamSet(¶mSet);
300 if (ret != HKS_SUCCESS) {
301 CM_LOG_E("init paramSet failed, ret = %d", ret);
302 return CMR_ERROR_KEY_OPERATION_FAILED;
303 }
304
305 ret = AddParamsToParamSet(commonUri, spec, paramSet);
306 if (ret != CM_SUCCESS) {
307 CM_LOG_E("add params failed");
308 HksFreeParamSet(¶mSet);
309 return ret;
310 }
311
312 ret = HksBuildParamSet(¶mSet);
313 if (ret != HKS_SUCCESS) {
314 CM_LOG_E("build params failed, ret = %d", ret);
315 HksFreeParamSet(¶mSet);
316 return CMR_ERROR_KEY_OPERATION_FAILED;
317 }
318
319 *outParamSet = paramSet;
320 return CM_SUCCESS;
321 }
322
ServiceSignVerifyUpdate(const struct CmBlob * handle,const struct HksParamSet * paramSet,const struct CmBlob * inData)323 static int32_t ServiceSignVerifyUpdate(const struct CmBlob *handle, const struct HksParamSet *paramSet,
324 const struct CmBlob *inData)
325 {
326 uint32_t temp = 0;
327 struct HksBlob tempOut = { sizeof(uint32_t), (uint8_t *)&temp };
328
329 struct HksBlob handleHks = { handle->size, handle->data };
330 struct HksBlob inDataHks = { inData->size, inData->data };
331
332 int32_t ret = HksUpdate(&handleHks, paramSet, &inDataHks, &tempOut);
333 if (ret != HKS_SUCCESS) {
334 CM_LOG_E("huks update fail, ret = %d", ret);
335 CmDeleteSession(handle);
336 return CMR_ERROR_KEY_OPERATION_FAILED;
337 }
338 return CM_SUCCESS;
339 }
340
ServiceSignVerifyFinish(const struct CmBlob * handle,const struct HksParamSet * paramSet,const struct CmBlob * inData,struct CmBlob * outData)341 static int32_t ServiceSignVerifyFinish(const struct CmBlob *handle, const struct HksParamSet *paramSet,
342 const struct CmBlob *inData, struct CmBlob *outData)
343 {
344 struct HksBlob handleHks = { handle->size, handle->data };
345 struct HksBlob inDataHks = { inData->size, inData->data };
346 struct HksBlob outDataHks = { outData->size, outData->data };
347
348 int32_t ret = HksFinish(&handleHks, paramSet, &inDataHks, &outDataHks);
349 CmDeleteSession(handle);
350 if (ret != HKS_SUCCESS) {
351 CM_LOG_E("huks finish fail, ret = %d", ret);
352 return CMR_ERROR_KEY_OPERATION_FAILED;
353 }
354 outData->size = outDataHks.size;
355 return CM_SUCCESS;
356 }
357
ServiceSignVerifyAbort(const struct CmBlob * handle,const struct HksParamSet * paramSet)358 static int32_t ServiceSignVerifyAbort(const struct CmBlob *handle, const struct HksParamSet *paramSet)
359 {
360 struct HksBlob handleHks = { handle->size, handle->data };
361
362 int32_t ret = HksAbort(&handleHks, paramSet);
363 CmDeleteSession(handle);
364 if (ret != HKS_SUCCESS) {
365 CM_LOG_E("huks abort fail, ret = %d", ret);
366 return CMR_ERROR_KEY_OPERATION_FAILED;
367 }
368 return CM_SUCCESS;
369 }
370
CmKeyOpInit(const struct CmContext * context,const struct CmBlob * alias,const struct CmSignatureSpec * spec,struct CmBlob * handle)371 int32_t CmKeyOpInit(const struct CmContext *context, const struct CmBlob *alias, const struct CmSignatureSpec *spec,
372 struct CmBlob *handle)
373 {
374 struct HksParamSet *paramSet = NULL;
375 int32_t ret = ConstructInitParamSet(alias, spec, ¶mSet);
376 if (ret != CM_SUCCESS) {
377 CM_LOG_E("construct init paramSet failed, ret = %d", ret);
378 return ret;
379 }
380
381 do {
382 struct HksBlob keyAlias = { alias->size, alias->data };
383 struct HksBlob handleOut = { handle->size, handle->data };
384 ret = HksInit(&keyAlias, paramSet, &handleOut, NULL);
385 if (ret != HKS_SUCCESS) {
386 CM_LOG_E("Huks init failed, ret = %d", ret);
387 break;
388 }
389 handle->size = handleOut.size;
390
391 struct CmSessionNodeInfo info = { context->userId, context->uid, *alias };
392 ret = CmCreateSession(&info, handle, true);
393 if (ret != CM_SUCCESS) {
394 CM_LOG_E("create session failed, ret = %d", ret);
395 break;
396 }
397 } while (0);
398
399 HksFreeParamSet(¶mSet);
400 return (ret == HKS_SUCCESS) ? CM_SUCCESS : CMR_ERROR_KEY_OPERATION_FAILED;
401 }
402
CmKeyOpProcess(enum CmSignVerifyCmd cmdId,const struct CmContext * context,const struct CmBlob * handle,const struct CmBlob * inData,struct CmBlob * outData)403 int32_t CmKeyOpProcess(enum CmSignVerifyCmd cmdId, const struct CmContext *context, const struct CmBlob *handle,
404 const struct CmBlob *inData, struct CmBlob *outData)
405 {
406 struct CmSessionNodeInfo info = { context->userId, context->uid, { 0, NULL } };
407 if (CmQuerySession(&info, handle) == NULL) {
408 CM_LOG_E("session handle not exist");
409 return (cmdId == SIGN_VERIFY_CMD_ABORT) ? CM_SUCCESS : CMR_ERROR_NOT_EXIST;
410 }
411
412 struct HksParamSet *paramSet = NULL;
413 int32_t ret = HksInitParamSet(¶mSet);
414 if (ret != HKS_SUCCESS) {
415 CM_LOG_E("init paramset failed");
416 CmDeleteSession(handle);
417 return CMR_ERROR_KEY_OPERATION_FAILED;
418 }
419
420 switch (cmdId) {
421 case SIGN_VERIFY_CMD_UPDATE:
422 ret = ServiceSignVerifyUpdate(handle, paramSet, inData);
423 break;
424 case SIGN_VERIFY_CMD_FINISH:
425 ret = ServiceSignVerifyFinish(handle, paramSet, inData, outData);
426 break;
427 case SIGN_VERIFY_CMD_ABORT:
428 ret = ServiceSignVerifyAbort(handle, paramSet);
429 break;
430 default:
431 ret = CMR_ERROR_INVALID_ARGUMENT;
432 break;
433 }
434
435 HksFreeParamSet(¶mSet);
436 return ret;
437 }
438
439