11cb0ef41Sopenharmony_ci/* 21cb0ef41Sopenharmony_ci * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. 31cb0ef41Sopenharmony_ci * Copyright 2017 Ribose Inc. All Rights Reserved. 41cb0ef41Sopenharmony_ci * Ported from Ribose contributions from Botan. 51cb0ef41Sopenharmony_ci * 61cb0ef41Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 71cb0ef41Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 81cb0ef41Sopenharmony_ci * in the file LICENSE in the source distribution or at 91cb0ef41Sopenharmony_ci * https://www.openssl.org/source/license.html 101cb0ef41Sopenharmony_ci */ 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_ci/* 131cb0ef41Sopenharmony_ci * ECDSA low level APIs are deprecated for public use, but still ok for 141cb0ef41Sopenharmony_ci * internal use. 151cb0ef41Sopenharmony_ci */ 161cb0ef41Sopenharmony_ci#include "internal/deprecated.h" 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_ci#include "crypto/sm2.h" 191cb0ef41Sopenharmony_ci#include "crypto/sm2err.h" 201cb0ef41Sopenharmony_ci#include "crypto/ec.h" /* ossl_ecdh_kdf_X9_63() */ 211cb0ef41Sopenharmony_ci#include <openssl/err.h> 221cb0ef41Sopenharmony_ci#include <openssl/evp.h> 231cb0ef41Sopenharmony_ci#include <openssl/bn.h> 241cb0ef41Sopenharmony_ci#include <openssl/asn1.h> 251cb0ef41Sopenharmony_ci#include <openssl/asn1t.h> 261cb0ef41Sopenharmony_ci#include <string.h> 271cb0ef41Sopenharmony_ci 281cb0ef41Sopenharmony_citypedef struct SM2_Ciphertext_st SM2_Ciphertext; 291cb0ef41Sopenharmony_ciDECLARE_ASN1_FUNCTIONS(SM2_Ciphertext) 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_cistruct SM2_Ciphertext_st { 321cb0ef41Sopenharmony_ci BIGNUM *C1x; 331cb0ef41Sopenharmony_ci BIGNUM *C1y; 341cb0ef41Sopenharmony_ci ASN1_OCTET_STRING *C3; 351cb0ef41Sopenharmony_ci ASN1_OCTET_STRING *C2; 361cb0ef41Sopenharmony_ci}; 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_ciASN1_SEQUENCE(SM2_Ciphertext) = { 391cb0ef41Sopenharmony_ci ASN1_SIMPLE(SM2_Ciphertext, C1x, BIGNUM), 401cb0ef41Sopenharmony_ci ASN1_SIMPLE(SM2_Ciphertext, C1y, BIGNUM), 411cb0ef41Sopenharmony_ci ASN1_SIMPLE(SM2_Ciphertext, C3, ASN1_OCTET_STRING), 421cb0ef41Sopenharmony_ci ASN1_SIMPLE(SM2_Ciphertext, C2, ASN1_OCTET_STRING), 431cb0ef41Sopenharmony_ci} ASN1_SEQUENCE_END(SM2_Ciphertext) 441cb0ef41Sopenharmony_ci 451cb0ef41Sopenharmony_ciIMPLEMENT_ASN1_FUNCTIONS(SM2_Ciphertext) 461cb0ef41Sopenharmony_ci 471cb0ef41Sopenharmony_cistatic size_t ec_field_size(const EC_GROUP *group) 481cb0ef41Sopenharmony_ci{ 491cb0ef41Sopenharmony_ci /* Is there some simpler way to do this? */ 501cb0ef41Sopenharmony_ci BIGNUM *p = BN_new(); 511cb0ef41Sopenharmony_ci BIGNUM *a = BN_new(); 521cb0ef41Sopenharmony_ci BIGNUM *b = BN_new(); 531cb0ef41Sopenharmony_ci size_t field_size = 0; 541cb0ef41Sopenharmony_ci 551cb0ef41Sopenharmony_ci if (p == NULL || a == NULL || b == NULL) 561cb0ef41Sopenharmony_ci goto done; 571cb0ef41Sopenharmony_ci 581cb0ef41Sopenharmony_ci if (!EC_GROUP_get_curve(group, p, a, b, NULL)) 591cb0ef41Sopenharmony_ci goto done; 601cb0ef41Sopenharmony_ci field_size = (BN_num_bits(p) + 7) / 8; 611cb0ef41Sopenharmony_ci 621cb0ef41Sopenharmony_ci done: 631cb0ef41Sopenharmony_ci BN_free(p); 641cb0ef41Sopenharmony_ci BN_free(a); 651cb0ef41Sopenharmony_ci BN_free(b); 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci return field_size; 681cb0ef41Sopenharmony_ci} 691cb0ef41Sopenharmony_ci 701cb0ef41Sopenharmony_ciint ossl_sm2_plaintext_size(const unsigned char *ct, size_t ct_size, 711cb0ef41Sopenharmony_ci size_t *pt_size) 721cb0ef41Sopenharmony_ci{ 731cb0ef41Sopenharmony_ci struct SM2_Ciphertext_st *sm2_ctext = NULL; 741cb0ef41Sopenharmony_ci 751cb0ef41Sopenharmony_ci sm2_ctext = d2i_SM2_Ciphertext(NULL, &ct, ct_size); 761cb0ef41Sopenharmony_ci 771cb0ef41Sopenharmony_ci if (sm2_ctext == NULL) { 781cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, SM2_R_INVALID_ENCODING); 791cb0ef41Sopenharmony_ci return 0; 801cb0ef41Sopenharmony_ci } 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_ci *pt_size = sm2_ctext->C2->length; 831cb0ef41Sopenharmony_ci SM2_Ciphertext_free(sm2_ctext); 841cb0ef41Sopenharmony_ci 851cb0ef41Sopenharmony_ci return 1; 861cb0ef41Sopenharmony_ci} 871cb0ef41Sopenharmony_ci 881cb0ef41Sopenharmony_ciint ossl_sm2_ciphertext_size(const EC_KEY *key, const EVP_MD *digest, 891cb0ef41Sopenharmony_ci size_t msg_len, size_t *ct_size) 901cb0ef41Sopenharmony_ci{ 911cb0ef41Sopenharmony_ci const size_t field_size = ec_field_size(EC_KEY_get0_group(key)); 921cb0ef41Sopenharmony_ci const int md_size = EVP_MD_get_size(digest); 931cb0ef41Sopenharmony_ci size_t sz; 941cb0ef41Sopenharmony_ci 951cb0ef41Sopenharmony_ci if (field_size == 0 || md_size < 0) 961cb0ef41Sopenharmony_ci return 0; 971cb0ef41Sopenharmony_ci 981cb0ef41Sopenharmony_ci /* Integer and string are simple type; set constructed = 0, means primitive and definite length encoding. */ 991cb0ef41Sopenharmony_ci sz = 2 * ASN1_object_size(0, field_size + 1, V_ASN1_INTEGER) 1001cb0ef41Sopenharmony_ci + ASN1_object_size(0, md_size, V_ASN1_OCTET_STRING) 1011cb0ef41Sopenharmony_ci + ASN1_object_size(0, msg_len, V_ASN1_OCTET_STRING); 1021cb0ef41Sopenharmony_ci /* Sequence is structured type; set constructed = 1, means constructed and definite length encoding. */ 1031cb0ef41Sopenharmony_ci *ct_size = ASN1_object_size(1, sz, V_ASN1_SEQUENCE); 1041cb0ef41Sopenharmony_ci 1051cb0ef41Sopenharmony_ci return 1; 1061cb0ef41Sopenharmony_ci} 1071cb0ef41Sopenharmony_ci 1081cb0ef41Sopenharmony_ciint ossl_sm2_encrypt(const EC_KEY *key, 1091cb0ef41Sopenharmony_ci const EVP_MD *digest, 1101cb0ef41Sopenharmony_ci const uint8_t *msg, size_t msg_len, 1111cb0ef41Sopenharmony_ci uint8_t *ciphertext_buf, size_t *ciphertext_len) 1121cb0ef41Sopenharmony_ci{ 1131cb0ef41Sopenharmony_ci int rc = 0, ciphertext_leni; 1141cb0ef41Sopenharmony_ci size_t i; 1151cb0ef41Sopenharmony_ci BN_CTX *ctx = NULL; 1161cb0ef41Sopenharmony_ci BIGNUM *k = NULL; 1171cb0ef41Sopenharmony_ci BIGNUM *x1 = NULL; 1181cb0ef41Sopenharmony_ci BIGNUM *y1 = NULL; 1191cb0ef41Sopenharmony_ci BIGNUM *x2 = NULL; 1201cb0ef41Sopenharmony_ci BIGNUM *y2 = NULL; 1211cb0ef41Sopenharmony_ci EVP_MD_CTX *hash = EVP_MD_CTX_new(); 1221cb0ef41Sopenharmony_ci struct SM2_Ciphertext_st ctext_struct; 1231cb0ef41Sopenharmony_ci const EC_GROUP *group = EC_KEY_get0_group(key); 1241cb0ef41Sopenharmony_ci const BIGNUM *order = EC_GROUP_get0_order(group); 1251cb0ef41Sopenharmony_ci const EC_POINT *P = EC_KEY_get0_public_key(key); 1261cb0ef41Sopenharmony_ci EC_POINT *kG = NULL; 1271cb0ef41Sopenharmony_ci EC_POINT *kP = NULL; 1281cb0ef41Sopenharmony_ci uint8_t *msg_mask = NULL; 1291cb0ef41Sopenharmony_ci uint8_t *x2y2 = NULL; 1301cb0ef41Sopenharmony_ci uint8_t *C3 = NULL; 1311cb0ef41Sopenharmony_ci size_t field_size; 1321cb0ef41Sopenharmony_ci const int C3_size = EVP_MD_get_size(digest); 1331cb0ef41Sopenharmony_ci EVP_MD *fetched_digest = NULL; 1341cb0ef41Sopenharmony_ci OSSL_LIB_CTX *libctx = ossl_ec_key_get_libctx(key); 1351cb0ef41Sopenharmony_ci const char *propq = ossl_ec_key_get0_propq(key); 1361cb0ef41Sopenharmony_ci 1371cb0ef41Sopenharmony_ci /* NULL these before any "goto done" */ 1381cb0ef41Sopenharmony_ci ctext_struct.C2 = NULL; 1391cb0ef41Sopenharmony_ci ctext_struct.C3 = NULL; 1401cb0ef41Sopenharmony_ci 1411cb0ef41Sopenharmony_ci if (hash == NULL || C3_size <= 0) { 1421cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR); 1431cb0ef41Sopenharmony_ci goto done; 1441cb0ef41Sopenharmony_ci } 1451cb0ef41Sopenharmony_ci 1461cb0ef41Sopenharmony_ci field_size = ec_field_size(group); 1471cb0ef41Sopenharmony_ci if (field_size == 0) { 1481cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR); 1491cb0ef41Sopenharmony_ci goto done; 1501cb0ef41Sopenharmony_ci } 1511cb0ef41Sopenharmony_ci 1521cb0ef41Sopenharmony_ci kG = EC_POINT_new(group); 1531cb0ef41Sopenharmony_ci kP = EC_POINT_new(group); 1541cb0ef41Sopenharmony_ci ctx = BN_CTX_new_ex(libctx); 1551cb0ef41Sopenharmony_ci if (kG == NULL || kP == NULL || ctx == NULL) { 1561cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); 1571cb0ef41Sopenharmony_ci goto done; 1581cb0ef41Sopenharmony_ci } 1591cb0ef41Sopenharmony_ci 1601cb0ef41Sopenharmony_ci BN_CTX_start(ctx); 1611cb0ef41Sopenharmony_ci k = BN_CTX_get(ctx); 1621cb0ef41Sopenharmony_ci x1 = BN_CTX_get(ctx); 1631cb0ef41Sopenharmony_ci x2 = BN_CTX_get(ctx); 1641cb0ef41Sopenharmony_ci y1 = BN_CTX_get(ctx); 1651cb0ef41Sopenharmony_ci y2 = BN_CTX_get(ctx); 1661cb0ef41Sopenharmony_ci 1671cb0ef41Sopenharmony_ci if (y2 == NULL) { 1681cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB); 1691cb0ef41Sopenharmony_ci goto done; 1701cb0ef41Sopenharmony_ci } 1711cb0ef41Sopenharmony_ci 1721cb0ef41Sopenharmony_ci x2y2 = OPENSSL_zalloc(2 * field_size); 1731cb0ef41Sopenharmony_ci C3 = OPENSSL_zalloc(C3_size); 1741cb0ef41Sopenharmony_ci 1751cb0ef41Sopenharmony_ci if (x2y2 == NULL || C3 == NULL) { 1761cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); 1771cb0ef41Sopenharmony_ci goto done; 1781cb0ef41Sopenharmony_ci } 1791cb0ef41Sopenharmony_ci 1801cb0ef41Sopenharmony_ci memset(ciphertext_buf, 0, *ciphertext_len); 1811cb0ef41Sopenharmony_ci 1821cb0ef41Sopenharmony_ci if (!BN_priv_rand_range_ex(k, order, 0, ctx)) { 1831cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR); 1841cb0ef41Sopenharmony_ci goto done; 1851cb0ef41Sopenharmony_ci } 1861cb0ef41Sopenharmony_ci 1871cb0ef41Sopenharmony_ci if (!EC_POINT_mul(group, kG, k, NULL, NULL, ctx) 1881cb0ef41Sopenharmony_ci || !EC_POINT_get_affine_coordinates(group, kG, x1, y1, ctx) 1891cb0ef41Sopenharmony_ci || !EC_POINT_mul(group, kP, NULL, P, k, ctx) 1901cb0ef41Sopenharmony_ci || !EC_POINT_get_affine_coordinates(group, kP, x2, y2, ctx)) { 1911cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_EC_LIB); 1921cb0ef41Sopenharmony_ci goto done; 1931cb0ef41Sopenharmony_ci } 1941cb0ef41Sopenharmony_ci 1951cb0ef41Sopenharmony_ci if (BN_bn2binpad(x2, x2y2, field_size) < 0 1961cb0ef41Sopenharmony_ci || BN_bn2binpad(y2, x2y2 + field_size, field_size) < 0) { 1971cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR); 1981cb0ef41Sopenharmony_ci goto done; 1991cb0ef41Sopenharmony_ci } 2001cb0ef41Sopenharmony_ci 2011cb0ef41Sopenharmony_ci msg_mask = OPENSSL_zalloc(msg_len); 2021cb0ef41Sopenharmony_ci if (msg_mask == NULL) { 2031cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); 2041cb0ef41Sopenharmony_ci goto done; 2051cb0ef41Sopenharmony_ci } 2061cb0ef41Sopenharmony_ci 2071cb0ef41Sopenharmony_ci /* X9.63 with no salt happens to match the KDF used in SM2 */ 2081cb0ef41Sopenharmony_ci if (!ossl_ecdh_kdf_X9_63(msg_mask, msg_len, x2y2, 2 * field_size, NULL, 0, 2091cb0ef41Sopenharmony_ci digest, libctx, propq)) { 2101cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB); 2111cb0ef41Sopenharmony_ci goto done; 2121cb0ef41Sopenharmony_ci } 2131cb0ef41Sopenharmony_ci 2141cb0ef41Sopenharmony_ci for (i = 0; i != msg_len; ++i) 2151cb0ef41Sopenharmony_ci msg_mask[i] ^= msg[i]; 2161cb0ef41Sopenharmony_ci 2171cb0ef41Sopenharmony_ci fetched_digest = EVP_MD_fetch(libctx, EVP_MD_get0_name(digest), propq); 2181cb0ef41Sopenharmony_ci if (fetched_digest == NULL) { 2191cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR); 2201cb0ef41Sopenharmony_ci goto done; 2211cb0ef41Sopenharmony_ci } 2221cb0ef41Sopenharmony_ci if (EVP_DigestInit(hash, fetched_digest) == 0 2231cb0ef41Sopenharmony_ci || EVP_DigestUpdate(hash, x2y2, field_size) == 0 2241cb0ef41Sopenharmony_ci || EVP_DigestUpdate(hash, msg, msg_len) == 0 2251cb0ef41Sopenharmony_ci || EVP_DigestUpdate(hash, x2y2 + field_size, field_size) == 0 2261cb0ef41Sopenharmony_ci || EVP_DigestFinal(hash, C3, NULL) == 0) { 2271cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB); 2281cb0ef41Sopenharmony_ci goto done; 2291cb0ef41Sopenharmony_ci } 2301cb0ef41Sopenharmony_ci 2311cb0ef41Sopenharmony_ci ctext_struct.C1x = x1; 2321cb0ef41Sopenharmony_ci ctext_struct.C1y = y1; 2331cb0ef41Sopenharmony_ci ctext_struct.C3 = ASN1_OCTET_STRING_new(); 2341cb0ef41Sopenharmony_ci ctext_struct.C2 = ASN1_OCTET_STRING_new(); 2351cb0ef41Sopenharmony_ci 2361cb0ef41Sopenharmony_ci if (ctext_struct.C3 == NULL || ctext_struct.C2 == NULL) { 2371cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); 2381cb0ef41Sopenharmony_ci goto done; 2391cb0ef41Sopenharmony_ci } 2401cb0ef41Sopenharmony_ci if (!ASN1_OCTET_STRING_set(ctext_struct.C3, C3, C3_size) 2411cb0ef41Sopenharmony_ci || !ASN1_OCTET_STRING_set(ctext_struct.C2, msg_mask, msg_len)) { 2421cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR); 2431cb0ef41Sopenharmony_ci goto done; 2441cb0ef41Sopenharmony_ci } 2451cb0ef41Sopenharmony_ci 2461cb0ef41Sopenharmony_ci ciphertext_leni = i2d_SM2_Ciphertext(&ctext_struct, &ciphertext_buf); 2471cb0ef41Sopenharmony_ci /* Ensure cast to size_t is safe */ 2481cb0ef41Sopenharmony_ci if (ciphertext_leni < 0) { 2491cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR); 2501cb0ef41Sopenharmony_ci goto done; 2511cb0ef41Sopenharmony_ci } 2521cb0ef41Sopenharmony_ci *ciphertext_len = (size_t)ciphertext_leni; 2531cb0ef41Sopenharmony_ci 2541cb0ef41Sopenharmony_ci rc = 1; 2551cb0ef41Sopenharmony_ci 2561cb0ef41Sopenharmony_ci done: 2571cb0ef41Sopenharmony_ci EVP_MD_free(fetched_digest); 2581cb0ef41Sopenharmony_ci ASN1_OCTET_STRING_free(ctext_struct.C2); 2591cb0ef41Sopenharmony_ci ASN1_OCTET_STRING_free(ctext_struct.C3); 2601cb0ef41Sopenharmony_ci OPENSSL_free(msg_mask); 2611cb0ef41Sopenharmony_ci OPENSSL_free(x2y2); 2621cb0ef41Sopenharmony_ci OPENSSL_free(C3); 2631cb0ef41Sopenharmony_ci EVP_MD_CTX_free(hash); 2641cb0ef41Sopenharmony_ci BN_CTX_free(ctx); 2651cb0ef41Sopenharmony_ci EC_POINT_free(kG); 2661cb0ef41Sopenharmony_ci EC_POINT_free(kP); 2671cb0ef41Sopenharmony_ci return rc; 2681cb0ef41Sopenharmony_ci} 2691cb0ef41Sopenharmony_ci 2701cb0ef41Sopenharmony_ciint ossl_sm2_decrypt(const EC_KEY *key, 2711cb0ef41Sopenharmony_ci const EVP_MD *digest, 2721cb0ef41Sopenharmony_ci const uint8_t *ciphertext, size_t ciphertext_len, 2731cb0ef41Sopenharmony_ci uint8_t *ptext_buf, size_t *ptext_len) 2741cb0ef41Sopenharmony_ci{ 2751cb0ef41Sopenharmony_ci int rc = 0; 2761cb0ef41Sopenharmony_ci int i; 2771cb0ef41Sopenharmony_ci BN_CTX *ctx = NULL; 2781cb0ef41Sopenharmony_ci const EC_GROUP *group = EC_KEY_get0_group(key); 2791cb0ef41Sopenharmony_ci EC_POINT *C1 = NULL; 2801cb0ef41Sopenharmony_ci struct SM2_Ciphertext_st *sm2_ctext = NULL; 2811cb0ef41Sopenharmony_ci BIGNUM *x2 = NULL; 2821cb0ef41Sopenharmony_ci BIGNUM *y2 = NULL; 2831cb0ef41Sopenharmony_ci uint8_t *x2y2 = NULL; 2841cb0ef41Sopenharmony_ci uint8_t *computed_C3 = NULL; 2851cb0ef41Sopenharmony_ci const size_t field_size = ec_field_size(group); 2861cb0ef41Sopenharmony_ci const int hash_size = EVP_MD_get_size(digest); 2871cb0ef41Sopenharmony_ci uint8_t *msg_mask = NULL; 2881cb0ef41Sopenharmony_ci const uint8_t *C2 = NULL; 2891cb0ef41Sopenharmony_ci const uint8_t *C3 = NULL; 2901cb0ef41Sopenharmony_ci int msg_len = 0; 2911cb0ef41Sopenharmony_ci EVP_MD_CTX *hash = NULL; 2921cb0ef41Sopenharmony_ci OSSL_LIB_CTX *libctx = ossl_ec_key_get_libctx(key); 2931cb0ef41Sopenharmony_ci const char *propq = ossl_ec_key_get0_propq(key); 2941cb0ef41Sopenharmony_ci 2951cb0ef41Sopenharmony_ci if (field_size == 0 || hash_size <= 0) 2961cb0ef41Sopenharmony_ci goto done; 2971cb0ef41Sopenharmony_ci 2981cb0ef41Sopenharmony_ci memset(ptext_buf, 0xFF, *ptext_len); 2991cb0ef41Sopenharmony_ci 3001cb0ef41Sopenharmony_ci sm2_ctext = d2i_SM2_Ciphertext(NULL, &ciphertext, ciphertext_len); 3011cb0ef41Sopenharmony_ci 3021cb0ef41Sopenharmony_ci if (sm2_ctext == NULL) { 3031cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, SM2_R_ASN1_ERROR); 3041cb0ef41Sopenharmony_ci goto done; 3051cb0ef41Sopenharmony_ci } 3061cb0ef41Sopenharmony_ci 3071cb0ef41Sopenharmony_ci if (sm2_ctext->C3->length != hash_size) { 3081cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, SM2_R_INVALID_ENCODING); 3091cb0ef41Sopenharmony_ci goto done; 3101cb0ef41Sopenharmony_ci } 3111cb0ef41Sopenharmony_ci 3121cb0ef41Sopenharmony_ci C2 = sm2_ctext->C2->data; 3131cb0ef41Sopenharmony_ci C3 = sm2_ctext->C3->data; 3141cb0ef41Sopenharmony_ci msg_len = sm2_ctext->C2->length; 3151cb0ef41Sopenharmony_ci if (*ptext_len < (size_t)msg_len) { 3161cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, SM2_R_BUFFER_TOO_SMALL); 3171cb0ef41Sopenharmony_ci goto done; 3181cb0ef41Sopenharmony_ci } 3191cb0ef41Sopenharmony_ci 3201cb0ef41Sopenharmony_ci ctx = BN_CTX_new_ex(libctx); 3211cb0ef41Sopenharmony_ci if (ctx == NULL) { 3221cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); 3231cb0ef41Sopenharmony_ci goto done; 3241cb0ef41Sopenharmony_ci } 3251cb0ef41Sopenharmony_ci 3261cb0ef41Sopenharmony_ci BN_CTX_start(ctx); 3271cb0ef41Sopenharmony_ci x2 = BN_CTX_get(ctx); 3281cb0ef41Sopenharmony_ci y2 = BN_CTX_get(ctx); 3291cb0ef41Sopenharmony_ci 3301cb0ef41Sopenharmony_ci if (y2 == NULL) { 3311cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB); 3321cb0ef41Sopenharmony_ci goto done; 3331cb0ef41Sopenharmony_ci } 3341cb0ef41Sopenharmony_ci 3351cb0ef41Sopenharmony_ci msg_mask = OPENSSL_zalloc(msg_len); 3361cb0ef41Sopenharmony_ci x2y2 = OPENSSL_zalloc(2 * field_size); 3371cb0ef41Sopenharmony_ci computed_C3 = OPENSSL_zalloc(hash_size); 3381cb0ef41Sopenharmony_ci 3391cb0ef41Sopenharmony_ci if (msg_mask == NULL || x2y2 == NULL || computed_C3 == NULL) { 3401cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); 3411cb0ef41Sopenharmony_ci goto done; 3421cb0ef41Sopenharmony_ci } 3431cb0ef41Sopenharmony_ci 3441cb0ef41Sopenharmony_ci C1 = EC_POINT_new(group); 3451cb0ef41Sopenharmony_ci if (C1 == NULL) { 3461cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); 3471cb0ef41Sopenharmony_ci goto done; 3481cb0ef41Sopenharmony_ci } 3491cb0ef41Sopenharmony_ci 3501cb0ef41Sopenharmony_ci if (!EC_POINT_set_affine_coordinates(group, C1, sm2_ctext->C1x, 3511cb0ef41Sopenharmony_ci sm2_ctext->C1y, ctx) 3521cb0ef41Sopenharmony_ci || !EC_POINT_mul(group, C1, NULL, C1, EC_KEY_get0_private_key(key), 3531cb0ef41Sopenharmony_ci ctx) 3541cb0ef41Sopenharmony_ci || !EC_POINT_get_affine_coordinates(group, C1, x2, y2, ctx)) { 3551cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_EC_LIB); 3561cb0ef41Sopenharmony_ci goto done; 3571cb0ef41Sopenharmony_ci } 3581cb0ef41Sopenharmony_ci 3591cb0ef41Sopenharmony_ci if (BN_bn2binpad(x2, x2y2, field_size) < 0 3601cb0ef41Sopenharmony_ci || BN_bn2binpad(y2, x2y2 + field_size, field_size) < 0 3611cb0ef41Sopenharmony_ci || !ossl_ecdh_kdf_X9_63(msg_mask, msg_len, x2y2, 2 * field_size, 3621cb0ef41Sopenharmony_ci NULL, 0, digest, libctx, propq)) { 3631cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR); 3641cb0ef41Sopenharmony_ci goto done; 3651cb0ef41Sopenharmony_ci } 3661cb0ef41Sopenharmony_ci 3671cb0ef41Sopenharmony_ci for (i = 0; i != msg_len; ++i) 3681cb0ef41Sopenharmony_ci ptext_buf[i] = C2[i] ^ msg_mask[i]; 3691cb0ef41Sopenharmony_ci 3701cb0ef41Sopenharmony_ci hash = EVP_MD_CTX_new(); 3711cb0ef41Sopenharmony_ci if (hash == NULL) { 3721cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); 3731cb0ef41Sopenharmony_ci goto done; 3741cb0ef41Sopenharmony_ci } 3751cb0ef41Sopenharmony_ci 3761cb0ef41Sopenharmony_ci if (!EVP_DigestInit(hash, digest) 3771cb0ef41Sopenharmony_ci || !EVP_DigestUpdate(hash, x2y2, field_size) 3781cb0ef41Sopenharmony_ci || !EVP_DigestUpdate(hash, ptext_buf, msg_len) 3791cb0ef41Sopenharmony_ci || !EVP_DigestUpdate(hash, x2y2 + field_size, field_size) 3801cb0ef41Sopenharmony_ci || !EVP_DigestFinal(hash, computed_C3, NULL)) { 3811cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB); 3821cb0ef41Sopenharmony_ci goto done; 3831cb0ef41Sopenharmony_ci } 3841cb0ef41Sopenharmony_ci 3851cb0ef41Sopenharmony_ci if (CRYPTO_memcmp(computed_C3, C3, hash_size) != 0) { 3861cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_SM2, SM2_R_INVALID_DIGEST); 3871cb0ef41Sopenharmony_ci goto done; 3881cb0ef41Sopenharmony_ci } 3891cb0ef41Sopenharmony_ci 3901cb0ef41Sopenharmony_ci rc = 1; 3911cb0ef41Sopenharmony_ci *ptext_len = msg_len; 3921cb0ef41Sopenharmony_ci 3931cb0ef41Sopenharmony_ci done: 3941cb0ef41Sopenharmony_ci if (rc == 0) 3951cb0ef41Sopenharmony_ci memset(ptext_buf, 0, *ptext_len); 3961cb0ef41Sopenharmony_ci 3971cb0ef41Sopenharmony_ci OPENSSL_free(msg_mask); 3981cb0ef41Sopenharmony_ci OPENSSL_free(x2y2); 3991cb0ef41Sopenharmony_ci OPENSSL_free(computed_C3); 4001cb0ef41Sopenharmony_ci EC_POINT_free(C1); 4011cb0ef41Sopenharmony_ci BN_CTX_free(ctx); 4021cb0ef41Sopenharmony_ci SM2_Ciphertext_free(sm2_ctext); 4031cb0ef41Sopenharmony_ci EVP_MD_CTX_free(hash); 4041cb0ef41Sopenharmony_ci 4051cb0ef41Sopenharmony_ci return rc; 4061cb0ef41Sopenharmony_ci} 407