xref: /openbsd/lib/libcrypto/sm2/sm2_crypt.c (revision aeeaa6d4)
1 /*	$OpenBSD: sm2_crypt.c,v 1.3 2024/02/09 07:43:52 tb Exp $ */
2 /*
3  * Copyright (c) 2017, 2019 Ribose Inc
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #ifndef OPENSSL_NO_SM2
19 
20 #include <string.h>
21 
22 #include <openssl/asn1.h>
23 #include <openssl/asn1t.h>
24 #include <openssl/bn.h>
25 #include <openssl/err.h>
26 #include <openssl/evp.h>
27 #include <openssl/sm2.h>
28 
29 #include "sm2_local.h"
30 
31 typedef struct SM2_Ciphertext_st SM2_Ciphertext;
32 
33 SM2_Ciphertext *SM2_Ciphertext_new(void);
34 void SM2_Ciphertext_free(SM2_Ciphertext *a);
35 SM2_Ciphertext *d2i_SM2_Ciphertext(SM2_Ciphertext **a, const unsigned char **in,
36     long len);
37 int i2d_SM2_Ciphertext(SM2_Ciphertext *a, unsigned char **out);
38 
39 struct SM2_Ciphertext_st {
40 	BIGNUM *C1x;
41 	BIGNUM *C1y;
42 	ASN1_OCTET_STRING *C3;
43 	ASN1_OCTET_STRING *C2;
44 };
45 
46 static const ASN1_TEMPLATE SM2_Ciphertext_seq_tt[] = {
47 	{
48 		.flags = 0,
49 		.tag = 0,
50 		.offset = offsetof(SM2_Ciphertext, C1x),
51 		.field_name = "C1x",
52 		.item = &BIGNUM_it,
53 	},
54 	{
55 		.flags = 0,
56 		.tag = 0,
57 		.offset = offsetof(SM2_Ciphertext, C1y),
58 		.field_name = "C1y",
59 		.item = &BIGNUM_it,
60 	},
61 	{
62 		.flags = 0,
63 		.tag = 0,
64 		.offset = offsetof(SM2_Ciphertext, C3),
65 		.field_name = "C3",
66 		.item = &ASN1_OCTET_STRING_it,
67 	},
68 	{
69 		.flags = 0,
70 		.tag = 0,
71 		.offset = offsetof(SM2_Ciphertext, C2),
72 		.field_name = "C2",
73 		.item = &ASN1_OCTET_STRING_it,
74 	},
75 };
76 
77 const ASN1_ITEM SM2_Ciphertext_it = {
78 	.itype = ASN1_ITYPE_SEQUENCE,
79 	.utype = V_ASN1_SEQUENCE,
80 	.templates = SM2_Ciphertext_seq_tt,
81 	.tcount = sizeof(SM2_Ciphertext_seq_tt) / sizeof(ASN1_TEMPLATE),
82 	.funcs = NULL,
83 	.size = sizeof(SM2_Ciphertext),
84 	.sname = "SM2_Ciphertext",
85 };
86 
87 SM2_Ciphertext *
d2i_SM2_Ciphertext(SM2_Ciphertext ** a,const unsigned char ** in,long len)88 d2i_SM2_Ciphertext(SM2_Ciphertext **a, const unsigned char **in, long len)
89 {
90 	return (SM2_Ciphertext *) ASN1_item_d2i((ASN1_VALUE **)a, in, len,
91 	    &SM2_Ciphertext_it);
92 }
93 
94 int
i2d_SM2_Ciphertext(SM2_Ciphertext * a,unsigned char ** out)95 i2d_SM2_Ciphertext(SM2_Ciphertext *a, unsigned char **out)
96 {
97 	return ASN1_item_i2d((ASN1_VALUE *)a, out, &SM2_Ciphertext_it);
98 }
99 
100 SM2_Ciphertext *
SM2_Ciphertext_new(void)101 SM2_Ciphertext_new(void)
102 {
103 	return (SM2_Ciphertext *)ASN1_item_new(&SM2_Ciphertext_it);
104 }
105 
106 void
SM2_Ciphertext_free(SM2_Ciphertext * a)107 SM2_Ciphertext_free(SM2_Ciphertext *a)
108 {
109 	ASN1_item_free((ASN1_VALUE *)a, &SM2_Ciphertext_it);
110 }
111 
112 static size_t
ec_field_size(const EC_GROUP * group)113 ec_field_size(const EC_GROUP *group)
114 {
115 	/* Is there some simpler way to do this? */
116 	BIGNUM *p;
117 	size_t field_size = 0;
118 
119 	if ((p = BN_new()) == NULL)
120 		goto err;
121 	if (!EC_GROUP_get_curve(group, p, NULL, NULL, NULL))
122 		goto err;
123 	field_size = BN_num_bytes(p);
124  err:
125 	BN_free(p);
126 	return field_size;
127 }
128 
129 int
SM2_plaintext_size(const EC_KEY * key,const EVP_MD * digest,size_t msg_len,size_t * pl_size)130 SM2_plaintext_size(const EC_KEY *key, const EVP_MD *digest, size_t msg_len,
131     size_t *pl_size)
132 {
133 	size_t field_size, overhead;
134 	int md_size;
135 
136 	if ((field_size = ec_field_size(EC_KEY_get0_group(key))) == 0) {
137 		SM2error(SM2_R_INVALID_FIELD);
138 		return 0;
139 	}
140 
141 	if ((md_size = EVP_MD_size(digest)) < 0) {
142 		SM2error(SM2_R_INVALID_DIGEST);
143 		return 0;
144 	}
145 
146 	overhead = 10 + 2 * field_size + md_size;
147 	if (msg_len <= overhead) {
148 		SM2error(SM2_R_INVALID_ARGUMENT);
149 		return 0;
150 	}
151 
152 	*pl_size = msg_len - overhead;
153 	return 1;
154 }
155 
156 int
SM2_ciphertext_size(const EC_KEY * key,const EVP_MD * digest,size_t msg_len,size_t * c_size)157 SM2_ciphertext_size(const EC_KEY *key, const EVP_MD *digest, size_t msg_len,
158     size_t *c_size)
159 {
160 	size_t asn_size, field_size;
161 	int md_size;
162 
163 	if ((field_size = ec_field_size(EC_KEY_get0_group(key))) == 0) {
164 		SM2error(SM2_R_INVALID_FIELD);
165 		return 0;
166 	}
167 
168 	if ((md_size = EVP_MD_size(digest)) < 0) {
169 		SM2error(SM2_R_INVALID_DIGEST);
170 		return 0;
171 	}
172 
173 	asn_size = 2 * ASN1_object_size(0, field_size + 1, V_ASN1_INTEGER) +
174 	    ASN1_object_size(0, md_size, V_ASN1_OCTET_STRING) +
175 	    ASN1_object_size(0, msg_len, V_ASN1_OCTET_STRING);
176 
177 	*c_size = ASN1_object_size(1, asn_size, V_ASN1_SEQUENCE);
178 	return 1;
179 }
180 
181 int
sm2_kdf(uint8_t * key,size_t key_len,uint8_t * secret,size_t secret_len,const EVP_MD * digest)182 sm2_kdf(uint8_t *key, size_t key_len, uint8_t *secret, size_t secret_len,
183     const EVP_MD *digest)
184 {
185 	EVP_MD_CTX *hash;
186 	uint8_t *hash_buf = NULL;
187 	uint32_t ctr = 1;
188 	uint8_t ctr_buf[4] = {0};
189 	size_t hadd, hlen;
190 	int rc = 0;
191 
192 	if ((hash = EVP_MD_CTX_new()) == NULL) {
193 		SM2error(ERR_R_MALLOC_FAILURE);
194 		goto err;
195 	}
196 
197 	if ((hlen = EVP_MD_size(digest)) < 0) {
198 		SM2error(SM2_R_INVALID_DIGEST);
199 		goto err;
200 	}
201 	if ((hash_buf = malloc(hlen)) == NULL) {
202 		SM2error(ERR_R_MALLOC_FAILURE);
203 		goto err;
204 	}
205 
206 	while ((key_len > 0) && (ctr != 0)) {
207 		if (!EVP_DigestInit_ex(hash, digest, NULL)) {
208 			SM2error(ERR_R_EVP_LIB);
209 			goto err;
210 		}
211 		if (!EVP_DigestUpdate(hash, secret, secret_len)) {
212 			SM2error(ERR_R_EVP_LIB);
213 			goto err;
214 		}
215 
216 		/* big-endian counter representation */
217 		ctr_buf[0] = (ctr >> 24) & 0xff;
218 		ctr_buf[1] = (ctr >> 16) & 0xff;
219 		ctr_buf[2] = (ctr >> 8) & 0xff;
220 		ctr_buf[3] = ctr & 0xff;
221 		ctr++;
222 
223 		if (!EVP_DigestUpdate(hash, ctr_buf, 4)) {
224 			SM2error(ERR_R_EVP_LIB);
225 			goto err;
226 		}
227 		if (!EVP_DigestFinal(hash, hash_buf, NULL)) {
228 			SM2error(ERR_R_EVP_LIB);
229 			goto err;
230 		}
231 
232 		hadd = key_len > hlen ? hlen : key_len;
233 		memcpy(key, hash_buf, hadd);
234 		memset(hash_buf, 0, hlen);
235 		key_len -= hadd;
236 		key += hadd;
237 	}
238 
239 	rc = 1;
240  err:
241 	free(hash_buf);
242 	EVP_MD_CTX_free(hash);
243 	return rc;
244 }
245 
246 int
SM2_encrypt(const EC_KEY * key,const EVP_MD * digest,const uint8_t * msg,size_t msg_len,uint8_t * ciphertext_buf,size_t * ciphertext_len)247 SM2_encrypt(const EC_KEY *key, const EVP_MD *digest, const uint8_t *msg,
248     size_t msg_len, uint8_t *ciphertext_buf, size_t *ciphertext_len)
249 {
250 	SM2_Ciphertext ctext_struct;
251 	EVP_MD_CTX *hash = NULL;
252 	BN_CTX *ctx = NULL;
253 	BIGNUM *order = NULL;
254 	BIGNUM *k, *x1, *y1, *x2, *y2;
255 	const EC_GROUP *group;
256 	const EC_POINT *P;
257 	EC_POINT *kG = NULL, *kP = NULL;
258 	uint8_t *msg_mask = NULL, *x2y2 = NULL, *C3 = NULL;
259 	size_t C3_size, field_size, i, x2size, y2size;
260 	int rc = 0;
261 	int clen;
262 
263 	ctext_struct.C2 = NULL;
264 	ctext_struct.C3 = NULL;
265 
266 	if ((hash = EVP_MD_CTX_new()) == NULL) {
267 		SM2error(ERR_R_MALLOC_FAILURE);
268 		goto err;
269 	}
270 
271 	if ((group = EC_KEY_get0_group(key)) == NULL) {
272 		SM2error(SM2_R_INVALID_KEY);
273 		goto err;
274 	}
275 
276 	if ((order = BN_new()) == NULL) {
277 		SM2error(ERR_R_MALLOC_FAILURE);
278 		goto err;
279 	}
280 
281 	if (!EC_GROUP_get_order(group, order, NULL)) {
282 		SM2error(SM2_R_INVALID_GROUP_ORDER);
283 		goto err;
284 	}
285 
286 	if ((P = EC_KEY_get0_public_key(key)) == NULL) {
287 		SM2error(SM2_R_INVALID_KEY);
288 		goto err;
289 	}
290 
291 	if ((field_size = ec_field_size(group)) == 0) {
292 		SM2error(SM2_R_INVALID_FIELD);
293 		goto err;
294 	}
295 
296 	if ((C3_size = EVP_MD_size(digest)) < 0) {
297 		SM2error(SM2_R_INVALID_DIGEST);
298 		goto err;
299 	}
300 
301 	if ((kG = EC_POINT_new(group)) == NULL) {
302 		SM2error(ERR_R_MALLOC_FAILURE);
303 		goto err;
304 	}
305 	if ((kP = EC_POINT_new(group)) == NULL) {
306 		SM2error(ERR_R_MALLOC_FAILURE);
307 		goto err;
308 	}
309 
310 	if ((ctx = BN_CTX_new()) == NULL) {
311 		SM2error(ERR_R_MALLOC_FAILURE);
312 		goto err;
313 	}
314 
315 	BN_CTX_start(ctx);
316 	if ((k = BN_CTX_get(ctx)) == NULL) {
317 		SM2error(ERR_R_BN_LIB);
318 		goto err;
319 	}
320 	if ((x1 = BN_CTX_get(ctx)) == NULL) {
321 		SM2error(ERR_R_BN_LIB);
322 		goto err;
323 	}
324 	if ((x2 = BN_CTX_get(ctx)) == NULL) {
325 		SM2error(ERR_R_BN_LIB);
326 		goto err;
327 	}
328 	if ((y1 = BN_CTX_get(ctx)) == NULL) {
329 		SM2error(ERR_R_BN_LIB);
330 		goto err;
331 	}
332 	if ((y2 = BN_CTX_get(ctx)) == NULL) {
333 		SM2error(ERR_R_BN_LIB);
334 		goto err;
335 	}
336 
337 	if ((x2y2 = calloc(2, field_size)) == NULL) {
338 		SM2error(ERR_R_MALLOC_FAILURE);
339 		goto err;
340 	}
341 
342 	if ((C3 = calloc(1, C3_size)) == NULL) {
343 		SM2error(ERR_R_MALLOC_FAILURE);
344 		goto err;
345 	}
346 
347 	memset(ciphertext_buf, 0, *ciphertext_len);
348 
349 	if (!BN_rand_range(k, order)) {
350 		SM2error(SM2_R_RANDOM_NUMBER_GENERATION_FAILED);
351 		goto err;
352 	}
353 
354 	if (!EC_POINT_mul(group, kG, k, NULL, NULL, ctx)) {
355 		SM2error(ERR_R_EC_LIB);
356 		goto err;
357 	}
358 
359 	if (!EC_POINT_get_affine_coordinates(group, kG, x1, y1, ctx)) {
360 		SM2error(ERR_R_EC_LIB);
361 		goto err;
362 	}
363 
364 	if (!EC_POINT_mul(group, kP, NULL, P, k, ctx)) {
365 		SM2error(ERR_R_EC_LIB);
366 		goto err;
367 	}
368 
369 	if (!EC_POINT_get_affine_coordinates(group, kP, x2, y2, ctx)) {
370 		SM2error(ERR_R_EC_LIB);
371 		goto err;
372 	}
373 
374 	if ((x2size = BN_num_bytes(x2)) > field_size ||
375 	    (y2size = BN_num_bytes(y2)) > field_size) {
376 		SM2error(SM2_R_BIGNUM_OUT_OF_RANGE);
377 		goto err;
378 	}
379 
380 	BN_bn2bin(x2, x2y2 + field_size - x2size);
381 	BN_bn2bin(y2, x2y2 + 2 * field_size - y2size);
382 
383 	if ((msg_mask = calloc(1, msg_len)) == NULL) {
384 		SM2error(ERR_R_MALLOC_FAILURE);
385 		goto err;
386 	}
387 
388 	if (!sm2_kdf(msg_mask, msg_len, x2y2, 2 * field_size, digest)) {
389 		SM2error(SM2_R_KDF_FAILURE);
390 		goto err;
391 	}
392 
393 	for (i = 0; i != msg_len; i++)
394 		msg_mask[i] ^= msg[i];
395 
396 	if (!EVP_DigestInit(hash, digest)) {
397 		SM2error(ERR_R_EVP_LIB);
398 		goto err;
399 	}
400 
401 	if (!EVP_DigestUpdate(hash, x2y2, field_size)) {
402 		SM2error(ERR_R_EVP_LIB);
403 		goto err;
404 	}
405 
406 	if (!EVP_DigestUpdate(hash, msg, msg_len)) {
407 		SM2error(ERR_R_EVP_LIB);
408 		goto err;
409 	}
410 
411 	if (!EVP_DigestUpdate(hash, x2y2 + field_size, field_size)) {
412 		SM2error(ERR_R_EVP_LIB);
413 		goto err;
414 	}
415 
416 	if (!EVP_DigestFinal(hash, C3, NULL)) {
417 		SM2error(ERR_R_EVP_LIB);
418 		goto err;
419 	}
420 
421 	ctext_struct.C1x = x1;
422 	ctext_struct.C1y = y1;
423 	if ((ctext_struct.C3 = ASN1_OCTET_STRING_new()) == NULL) {
424 		SM2error(ERR_R_MALLOC_FAILURE);
425 		goto err;
426 	}
427 	if ((ctext_struct.C2 = ASN1_OCTET_STRING_new()) == NULL) {
428 		SM2error(ERR_R_MALLOC_FAILURE);
429 		goto err;
430 	}
431 	if (!ASN1_OCTET_STRING_set(ctext_struct.C3, C3, C3_size)) {
432 		SM2error(ERR_R_INTERNAL_ERROR);
433 		goto err;
434 	}
435 	if (!ASN1_OCTET_STRING_set(ctext_struct.C2, msg_mask, msg_len)) {
436 		SM2error(ERR_R_INTERNAL_ERROR);
437 		goto err;
438 	}
439 
440 	if ((clen = i2d_SM2_Ciphertext(&ctext_struct, &ciphertext_buf)) < 0) {
441 		SM2error(ERR_R_INTERNAL_ERROR);
442 		goto err;
443 	}
444 
445 	*ciphertext_len = clen;
446 	rc = 1;
447 
448  err:
449 	ASN1_OCTET_STRING_free(ctext_struct.C2);
450 	ASN1_OCTET_STRING_free(ctext_struct.C3);
451 	free(msg_mask);
452 	free(x2y2);
453 	free(C3);
454 	EVP_MD_CTX_free(hash);
455 	BN_CTX_end(ctx);
456 	BN_CTX_free(ctx);
457 	EC_POINT_free(kG);
458 	EC_POINT_free(kP);
459 	BN_free(order);
460 	return rc;
461 }
462 
463 int
SM2_decrypt(const EC_KEY * key,const EVP_MD * digest,const uint8_t * ciphertext,size_t ciphertext_len,uint8_t * ptext_buf,size_t * ptext_len)464 SM2_decrypt(const EC_KEY *key, const EVP_MD *digest, const uint8_t *ciphertext,
465     size_t ciphertext_len, uint8_t *ptext_buf, size_t *ptext_len)
466 {
467 	SM2_Ciphertext *sm2_ctext = NULL;
468 	EVP_MD_CTX *hash = NULL;
469 	BN_CTX *ctx = NULL;
470 	BIGNUM *x2, *y2;
471 	const EC_GROUP *group;
472 	EC_POINT *C1 = NULL;
473 	const uint8_t *C2, *C3;
474 	uint8_t *computed_C3 = NULL, *msg_mask = NULL, *x2y2 = NULL;
475 	size_t field_size, x2size, y2size;
476 	int msg_len = 0, rc = 0;
477 	int hash_size, i;
478 
479 	if ((group = EC_KEY_get0_group(key)) == NULL) {
480 		SM2error(SM2_R_INVALID_KEY);
481 		goto err;
482 	}
483 
484 	if ((field_size = ec_field_size(group)) == 0) {
485 		SM2error(SM2_R_INVALID_FIELD);
486 		goto err;
487 	}
488 
489 	if ((hash_size = EVP_MD_size(digest)) < 0) {
490 		SM2error(SM2_R_INVALID_DIGEST);
491 		goto err;
492 	}
493 
494 	memset(ptext_buf, 0xFF, *ptext_len);
495 
496 	if ((sm2_ctext = d2i_SM2_Ciphertext(NULL, &ciphertext,
497 	    ciphertext_len)) == NULL) {
498 		SM2error(SM2_R_ASN1_ERROR);
499 		goto err;
500 	}
501 
502 	if (sm2_ctext->C3->length != hash_size) {
503 		SM2error(SM2_R_INVALID_ENCODING);
504 		goto err;
505 	}
506 
507 	C2 = sm2_ctext->C2->data;
508 	C3 = sm2_ctext->C3->data;
509 	msg_len = sm2_ctext->C2->length;
510 
511 	if ((ctx = BN_CTX_new()) == NULL) {
512 		SM2error(ERR_R_MALLOC_FAILURE);
513 		goto err;
514 	}
515 
516 	BN_CTX_start(ctx);
517 	if ((x2 = BN_CTX_get(ctx)) == NULL) {
518 		SM2error(ERR_R_BN_LIB);
519 		goto err;
520 	}
521 	if ((y2 = BN_CTX_get(ctx)) == NULL) {
522 		SM2error(ERR_R_BN_LIB);
523 		goto err;
524 	}
525 
526 	if ((msg_mask = calloc(1, msg_len)) == NULL) {
527 		SM2error(ERR_R_MALLOC_FAILURE);
528 		goto err;
529 	}
530 	if ((x2y2 = calloc(2, field_size)) == NULL) {
531 		SM2error(ERR_R_MALLOC_FAILURE);
532 		goto err;
533 	}
534 	if ((computed_C3 = calloc(1, hash_size)) == NULL) {
535 		SM2error(ERR_R_MALLOC_FAILURE);
536 		goto err;
537 	}
538 
539 	if ((C1 = EC_POINT_new(group)) == NULL) {
540 		SM2error(ERR_R_MALLOC_FAILURE);
541 		goto err;
542 	}
543 
544 	if (!EC_POINT_set_affine_coordinates(group, C1, sm2_ctext->C1x,
545 	    sm2_ctext->C1y, ctx))
546 	{
547 		SM2error(ERR_R_EC_LIB);
548 		goto err;
549 	}
550 
551 	if (!EC_POINT_mul(group, C1, NULL, C1, EC_KEY_get0_private_key(key),
552 	    ctx)) {
553 		SM2error(ERR_R_EC_LIB);
554 		goto err;
555 	}
556 
557 	if (!EC_POINT_get_affine_coordinates(group, C1, x2, y2, ctx)) {
558 		SM2error(ERR_R_EC_LIB);
559 		goto err;
560 	}
561 
562 	if ((x2size = BN_num_bytes(x2)) > field_size ||
563 	    (y2size = BN_num_bytes(y2)) > field_size) {
564 		SM2error(SM2_R_BIGNUM_OUT_OF_RANGE);
565 		goto err;
566 	}
567 
568 	BN_bn2bin(x2, x2y2 + field_size - x2size);
569 	BN_bn2bin(y2, x2y2 + 2 * field_size - y2size);
570 
571 	if (!sm2_kdf(msg_mask, msg_len, x2y2, 2 * field_size, digest)) {
572 		SM2error(SM2_R_KDF_FAILURE);
573 		goto err;
574 	}
575 
576 	for (i = 0; i != msg_len; ++i)
577 		ptext_buf[i] = C2[i] ^ msg_mask[i];
578 
579 	if ((hash = EVP_MD_CTX_new()) == NULL) {
580 		SM2error(ERR_R_EVP_LIB);
581 		goto err;
582 	}
583 
584 	if (!EVP_DigestInit(hash, digest)) {
585 		SM2error(ERR_R_EVP_LIB);
586 		goto err;
587 	}
588 
589 	if (!EVP_DigestUpdate(hash, x2y2, field_size)) {
590 		SM2error(ERR_R_EVP_LIB);
591 		goto err;
592 	}
593 
594 	if (!EVP_DigestUpdate(hash, ptext_buf, msg_len)) {
595 		SM2error(ERR_R_EVP_LIB);
596 		goto err;
597 	}
598 
599 	if (!EVP_DigestUpdate(hash, x2y2 + field_size, field_size)) {
600 		SM2error(ERR_R_EVP_LIB);
601 		goto err;
602 	}
603 
604 	if (!EVP_DigestFinal(hash, computed_C3, NULL)) {
605 		SM2error(ERR_R_EVP_LIB);
606 		goto err;
607 	}
608 
609 	if (memcmp(computed_C3, C3, hash_size) != 0)
610 		goto err;
611 
612 	rc = 1;
613 	*ptext_len = msg_len;
614 
615  err:
616 	if (rc == 0)
617 		memset(ptext_buf, 0, *ptext_len);
618 
619 	free(msg_mask);
620 	free(x2y2);
621 	free(computed_C3);
622 	EC_POINT_free(C1);
623 	BN_CTX_end(ctx);
624 	BN_CTX_free(ctx);
625 	SM2_Ciphertext_free(sm2_ctext);
626 	EVP_MD_CTX_free(hash);
627 
628 	return rc;
629 }
630 
631 #endif /* OPENSSL_NO_SM2 */
632