• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&paramSet);
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(&paramSet);
72         return ret;
73     }
74 
75     ret = HksBuildParamSet(&paramSet);
76     if (ret != HKS_SUCCESS) {
77         CM_LOG_E("build paramSet failed");
78         HksFreeParamSet(&paramSet);
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         &paramSet);
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(&paramSet);
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), &paramSet);
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(&paramSet);
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), &paramSet);
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(&paramSet);
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(&paramSet);
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(&paramSet);
309         return ret;
310     }
311 
312     ret = HksBuildParamSet(&paramSet);
313     if (ret != HKS_SUCCESS) {
314         CM_LOG_E("build params failed, ret = %d", ret);
315         HksFreeParamSet(&paramSet);
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, &paramSet);
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(&paramSet);
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(&paramSet);
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(&paramSet);
436     return ret;
437 }
438 
439