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