• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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