• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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 "hks_local_engine.h"
17 
18 #include <stdbool.h>
19 #include <stddef.h>
20 
21 #include "hks_ability.h"
22 #include "hks_base_check.h"
23 #include "hks_check_paramset.h"
24 #include "hks_cmd_id.h"
25 #include "hks_common_check.h"
26 #include "hks_crypto_adapter.h"
27 #include "hks_crypto_hal.h"
28 #include "hks_log.h"
29 #include "hks_mem.h"
30 #include "hks_param.h"
31 #include "hks_template.h"
32 #include "securec.h"
33 
34 #define MAX_DEGIST_SIZE 64
35 #define X25519_KEY_BYTE_SIZE 32
36 
HksLocalCryptoAbilityInit(void)37 static void HksLocalCryptoAbilityInit(void)
38 {
39     int32_t ret = HksCryptoAbilityInit();
40     HKS_IF_NOT_SUCC_LOGE(ret, "Hks local init crypto ability failed, ret = %" LOG_PUBLIC "d", ret)
41 }
42 
43 #ifndef _CUT_AUTHENTICATE_
HksLocalHash(const struct HksParamSet * paramSet,const struct HksBlob * srcData,struct HksBlob * hash)44 int32_t HksLocalHash(const struct HksParamSet *paramSet, const struct HksBlob *srcData, struct HksBlob *hash)
45 {
46     HKS_IF_NOT_SUCC_RETURN(HksCheckBlob2AndParamSet(srcData, hash, paramSet), HKS_ERROR_INVALID_ARGUMENT)
47 
48     struct HksParam *digestAlg = NULL;
49     int32_t ret = HksGetParam(paramSet, HKS_TAG_DIGEST, &digestAlg);
50     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, HKS_ERROR_CHECK_GET_DIGEST_FAIL, "get param digest failed")
51 
52     uint32_t digestLen;
53     ret = HksGetDigestLen(digestAlg->uint32Param, &digestLen);
54     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "get digest len failed, ret = %" LOG_PUBLIC "d", ret)
55 
56     if (hash->size < digestLen) {
57         HKS_LOG_E("hash len too small, size = %" LOG_PUBLIC "u", hash->size);
58         return HKS_ERROR_BUFFER_TOO_SMALL;
59     }
60     HksLocalCryptoAbilityInit();
61     return HksCryptoHalHash(digestAlg->uint32Param, srcData, hash);
62 }
63 #endif
64 
HksLocalMac(const struct HksBlob * key,const struct HksParamSet * paramSet,const struct HksBlob * srcData,struct HksBlob * mac)65 int32_t HksLocalMac(const struct HksBlob *key, const struct HksParamSet *paramSet,
66     const struct HksBlob *srcData, struct HksBlob *mac)
67 {
68     HKS_IF_NOT_SUCC_RETURN(HksCheckBlob3AndParamSet(key, srcData, mac, paramSet), HKS_ERROR_INVALID_ARGUMENT)
69     int32_t ret = HksCoreCheckMacParams(key, paramSet, srcData, mac, true);
70     HKS_IF_NOT_SUCC_RETURN(ret, ret)
71 
72     struct HksParam *digestAlg = NULL;
73     ret = HksGetParam(paramSet, HKS_TAG_DIGEST, &digestAlg);
74     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, HKS_ERROR_CHECK_GET_DIGEST_FAIL, "get param digest failed")
75     HksLocalCryptoAbilityInit();
76     return HksCryptoHalHmac(key, digestAlg->uint32Param, srcData, mac);
77 }
78 
HksLocalBnExpMod(struct HksBlob * x,const struct HksBlob * a,const struct HksBlob * e,const struct HksBlob * n)79 int32_t HksLocalBnExpMod(struct HksBlob *x, const struct HksBlob *a, const struct HksBlob *e, const struct HksBlob *n)
80 {
81     int32_t ret = HksCheckBlob4(x, a, e, n);
82     HKS_IF_NOT_SUCC_RETURN(ret, ret)
83     HksLocalCryptoAbilityInit();
84     return HksCryptoHalBnExpMod(x, a, e, n);
85 }
86 
87 #ifndef _CUT_AUTHENTICATE_
CheckLocalGenerateKeyParams(const struct HksParamSet * paramSetIn,const struct HksParamSet * paramSetOut)88 static int32_t CheckLocalGenerateKeyParams(const struct HksParamSet *paramSetIn, const struct HksParamSet *paramSetOut)
89 {
90     int32_t ret;
91     if ((HksCheckParamSetValidity(paramSetIn) != HKS_SUCCESS) || (paramSetOut == NULL)) {
92         return HKS_ERROR_INVALID_ARGUMENT;
93     }
94 
95     ret = HksCoreCheckGenKeyParams(NULL, paramSetIn, NULL, NULL, HKS_KEY_FLAG_GENERATE_KEY);
96     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, HKS_ERROR_INVALID_ARGUMENT,
97         "check generate key parameter failed ret = %" LOG_PUBLIC "x.", ret)
98 
99     return HKS_SUCCESS;
100 }
101 
HksLocalGenerateKey(const struct HksParamSet * paramSetIn,struct HksParamSet * paramSetOut)102 int32_t HksLocalGenerateKey(const struct HksParamSet *paramSetIn, struct HksParamSet *paramSetOut)
103 {
104     int32_t ret = CheckLocalGenerateKeyParams(paramSetIn, paramSetOut);
105     HKS_IF_NOT_SUCC_RETURN(ret, ret)
106 
107     struct HksKeySpec spec = {0};
108     HksFillKeySpec(paramSetIn, &spec);
109     struct HksBlob key = { 0, NULL };
110 
111     HksLocalCryptoAbilityInit();
112     ret = HksCryptoHalGenerateKey(&spec, &key);
113     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "local engine generate key failed, ret:%" LOG_PUBLIC "x!", ret)
114 
115     ret = HksFormatKeyFromMaterial(spec.algType, &key, paramSetOut);
116     (void)memset_s(key.data, key.size, 0, key.size);
117     HKS_FREE_PTR(key.data);
118     return ret;
119 }
120 
HksLocalAgreeKey(const struct HksParamSet * paramSet,const struct HksBlob * privateKey,const struct HksBlob * peerPublicKey,struct HksBlob * agreedKey)121 int32_t HksLocalAgreeKey(const struct HksParamSet *paramSet, const struct HksBlob *privateKey,
122     const struct HksBlob *peerPublicKey, struct HksBlob *agreedKey)
123 {
124     HKS_IF_NOT_SUCC_RETURN(HksCheckBlob3AndParamSet(privateKey, peerPublicKey, agreedKey, paramSet),
125         HKS_ERROR_INVALID_ARGUMENT)
126 
127     int32_t ret = HksCoreCheckAgreeKeyParams(paramSet, privateKey, peerPublicKey, agreedKey, true);
128     HKS_IF_NOT_SUCC_RETURN(ret, ret)
129 
130     struct HksKeySpec spec = {0};
131     HksFillKeySpec(paramSet, &spec);
132 
133     struct HksBlob privateKeyMaterial = { 0, NULL };
134     ret = HksSetKeyToMaterial(spec.algType, false, privateKey, &privateKeyMaterial);
135     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "set prikey to materail failed, ret:%" LOG_PUBLIC "x!", ret)
136 
137     struct HksBlob publicKeyMaterial = { 0, NULL };
138     ret = HksSetKeyToMaterial(spec.algType, true, peerPublicKey, &publicKeyMaterial);
139     if (ret != HKS_SUCCESS) {
140         HKS_LOG_E("set pubkey to materail failed, ret:%" LOG_PUBLIC "x!", ret);
141         (void)memset_s(privateKeyMaterial.data, privateKeyMaterial.size, 0, privateKeyMaterial.size);
142         HKS_FREE_PTR(privateKeyMaterial.data);
143         return ret;
144     }
145 
146     HksLocalCryptoAbilityInit();
147     ret = HksCryptoHalAgreeKey(&privateKeyMaterial, &publicKeyMaterial, &spec, agreedKey);
148     HKS_IF_NOT_SUCC_LOGE(ret, "local engine agree key failed, ret:%" LOG_PUBLIC "x!", ret)
149 
150     (void)memset_s(privateKeyMaterial.data, privateKeyMaterial.size, 0, privateKeyMaterial.size);
151     HKS_FREE_PTR(privateKeyMaterial.data);
152     (void)memset_s(publicKeyMaterial.data, publicKeyMaterial.size, 0, publicKeyMaterial.size);
153     HKS_FREE_PTR(publicKeyMaterial.data);
154     return ret;
155 }
156 #endif
157 
CipherEncrypt(const struct HksBlob * key,const struct HksParamSet * paramSet,const struct HksUsageSpec * usageSpec,const struct HksBlob * inData,struct HksBlob * outData)158 static int32_t CipherEncrypt(const struct HksBlob *key, const struct HksParamSet *paramSet,
159     const struct HksUsageSpec *usageSpec, const struct HksBlob *inData, struct HksBlob *outData)
160 {
161     struct HksBlob tag = { 0, NULL };
162     int32_t ret = HksGetEncryptAeTag(paramSet, inData, outData, &tag);
163     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "cipher encrypt get ae tag failed!")
164 
165     ret = HksCryptoHalEncrypt(key, usageSpec, inData, outData, &tag);
166     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "cipher encrypt failed!")
167 
168     outData->size += tag.size;
169     return HKS_SUCCESS;
170 }
171 
CheckLocalCipherParams(uint32_t cmdId,const struct HksBlob * key,const struct HksParamSet * paramSet,const struct HksBlob * inputText,struct HksBlob * outputText)172 static int32_t CheckLocalCipherParams(uint32_t cmdId, const struct HksBlob *key, const struct HksParamSet *paramSet,
173     const struct HksBlob *inputText, struct HksBlob *outputText)
174 {
175     HKS_IF_NOT_SUCC_RETURN(HksCheckBlob3AndParamSet(key, inputText, outputText, paramSet), HKS_ERROR_INVALID_ARGUMENT)
176 
177     struct HksParam *outParam = NULL;
178     HKS_IF_NOT_SUCC_LOGE_RETURN(HksGetParam(paramSet, HKS_TAG_ALGORITHM, &outParam),
179         HKS_ERROR_CHECK_GET_ALG_FAIL, "get tag algorithm failed.")
180 
181     uint32_t keySize = 0;
182     if (outParam->uint32Param == HKS_ALG_AES) {
183         keySize = key->size * HKS_BITS_PER_BYTE;
184     } else if (outParam->uint32Param == HKS_ALG_RSA) {
185         const struct KeyMaterialRsa *keyMaterial = (struct KeyMaterialRsa *)key->data;
186         keySize = keyMaterial->keySize;
187     } else {
188         return HKS_ERROR_INVALID_ALGORITHM;
189     }
190 
191     return HksLocalCheckCipherParams(cmdId, keySize, paramSet, inputText, outputText);
192 }
193 
EncryptAndDecrypt(uint32_t cmdId,const struct HksBlob * key,const struct HksParamSet * paramSet,const struct HksBlob * inputText,struct HksBlob * outputText)194 static int32_t EncryptAndDecrypt(uint32_t cmdId, const struct HksBlob *key, const struct HksParamSet *paramSet,
195     const struct HksBlob *inputText, struct HksBlob *outputText)
196 {
197     int32_t ret = CheckLocalCipherParams(cmdId, key, paramSet, inputText, outputText);
198     HKS_IF_NOT_SUCC_RETURN(ret, ret)
199 
200     struct HksUsageSpec *usageSpec = NULL;
201     bool isEncrypt = (cmdId == HKS_CMD_ID_ENCRYPT);
202     struct HksBlob tmpInputText = { inputText->size, inputText->data };
203     ret = HksBuildCipherUsageSpec(paramSet, isEncrypt, &tmpInputText, &usageSpec);
204     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "build cipher usagespec failed, ret:%" LOG_PUBLIC "x!", ret)
205 
206     if (cmdId == HKS_CMD_ID_ENCRYPT) {
207         ret = CipherEncrypt(key, paramSet, usageSpec, &tmpInputText, outputText);
208     } else {
209         ret = HksCryptoHalDecrypt(key, usageSpec, &tmpInputText, outputText);
210     }
211     HksFreeUsageSpec(&usageSpec);
212 
213     HKS_IF_NOT_SUCC_LOGE(ret,
214         "local engine EncryptDecrypt cmdId = %" LOG_PUBLIC "u failed, ret:%" LOG_PUBLIC "x!", cmdId, ret)
215     return ret;
216 }
217 
HksLocalEncrypt(const struct HksBlob * key,const struct HksParamSet * paramSet,const struct HksBlob * plainText,struct HksBlob * cipherText)218 int32_t HksLocalEncrypt(const struct HksBlob *key, const struct HksParamSet *paramSet,
219     const struct HksBlob *plainText, struct HksBlob *cipherText)
220 {
221     HksLocalCryptoAbilityInit();
222     return EncryptAndDecrypt(HKS_CMD_ID_ENCRYPT, key, paramSet, plainText, cipherText);
223 }
224 
HksLocalDecrypt(const struct HksBlob * key,const struct HksParamSet * paramSet,const struct HksBlob * cipherText,struct HksBlob * plainText)225 int32_t HksLocalDecrypt(const struct HksBlob *key, const struct HksParamSet *paramSet,
226     const struct HksBlob *cipherText, struct HksBlob *plainText)
227 {
228     HksLocalCryptoAbilityInit();
229     return EncryptAndDecrypt(HKS_CMD_ID_DECRYPT, key, paramSet, cipherText, plainText);
230 }
231 
HksLocalDeriveKey(const struct HksParamSet * paramSet,const struct HksBlob * mainKey,struct HksBlob * derivedKey)232 int32_t HksLocalDeriveKey(const struct HksParamSet *paramSet, const struct HksBlob *mainKey,
233     struct HksBlob *derivedKey)
234 {
235     HksLocalCryptoAbilityInit();
236     HKS_IF_NOT_SUCC_RETURN(HksCheckBlob2AndParamSet(mainKey, derivedKey, paramSet), HKS_ERROR_INVALID_ARGUMENT)
237 
238     int32_t ret = HksCoreCheckDeriveKeyParams(paramSet, mainKey, derivedKey, true);
239     HKS_IF_NOT_SUCC_RETURN(ret, ret)
240 
241     struct HksKeyDerivationParam derivationParam = { { 0, NULL }, { 0, NULL }, 0, 0 };
242     struct HksKeySpec derivationSpec = { 0, 0, &derivationParam };
243 
244     HksFillKeySpec(paramSet, &derivationSpec);
245     HksFillKeyDerivationParam(paramSet, &derivationParam);
246 
247     return HksCryptoHalDeriveKey(mainKey, &derivationSpec, derivedKey);
248 }
249 
250 #ifndef _CUT_AUTHENTICATE_
CheckLocalSignVerifyParams(uint32_t cmdId,const struct HksBlob * key,const struct HksParamSet * paramSet,const struct HksBlob * srcData,const struct HksBlob * signature)251 static int32_t CheckLocalSignVerifyParams(uint32_t cmdId, const struct HksBlob *key, const struct HksParamSet *paramSet,
252     const struct HksBlob *srcData, const struct HksBlob *signature)
253 {
254     HksLocalCryptoAbilityInit();
255     HKS_IF_NOT_SUCC_RETURN(HksCheckBlob3AndParamSet(key, srcData, signature, paramSet), HKS_ERROR_INVALID_ARGUMENT)
256 
257     struct HksParam *algParam = NULL;
258     int32_t ret = HksGetParam(paramSet, HKS_TAG_ALGORITHM, &algParam);
259     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, HKS_ERROR_CHECK_GET_ALG_FAIL, "get param algorithm failed")
260 
261     uint32_t keySize = 0;
262     if (algParam->uint32Param == HKS_ALG_RSA) {
263         keySize = ((struct KeyMaterialRsa *)key->data)->keySize;
264     } else if (algParam->uint32Param == HKS_ALG_DSA) {
265         keySize = ((struct KeyMaterialDsa *)key->data)->keySize;
266     } else if (algParam->uint32Param == HKS_ALG_ECC) {
267         keySize = ((struct KeyMaterialEcc *)key->data)->keySize;
268     } else if (algParam->uint32Param == HKS_ALG_ED25519) {
269         keySize = key->size * HKS_BITS_PER_BYTE;
270     }
271 
272     ret = HksLocalCheckSignVerifyParams(cmdId, keySize, paramSet, srcData, signature);
273     HKS_IF_NOT_SUCC_RETURN(ret, ret)
274 
275     if (algParam->uint32Param == HKS_ALG_ED25519) {
276         if (key->size != (HKS_CURVE25519_KEY_SIZE_256 / HKS_BITS_PER_BYTE)) {
277             HKS_LOG_E("invalid key size: %" LOG_PUBLIC "u", key->size);
278             return HKS_ERROR_INVALID_KEY_SIZE;
279         }
280 
281         if (signature->size < HKS_SIGNATURE_MIN_SIZE) {
282             HKS_LOG_E("signature size too small, size: %" LOG_PUBLIC "u", signature->size);
283             return HKS_ERROR_INVALID_SIGNATURE_SIZE;
284         }
285     }
286 
287     return HKS_SUCCESS;
288 }
289 
GetSignVerifyMessage(struct HksUsageSpec * usageSpec,const struct HksBlob * srcData,struct HksBlob * message,bool * needFree)290 static int32_t GetSignVerifyMessage(struct HksUsageSpec *usageSpec, const struct HksBlob *srcData,
291     struct HksBlob *message, bool *needFree)
292 {
293     if (HksCheckNeedCache(usageSpec->algType, usageSpec->digest) == HKS_SUCCESS) {
294         message->size = srcData->size;
295         message->data = srcData->data;
296         *needFree = false;
297     } else {
298         message->size = MAX_DEGIST_SIZE;
299         message->data = (uint8_t *)HksMalloc(MAX_DEGIST_SIZE);
300         HKS_IF_NULL_LOGE_RETURN(message->data, HKS_ERROR_MALLOC_FAIL, "SignVerify malloc message data failed!")
301 
302         int32_t ret = HksCryptoHalHash(usageSpec->digest, srcData, message);
303         if (ret != HKS_SUCCESS) {
304             HKS_LOG_E("SignVerify calc hash failed!");
305             HKS_FREE_PTR(message->data);
306             return ret;
307         }
308 
309         *needFree = true;
310     }
311     return HKS_SUCCESS;
312 }
313 
HksLocalSign(const struct HksBlob * key,const struct HksParamSet * paramSet,const struct HksBlob * srcData,struct HksBlob * signature)314 int32_t HksLocalSign(const struct HksBlob *key, const struct HksParamSet *paramSet, const struct HksBlob *srcData,
315     struct HksBlob *signature)
316 {
317     int32_t ret = CheckLocalSignVerifyParams(HKS_CMD_ID_SIGN, key, paramSet, srcData, signature);
318     HKS_IF_NOT_SUCC_RETURN(ret, ret)
319 
320     struct HksUsageSpec usageSpec = {0};
321     HksFillUsageSpec(paramSet, &usageSpec);
322     SetRsaPssSaltLenType(paramSet, &usageSpec);
323     bool needFree = true;
324     struct HksBlob message = { 0, NULL };
325     struct HksBlob keyMaterial = { 0, NULL };
326     do {
327         ret = HksSetKeyToMaterial(usageSpec.algType, false, key, &keyMaterial);
328         HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "set key to material failed, ret:%" LOG_PUBLIC "x!", ret)
329         ret = GetSignVerifyMessage(&usageSpec, srcData, &message, &needFree);
330         HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "SignVerify calc hash failed!")
331 
332         HksLocalCryptoAbilityInit();
333         ret = HksCryptoHalSign(&keyMaterial, &usageSpec, &message, signature);
334         HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "local engine Sign failed, ret:%" LOG_PUBLIC "x!", ret)
335     } while (0);
336 
337     if (keyMaterial.data != NULL) {
338         (void)memset_s(keyMaterial.data, keyMaterial.size, 0, keyMaterial.size);
339         HKS_FREE_PTR(keyMaterial.data);
340     }
341     if (needFree) {
342         HKS_FREE_PTR(message.data);
343     }
344     return ret;
345 }
346 
HksLocalVerify(const struct HksBlob * key,const struct HksParamSet * paramSet,const struct HksBlob * srcData,const struct HksBlob * signature)347 int32_t HksLocalVerify(const struct HksBlob *key, const struct HksParamSet *paramSet, const struct HksBlob *srcData,
348     const struct HksBlob *signature)
349 {
350     int32_t ret = CheckLocalSignVerifyParams(HKS_CMD_ID_VERIFY, key, paramSet, srcData, signature);
351     HKS_IF_NOT_SUCC_RETURN(ret, ret)
352 
353     struct HksUsageSpec usageSpec = {0};
354     HksFillUsageSpec(paramSet, &usageSpec);
355     SetRsaPssSaltLenType(paramSet, &usageSpec);
356     bool needFree = true;
357     struct HksBlob message = { 0, NULL };
358     struct HksBlob keyMaterial = { 0, NULL };
359     do {
360         ret = HksSetKeyToMaterial(usageSpec.algType, true, key, &keyMaterial);
361         HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "set key to material failed, ret:%" LOG_PUBLIC "x!", ret)
362 
363         ret = GetSignVerifyMessage(&usageSpec, srcData, &message, &needFree);
364         HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "SignVerify calc hash failed!")
365 
366         HksLocalCryptoAbilityInit();
367         ret = HksCryptoHalVerify(&keyMaterial, &usageSpec, &message, signature);
368         HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "local engine verify failed, ret:%" LOG_PUBLIC "x!", ret)
369     } while (0);
370 
371     if (needFree) {
372         HKS_FREE_PTR(message.data);
373     }
374     if (keyMaterial.data != NULL) {
375         (void)memset_s(keyMaterial.data, keyMaterial.size, 0, keyMaterial.size);
376         HKS_FREE_PTR(keyMaterial.data);
377     }
378     return ret;
379 }
380 #endif