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