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