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 #define OPENSSL_NO_DEPRECATED
16
17 #ifdef HKS_CONFIG_FILE
18 #include HKS_CONFIG_FILE
19 #else
20 #include "hks_config.h"
21 #endif
22
23 #ifdef HKS_SUPPORT_SM2_C
24 #include "hks_openssl_sm2.h"
25
26 #include <openssl/bn.h>
27 #include <openssl/core_names.h>
28 #include <openssl/ec.h>
29 #include <openssl/err.h>
30 #include <openssl/evp.h>
31 #include <openssl/obj_mac.h>
32 #include <openssl/ossl_typ.h>
33 #include <openssl/params.h>
34 #include <openssl/param_build.h>
35 #include <openssl/types.h>
36 #include <stdbool.h>
37 #include <stddef.h>
38
39 #include "hks_crypto_hal.h"
40 #include "hks_log.h"
41 #include "hks_mem.h"
42 #include "hks_openssl_ecc.h"
43 #include "hks_openssl_engine.h"
44 #include "hks_openssl_hmac.h"
45 #include "hks_template.h"
46 #include "hks_type.h"
47
48 #include <string.h>
49
50 #include "securec.h"
51
52 #ifdef HKS_SUPPORT_SM2_GENERATE_KEY
EvpPkeyToKeyMaterialEc(const struct HksKeySpec * spec,const EVP_PKEY * pkey,struct HksBlob * key)53 static int32_t EvpPkeyToKeyMaterialEc(const struct HksKeySpec *spec, const EVP_PKEY *pkey, struct HksBlob *key)
54 {
55 struct HksBlob pubXBlob = { 0, NULL };
56 struct HksBlob pubYBlob = { 0, NULL };
57 struct HksBlob privBlob = { 0, NULL };
58 // pubXBlob pubYBlob privBlob length may not be HKS_KEY_BYTES(spec->keyLen)
59 // pubXBlob pubYBlob privBlob length all are not greater than HKS_MAX_KEY_LEN
60 // lengthes have been checked in GetBnBinpadFromPkey
61 int pubXRet = GetBnBinpadFromPkey(pkey, OSSL_PKEY_PARAM_EC_PUB_X, &pubXBlob);
62 int pubYRet = GetBnBinpadFromPkey(pkey, OSSL_PKEY_PARAM_EC_PUB_Y, &pubYBlob);
63 int priRet = GetBnBinpadFromPkey(pkey, OSSL_PKEY_PARAM_PRIV_KEY, &privBlob);
64 int ret = HKS_ERROR_CRYPTO_ENGINE_ERROR;
65 do {
66 if (pubXRet != HKS_SUCCESS || pubYRet != HKS_SUCCESS || priRet != HKS_SUCCESS) {
67 HKS_LOG_E("GetBnBinpadFromPkey failed");
68 break;
69 }
70 uint32_t rawMaterialLen = sizeof(struct KeyMaterialEcc) + pubXBlob.size + pubYBlob.size + privBlob.size;
71 uint8_t *rawMaterial = (uint8_t *)HksMalloc(rawMaterialLen);
72 if (!rawMaterial) {
73 HKS_LOG_E("HksMalloc rawMaterial NULL");
74 ret = HKS_ERROR_INSUFFICIENT_MEMORY;
75 break;
76 }
77 /*
78 * ECC key data internal struct:
79 * struct KeyMaterialEcc + pubX_data + pubY_data + pri_data
80 */
81 struct KeyMaterialEcc *keyMaterial = (struct KeyMaterialEcc *)rawMaterial;
82 keyMaterial->keyAlg = (enum HksKeyAlg)spec->algType;
83 keyMaterial->keySize = spec->keyLen;
84 keyMaterial->xSize = pubXBlob.size;
85 keyMaterial->ySize = pubYBlob.size;
86 keyMaterial->zSize = privBlob.size;
87 uint32_t offset = sizeof(struct KeyMaterialEcc);
88 pubXRet = memcpy_s(rawMaterial + offset, pubXBlob.size, pubXBlob.data, pubXBlob.size);
89 offset += pubXBlob.size;
90 pubYRet = memcpy_s(rawMaterial + offset, pubYBlob.size, pubYBlob.data, pubYBlob.size);
91 offset += pubYBlob.size;
92 priRet = memcpy_s(rawMaterial + offset, privBlob.size, privBlob.data, privBlob.size);
93 if (pubXRet != EOK || pubYRet != EOK || priRet != EOK) {
94 HKS_LOG_E("memcpy_s failed");
95 HKS_FREE(rawMaterial);
96 ret = HKS_ERROR_BAD_STATE;
97 break;
98 }
99 key->data = rawMaterial;
100 key->size = rawMaterialLen;
101 ret = HKS_SUCCESS;
102 } while (false);
103 HKS_FREE(privBlob.data);
104 HKS_FREE(pubXBlob.data);
105 HKS_FREE(pubYBlob.data);
106 return ret;
107 }
108
HksOpensslSm2GenerateKey(const struct HksKeySpec * spec,struct HksBlob * key)109 int32_t HksOpensslSm2GenerateKey(const struct HksKeySpec *spec, struct HksBlob *key)
110 {
111 if (spec->algType != HKS_ALG_SM2) {
112 HKS_LOG_E("not HKS_ALG_SM2 but %" LOG_PUBLIC "u", spec->algType);
113 return HKS_ERROR_INVALID_ARGUMENT;
114 }
115
116 if (spec->keyLen != HKS_SM2_KEY_SIZE_256) {
117 HKS_LOG_E("Sm2 Invalid keyLen %" LOG_PUBLIC "u", spec->keyLen);
118 return HKS_ERROR_INVALID_ARGUMENT;
119 }
120
121 EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_SM2, NULL);
122 if (!ctx) {
123 HKS_LOG_E("ctx NULL %" LOG_PUBLIC "s", ERR_reason_error_string(ERR_get_error()));
124 return HKS_ERROR_CRYPTO_ENGINE_ERROR;
125 }
126 int ret = HKS_ERROR_CRYPTO_ENGINE_ERROR;
127 EVP_PKEY *pkey = NULL;
128 do {
129 int osRet = EVP_PKEY_keygen_init(ctx);
130 if (osRet != HKS_OPENSSL_SUCCESS) {
131 HKS_LOG_E("EVP_PKEY_keygen_init ret = %" LOG_PUBLIC "d %" LOG_PUBLIC "s",
132 osRet, ERR_reason_error_string(ERR_get_error()));
133 break;
134 }
135 osRet = EVP_PKEY_keygen(ctx, &pkey);
136 if (osRet != HKS_OPENSSL_SUCCESS) {
137 HKS_LOG_E("EVP_PKEY_keygen ret = %" LOG_PUBLIC "d %" LOG_PUBLIC "s",
138 osRet, ERR_reason_error_string(ERR_get_error()));
139 break;
140 }
141 ret = EvpPkeyToKeyMaterialEc(spec, pkey, key);
142 if (ret != HKS_SUCCESS) {
143 HKS_LOG_E("EvpPkeyToKeyMaterialEc ret = %" LOG_PUBLIC "d", ret);
144 break;
145 }
146 } while (false);
147 SELF_FREE_PTR(pkey, EVP_PKEY_free)
148 SELF_FREE_PTR(ctx, EVP_PKEY_CTX_free)
149 return ret;
150 }
151 #endif
152
GetSm2Modules(const struct HksBlob * keyBlob,struct KeyMaterialEcc ** out)153 static int GetSm2Modules(const struct HksBlob *keyBlob, struct KeyMaterialEcc **out)
154 {
155 if (CheckBlob(keyBlob) != HKS_SUCCESS) {
156 HKS_LOG_E("invalid keyBlob");
157 return HKS_ERROR_INVALID_ARGUMENT;
158 }
159 if (keyBlob->size < sizeof(struct KeyMaterialEcc)) {
160 HKS_LOG_E("invalid keyBlob size %" LOG_PUBLIC "u", keyBlob->size);
161 return HKS_ERROR_INVALID_ARGUMENT;
162 }
163 struct KeyMaterialEcc *keyMaterial = (struct KeyMaterialEcc *)keyBlob->data;
164 HKS_LOG_I("keySize = %" LOG_PUBLIC "u, xSize = %" LOG_PUBLIC "u, ySize = %" LOG_PUBLIC "u, zSize = %" LOG_PUBLIC
165 "u", keyMaterial->keySize, keyMaterial->xSize, keyMaterial->ySize, keyMaterial->zSize);
166 // if the big number starts with leading zero, then its length will be less than 32, e.g. 31, 30, but not 32,
167 // so we ensure that its length is not greater than 32.
168 if ((keyMaterial->keySize != HKS_SM2_KEY_SIZE_256) ||
169 (keyMaterial->xSize > HKS_KEY_BYTES(keyMaterial->keySize)) ||
170 (keyMaterial->ySize > HKS_KEY_BYTES(keyMaterial->keySize)) ||
171 (keyMaterial->zSize > HKS_KEY_BYTES(keyMaterial->keySize)) ||
172 (sizeof(struct KeyMaterialEcc) + keyMaterial->xSize + keyMaterial->ySize + keyMaterial->zSize !=
173 keyBlob->size)) {
174 HKS_LOG_E("invalid size");
175 return HKS_ERROR_INVALID_ARGUMENT;
176 }
177 if (keyBlob->size < sizeof(struct KeyMaterialEcc) + keyMaterial->xSize + keyMaterial->ySize + keyMaterial->zSize) {
178 HKS_LOG_E("invalid keyBlob size %" LOG_PUBLIC "u", keyBlob->size);
179 return HKS_ERROR_INVALID_ARGUMENT;
180 }
181 *out = keyMaterial;
182 return HKS_SUCCESS;
183 }
184
PushPubKeyToParam(const struct KeyMaterialEcc * material,uint32_t fullSize,uint8_t * uncompressedPublicKey,OSSL_PARAM_BLD * paramBld)185 static int32_t PushPubKeyToParam(const struct KeyMaterialEcc *material,
186 uint32_t fullSize, uint8_t *uncompressedPublicKey, OSSL_PARAM_BLD *paramBld)
187 {
188 HKS_LOG_I("begin PushPubKeyToParam");
189 // https://www.mail-archive.com/openssl-users@openssl.org/msg90185.html
190 // Unfortunately supplying x and y separately is not supported for import.
191 // You have to instead use OSSL_PKEY_PARAM_PUB_KEY.
192 // You can supply the key as an uncompressed public key simply be concatenating the byte "04",
193 // the x co-ord (padded to the appropriate size if necessary) and the y co-cord (also padded as appropriate).
194
195 // NOTICE! x size and y size are smaller than or equal to HKS_KEY_BYTES(material->keySize)
196 // e.g. assuming that HKS_KEY_BYTES(material->keySize) is 32, x size might be 32, 31, 30, etc.
197 uncompressedPublicKey[0] = POINT_CONVERSION_UNCOMPRESSED;
198 errno_t memRet = memcpy_s(
199 uncompressedPublicKey + 1 + HKS_KEY_BYTES(material->keySize) - material->xSize, material->xSize,
200 (const uint8_t *)(material) + sizeof(struct KeyMaterialEcc), material->xSize);
201 if (memRet != EOK) {
202 HKS_LOG_E("copy x fail");
203 return HKS_ERROR_BAD_STATE;
204 }
205 memRet = memcpy_s(uncompressedPublicKey + fullSize - material->ySize, material->ySize,
206 (const uint8_t *)(material) + sizeof(struct KeyMaterialEcc) + material->xSize, material->ySize);
207 if (memRet != EOK) {
208 HKS_LOG_E("copy y fail");
209 return HKS_ERROR_BAD_STATE;
210 }
211 int osRet = OSSL_PARAM_BLD_push_octet_string(paramBld, OSSL_PKEY_PARAM_PUB_KEY,
212 uncompressedPublicKey, fullSize);
213 if (osRet != HKS_OPENSSL_SUCCESS) {
214 HKS_LOG_E("OSSL_PARAM_BLD_push_octet_string failed %" LOG_PUBLIC "d", osRet);
215 HksLogOpensslError();
216 return HKS_ERROR_BAD_STATE;
217 }
218 return HKS_SUCCESS;
219 }
220
221 // Notice: you must call OSSL_PARAM_free after using the return value.
ConstructSm2ParamsFromRawKey(const struct KeyMaterialEcc * material,enum HksKeyPurpose keyPurpose)222 static OSSL_PARAM *ConstructSm2ParamsFromRawKey(const struct KeyMaterialEcc *material, enum HksKeyPurpose keyPurpose)
223 {
224 // publicXSize publicYSize privateSize lengthes all are not greater than HKS_MAX_KEY_LEN
225 // have been checked in GetSm2Modules
226 OSSL_PARAM_BLD *paramBld = OSSL_PARAM_BLD_new();
227 HKS_IF_NULL_LOGE_RETURN(paramBld, NULL, "OSSL_PARAM_BLD_new failed")
228 OSSL_PARAM *params = NULL;
229 uint8_t *uncompressedPublicKey = NULL;
230 BIGNUM *priBn = NULL;
231 do {
232 int ret = OSSL_PARAM_BLD_push_utf8_string(paramBld, OSSL_PKEY_PARAM_GROUP_NAME, SN_sm2, 0);
233 if (ret != HKS_OPENSSL_SUCCESS) {
234 HKS_LOG_E("OSSL_PARAM_BLD_push_utf8_string failed %" LOG_PUBLIC "d", ret);
235 HksLogOpensslError();
236 break;
237 }
238
239 // push public key if it is present
240 if (material->xSize != 0 && material->ySize != 0) {
241 // sizes have been checked in GetSm2Modules
242 uint32_t fullSize = 1 + HKS_KEY_BYTES(material->keySize) + HKS_KEY_BYTES(material->keySize);
243 uncompressedPublicKey = HksMalloc(fullSize);
244 HKS_IF_NULL_LOGE_BREAK(uncompressedPublicKey, "uncompressedPublicKey HksMalloc NULL")
245 ret = PushPubKeyToParam(material, fullSize, uncompressedPublicKey, paramBld);
246 HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "PushPubKeyToParam failed %" LOG_PUBLIC "d", ret)
247 }
248
249 // push private key if required
250 if ((keyPurpose == HKS_KEY_PURPOSE_DECRYPT) || (keyPurpose == HKS_KEY_PURPOSE_SIGN)) {
251 if (material->zSize == 0) {
252 HKS_LOG_E("decrypt or sign but private key empty");
253 break;
254 }
255 priBn = BN_bin2bn((const uint8_t *)(material) + sizeof(struct KeyMaterialEcc) +
256 material->xSize + material->ySize, material->zSize, NULL);
257 HKS_IF_NULL_LOGE_BREAK(priBn, "BN_bin2bn fail%" LOG_PUBLIC "s", ERR_reason_error_string(ERR_get_error()))
258 ret = OSSL_PARAM_BLD_push_BN(paramBld, OSSL_PKEY_PARAM_PRIV_KEY, priBn);
259 if (ret != HKS_OPENSSL_SUCCESS) {
260 HKS_LOG_E("OSSL_PARAM_BLD_push_BN failed %" LOG_PUBLIC "d", ret);
261 break;
262 }
263 }
264
265 params = OSSL_PARAM_BLD_to_param(paramBld);
266 HKS_IF_NULL_LOGE_BREAK(params, "OSSL_PARAM_BLD_to_param fail %" LOG_PUBLIC "s",
267 ERR_reason_error_string(ERR_get_error()))
268 } while (0);
269 SELF_FREE_PTR(paramBld, OSSL_PARAM_BLD_free)
270 HKS_FREE(uncompressedPublicKey);
271 BN_free(priBn);
272 return params;
273 }
274
Sm2InitKey(const struct HksBlob * keyBlob,enum HksKeyPurpose keyPurpose)275 static EVP_PKEY *Sm2InitKey(const struct HksBlob *keyBlob, enum HksKeyPurpose keyPurpose)
276 {
277 /* get ecc pubX,pubY,pri */
278 struct KeyMaterialEcc *keyMaterial = NULL;
279
280 HKS_IF_NOT_SUCC_LOGE_RETURN(GetSm2Modules(keyBlob, &keyMaterial),
281 NULL, "get sm2 key modules is failed")
282
283 EVP_PKEY *sm2EvpPkey = NULL;
284 HKS_LOG_I("begin ConstructSm2ParamsFromRawKey");
285 OSSL_PARAM *params = ConstructSm2ParamsFromRawKey(keyMaterial, keyPurpose);
286 if (params == NULL) {
287 HKS_LOG_E("ConstructSm2ParamsFromRawKey failed");
288 return NULL;
289 }
290 do {
291 EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(NID_sm2, NULL);
292 if (ctx == NULL) {
293 HKS_LOG_E("EVP_PKEY_CTX_new_id failed");
294 HksLogOpensslError();
295 break;
296 }
297 int ret = EVP_PKEY_fromdata_init(ctx);
298 if (ret != HKS_OPENSSL_SUCCESS) {
299 HKS_LOG_E("EVP_PKEY_fromdata_init failed %" LOG_PUBLIC "d", ret);
300 HksLogOpensslError();
301 SELF_FREE_PTR(ctx, EVP_PKEY_CTX_free)
302 break;
303 }
304 if (keyPurpose == HKS_KEY_PURPOSE_DECRYPT || keyPurpose == HKS_KEY_PURPOSE_SIGN) {
305 HKS_LOG_I("selection is EVP_PKEY_KEYPAIR");
306 ret = EVP_PKEY_fromdata(ctx, &sm2EvpPkey, EVP_PKEY_KEYPAIR, params);
307 } else {
308 HKS_LOG_I("selection is EVP_PKEY_PUBLIC_KEY");
309 ret = EVP_PKEY_fromdata(ctx, &sm2EvpPkey, EVP_PKEY_PUBLIC_KEY, params);
310 }
311 if (ret != HKS_OPENSSL_SUCCESS) {
312 HKS_LOG_E("EVP_PKEY_fromdata failed %" LOG_PUBLIC "d, %" LOG_PUBLIC "s",
313 ret, ERR_reason_error_string(ERR_get_error()));
314 SELF_FREE_PTR(ctx, EVP_PKEY_CTX_free)
315 SELF_FREE_PTR(sm2EvpPkey, EVP_PKEY_free)
316 break;
317 }
318 } while (false);
319 SELF_FREE_PTR(params, OSSL_PARAM_free)
320 return sm2EvpPkey;
321 }
322
SetDigestIfNeeded(enum HksKeyPurpose keyPurpose,uint32_t digest,const struct HksBlob * message,EVP_PKEY_CTX * ctx)323 static int32_t SetDigestIfNeeded(enum HksKeyPurpose keyPurpose, uint32_t digest, const struct HksBlob *message,
324 EVP_PKEY_CTX *ctx)
325 {
326 if (!((keyPurpose == HKS_KEY_PURPOSE_SIGN) || (keyPurpose == HKS_KEY_PURPOSE_VERIFY))) {
327 return HKS_SUCCESS;
328 }
329 const EVP_MD *opensslAlg = GetOpensslAlg(digest);
330 if (opensslAlg != NULL) {
331 HKS_LOG_I("selected EVP_MD name = %" LOG_PUBLIC "s", EVP_MD_get0_name(opensslAlg));
332 int osRet = EVP_PKEY_CTX_set_signature_md(ctx, opensslAlg);
333 if (osRet != HKS_OPENSSL_SUCCESS) {
334 HKS_LOG_E("set digest type failed %" LOG_PUBLIC "d", osRet);
335 HksLogOpensslError();
336 return HKS_ERROR_CRYPTO_ENGINE_ERROR;
337 } else {
338 return HKS_SUCCESS;
339 }
340 } else if (digest != HKS_DIGEST_NONE || message == NULL) {
341 HKS_LOG_E("unknown digest %" LOG_PUBLIC "u", digest);
342 return HKS_ERROR_INVALID_ARGUMENT;
343 } else if (message->size != HKS_DIGEST_SM3_LEN) {
344 HKS_LOG_E("digest is none but message size %" LOG_PUBLIC "u is not sm3 digest len!", message->size);
345 return HKS_ERROR_INVALID_ARGUMENT;
346 } else {
347 // the default digest for sm2 is sm3, so we don't need to set it.
348 HKS_LOG_I("digest is none and message size is sm3 digest len");
349 return HKS_SUCCESS;
350 }
351 }
352
353 #ifdef HKS_SUPPORT_SM2_SIGN_VERIFY
InitSm2Ctx(const struct HksBlob * mainKey,uint32_t digest,enum HksKeyPurpose keyPurpose,const struct HksBlob * message)354 static EVP_PKEY_CTX *InitSm2Ctx(const struct HksBlob *mainKey, uint32_t digest, enum HksKeyPurpose keyPurpose,
355 const struct HksBlob *message)
356 {
357 EVP_PKEY *key = Sm2InitKey(mainKey, keyPurpose);
358 HKS_IF_NULL_LOGE_RETURN(key, NULL, "initialize sm2 key failed")
359
360 int32_t ret = HKS_ERROR_CRYPTO_ENGINE_ERROR;
361 EVP_PKEY_CTX *ctx = NULL;
362 do {
363 ctx = EVP_PKEY_CTX_new(key, NULL);
364 HKS_IF_NULL_LOGE_BREAK(ctx, "new ctx failed")
365 int osRet = 0; // set fail for default case
366 switch (keyPurpose) {
367 case HKS_KEY_PURPOSE_SIGN:
368 osRet = EVP_PKEY_sign_init(ctx);
369 break;
370 case HKS_KEY_PURPOSE_VERIFY:
371 osRet = EVP_PKEY_verify_init(ctx);
372 break;
373 case HKS_KEY_PURPOSE_ENCRYPT:
374 osRet = EVP_PKEY_encrypt_init(ctx);
375 break;
376 case HKS_KEY_PURPOSE_DECRYPT:
377 osRet = EVP_PKEY_decrypt_init(ctx);
378 break;
379 default:
380 HKS_LOG_E("Not supported actionCode for SM2 keypair in huks!");
381 break;
382 }
383 if (osRet != HKS_OPENSSL_SUCCESS) {
384 HKS_LOG_E("EVP_PKEY sign/verify/encrypt/decrypt init failed %" LOG_PUBLIC "d", osRet);
385 HksLogOpensslError();
386 break;
387 }
388 HKS_LOG_I("init ok");
389 ret = SetDigestIfNeeded(keyPurpose, digest, message, ctx);
390 if (ret != HKS_SUCCESS) {
391 HKS_LOG_E("SetDigestIfNeeded failed %" LOG_PUBLIC "d", ret);
392 break;
393 }
394 } while (0);
395 SELF_FREE_PTR(key, EVP_PKEY_free)
396 if (ret != HKS_SUCCESS) {
397 HKS_LOG_E("init ctx fail");
398 HksLogOpensslError();
399 SELF_FREE_PTR(ctx, EVP_PKEY_CTX_free)
400 return NULL;
401 }
402 return ctx;
403 }
404
HksOpensslSm2Verify(const struct HksBlob * key,const struct HksUsageSpec * usageSpec,const struct HksBlob * message,const struct HksBlob * signature)405 int32_t HksOpensslSm2Verify(const struct HksBlob *key, const struct HksUsageSpec *usageSpec,
406 const struct HksBlob *message, const struct HksBlob *signature)
407 {
408 if (CheckBlob(message) != HKS_SUCCESS || CheckBlob(signature) != HKS_SUCCESS) {
409 HKS_LOG_E("sm sign invalid arg");
410 return HKS_ERROR_INVALID_ARGUMENT;
411 }
412 HKS_LOG_I("sm2 verify");
413 EVP_PKEY_CTX *ctx = InitSm2Ctx(key, usageSpec->digest, usageSpec->purpose, message);
414 HKS_IF_NULL_LOGE_RETURN(ctx, HKS_ERROR_INVALID_KEY_INFO, "initialize sm2 context failed")
415
416 if (EVP_PKEY_verify(ctx, signature->data, signature->size, message->data, message->size) != HKS_OPENSSL_SUCCESS) {
417 HKS_LOG_D("verify data failed");
418 HksLogOpensslError();
419 SELF_FREE_PTR(ctx, EVP_PKEY_CTX_free)
420 return HKS_ERROR_CRYPTO_ENGINE_ERROR;
421 }
422
423 SELF_FREE_PTR(ctx, EVP_PKEY_CTX_free)
424 return HKS_SUCCESS;
425 }
426
HksOpensslSm2Sign(const struct HksBlob * key,const struct HksUsageSpec * usageSpec,const struct HksBlob * message,struct HksBlob * signature)427 int32_t HksOpensslSm2Sign(const struct HksBlob *key, const struct HksUsageSpec *usageSpec,
428 const struct HksBlob *message, struct HksBlob *signature)
429 {
430 if (CheckBlob(message) != HKS_SUCCESS || CheckBlob(signature) != HKS_SUCCESS) {
431 HKS_LOG_E("sm sign invalid arg");
432 return HKS_ERROR_INVALID_ARGUMENT;
433 }
434 HKS_LOG_I("sm2 sign");
435 EVP_PKEY_CTX *ctx = InitSm2Ctx(key, usageSpec->digest, usageSpec->purpose, message);
436 HKS_IF_NULL_LOGE_RETURN(ctx, HKS_ERROR_INVALID_KEY_INFO, "initialize sm2 context failed")
437
438 int32_t ret = HKS_ERROR_CRYPTO_ENGINE_ERROR;
439 do {
440 size_t sigSize = 0;
441 int osRet = EVP_PKEY_sign(ctx, NULL, &sigSize, message->data, message->size);
442 if (osRet != HKS_OPENSSL_SUCCESS) {
443 HKS_LOG_E("get sigSize failed osRet = %" LOG_PUBLIC "d %" LOG_PUBLIC "s",
444 osRet, ERR_reason_error_string(ERR_get_error()));
445 break;
446 }
447
448 if (signature->size < sigSize) {
449 HKS_LOG_E("out size too small %" LOG_PUBLIC "u < %" LOG_PUBLIC "zu", signature->size, sigSize);
450 ret = HKS_ERROR_BUFFER_TOO_SMALL;
451 break;
452 }
453
454 osRet = EVP_PKEY_sign(ctx, signature->data, &sigSize, message->data, message->size);
455 if (osRet != HKS_OPENSSL_SUCCESS) {
456 HKS_LOG_E("sign data failed osRet = %" LOG_PUBLIC "d %" LOG_PUBLIC "s",
457 osRet, ERR_reason_error_string(ERR_get_error()));
458 break;
459 }
460 signature->size = (uint32_t)sigSize;
461 ret = HKS_SUCCESS;
462 } while (false);
463 SELF_FREE_PTR(ctx, EVP_PKEY_CTX_free)
464 return ret;
465 }
466 #endif
467
468 #ifdef HKS_SUPPORT_SM2_ENCRYPT_DECRYPT
HksOpensslSm2Encrypt(const struct HksBlob * keyPair,const struct HksUsageSpec * usageSpec,const struct HksBlob * plainBlob,struct HksBlob * cipherBlob)469 int HksOpensslSm2Encrypt(const struct HksBlob *keyPair, const struct HksUsageSpec *usageSpec,
470 const struct HksBlob *plainBlob, struct HksBlob *cipherBlob)
471 {
472 HKS_LOG_I("sm2 encrypt");
473 EVP_PKEY_CTX *ctx = InitSm2Ctx(keyPair, usageSpec->digest, HKS_KEY_PURPOSE_ENCRYPT, NULL);
474 HKS_IF_NULL_LOGE_RETURN(ctx, HKS_ERROR_INVALID_KEY_INFO, "initialize sm2 context when encrypt failed!")
475 // cipherLength equals c1||c2||c3 which c1 and c3 is fixed length and c2 is equals to the plainText.
476 size_t cipherSize = plainBlob->size + SM2_C1_SIZE + SM2_C3_SIZE;
477 if (EVP_PKEY_encrypt(ctx, cipherBlob->data, &cipherSize, plainBlob->data,
478 (size_t)plainBlob->size) != HKS_OPENSSL_SUCCESS) {
479 HKS_LOG_E("encrypt data failed");
480 HksLogOpensslError();
481 SELF_FREE_PTR(ctx, EVP_PKEY_CTX_free)
482 return HKS_ERROR_CRYPTO_ENGINE_ERROR;
483 }
484 cipherBlob->size = (uint32_t)cipherSize;
485 SELF_FREE_PTR(ctx, EVP_PKEY_CTX_free)
486 return HKS_SUCCESS;
487 }
488
HksOpensslSm2Decrypt(const struct HksBlob * keyPair,const struct HksUsageSpec * usageSpec,const struct HksBlob * cipherBlob,struct HksBlob * plainBlob)489 int HksOpensslSm2Decrypt(const struct HksBlob *keyPair, const struct HksUsageSpec *usageSpec,
490 const struct HksBlob *cipherBlob, struct HksBlob *plainBlob)
491 {
492 HKS_LOG_I("sm2 decrypt");
493 if (usageSpec == NULL) {
494 HKS_LOG_E("Invalid param");
495 return HKS_ERROR_CRYPTO_ENGINE_ERROR;
496 }
497 HKS_IF_NOT_SUCC_LOGE_RETURN(HksOpensslCheckBlob(cipherBlob),
498 HKS_ERROR_INVALID_ARGUMENT, "Invalid param cipherBlob!");
499 HKS_IF_NOT_SUCC_LOGE_RETURN(HksOpensslCheckBlob(plainBlob), HKS_ERROR_INVALID_ARGUMENT, "Invalid param plainBlob!");
500 EVP_PKEY_CTX *ctx = InitSm2Ctx(keyPair, usageSpec->digest, HKS_KEY_PURPOSE_DECRYPT, NULL);
501 HKS_IF_NULL_LOGE_RETURN(ctx, HKS_ERROR_INVALID_KEY_INFO, "initialize sm2 context when decrypt failed!")
502 size_t decryptSize = plainBlob->size;
503 if (EVP_PKEY_decrypt(ctx, plainBlob->data, &decryptSize, cipherBlob->data,
504 cipherBlob->size) != HKS_OPENSSL_SUCCESS) {
505 HKS_LOG_E("decrypt data failed");
506 HksLogOpensslError();
507 SELF_FREE_PTR(ctx, EVP_PKEY_CTX_free)
508 return HKS_ERROR_CRYPTO_ENGINE_ERROR;
509 }
510 plainBlob->size = (uint32_t)decryptSize;
511 SELF_FREE_PTR(ctx, EVP_PKEY_CTX_free)
512 return HKS_SUCCESS;
513 }
514 #endif //HKS_SUPPORT_SM2_ENCRYPT_DECRYPT
515
516 #endif
517