]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/sm2/sm2_crypt.c
Raise an error on syscall failure in tls_retry_write_records
[thirdparty/openssl.git] / crypto / sm2 / sm2_crypt.c
CommitLineData
3d328a44 1/*
b6461792 2 * Copyright 2017-2024 The OpenSSL Project Authors. All Rights Reserved.
3d328a44
JL
3 * Copyright 2017 Ribose Inc. All Rights Reserved.
4 * Ported from Ribose contributions from Botan.
5 *
f9f859ad 6 * Licensed under the Apache License 2.0 (the "License"). You may not use
3d328a44
JL
7 * this file except in compliance with the License. You can obtain a copy
8 * in the file LICENSE in the source distribution or at
9 * https://www.openssl.org/source/license.html
10 */
11
579422c8
P
12/*
13 * ECDSA low level APIs are deprecated for public use, but still ok for
14 * internal use.
15 */
16#include "internal/deprecated.h"
17
25f2138b
DMSP
18#include "crypto/sm2.h"
19#include "crypto/sm2err.h"
32ab57cb 20#include "crypto/ec.h" /* ossl_ecdh_kdf_X9_63() */
2398404e 21#include <openssl/err.h>
3d328a44
JL
22#include <openssl/evp.h>
23#include <openssl/bn.h>
24#include <openssl/asn1.h>
25#include <openssl/asn1t.h>
26#include <string.h>
27
28typedef struct SM2_Ciphertext_st SM2_Ciphertext;
29DECLARE_ASN1_FUNCTIONS(SM2_Ciphertext)
30
31struct SM2_Ciphertext_st {
32 BIGNUM *C1x;
33 BIGNUM *C1y;
34 ASN1_OCTET_STRING *C3;
35 ASN1_OCTET_STRING *C2;
36};
37
38ASN1_SEQUENCE(SM2_Ciphertext) = {
39 ASN1_SIMPLE(SM2_Ciphertext, C1x, BIGNUM),
40 ASN1_SIMPLE(SM2_Ciphertext, C1y, BIGNUM),
41 ASN1_SIMPLE(SM2_Ciphertext, C3, ASN1_OCTET_STRING),
42 ASN1_SIMPLE(SM2_Ciphertext, C2, ASN1_OCTET_STRING),
43} ASN1_SEQUENCE_END(SM2_Ciphertext)
44
45IMPLEMENT_ASN1_FUNCTIONS(SM2_Ciphertext)
46
2167239a 47static size_t ec_field_size(const EC_GROUP *group)
3d328a44 48{
9170cc03 49 const BIGNUM *p = EC_GROUP_get0_field(group);
3d328a44 50
9170cc03
K
51 if (p == NULL)
52 return 0;
3d328a44 53
9170cc03 54 return BN_num_bytes(p);
3d328a44
JL
55}
56
36cf45ef
MC
57int ossl_sm2_plaintext_size(const unsigned char *ct, size_t ct_size,
58 size_t *pt_size)
4e664750 59{
36cf45ef 60 struct SM2_Ciphertext_st *sm2_ctext = NULL;
4e664750 61
36cf45ef 62 sm2_ctext = d2i_SM2_Ciphertext(NULL, &ct, ct_size);
4e664750 63
36cf45ef 64 if (sm2_ctext == NULL) {
9311d0c4 65 ERR_raise(ERR_LIB_SM2, SM2_R_INVALID_ENCODING);
e14d6cf6
MC
66 return 0;
67 }
68
36cf45ef
MC
69 *pt_size = sm2_ctext->C2->length;
70 SM2_Ciphertext_free(sm2_ctext);
71
e14d6cf6 72 return 1;
4e664750
JL
73}
74
32ab57cb
SL
75int ossl_sm2_ciphertext_size(const EC_KEY *key, const EVP_MD *digest,
76 size_t msg_len, size_t *ct_size)
3d328a44 77{
2167239a 78 const size_t field_size = ec_field_size(EC_KEY_get0_group(key));
ed576acd 79 const int md_size = EVP_MD_get_size(digest);
307a494e 80 size_t sz;
e14d6cf6
MC
81
82 if (field_size == 0 || md_size < 0)
83 return 0;
84
307a494e 85 /* Integer and string are simple type; set constructed = 0, means primitive and definite length encoding. */
86 sz = 2 * ASN1_object_size(0, field_size + 1, V_ASN1_INTEGER)
87 + ASN1_object_size(0, md_size, V_ASN1_OCTET_STRING)
88 + ASN1_object_size(0, msg_len, V_ASN1_OCTET_STRING);
89 /* Sequence is structured type; set constructed = 1, means constructed and definite length encoding. */
90 *ct_size = ASN1_object_size(1, sz, V_ASN1_SEQUENCE);
91
e14d6cf6 92 return 1;
3d328a44
JL
93}
94
32ab57cb
SL
95int ossl_sm2_encrypt(const EC_KEY *key,
96 const EVP_MD *digest,
97 const uint8_t *msg, size_t msg_len,
98 uint8_t *ciphertext_buf, size_t *ciphertext_len)
3d328a44 99{
44d3845d 100 int rc = 0, ciphertext_leni;
3d328a44
JL
101 size_t i;
102 BN_CTX *ctx = NULL;
103 BIGNUM *k = NULL;
104 BIGNUM *x1 = NULL;
105 BIGNUM *y1 = NULL;
106 BIGNUM *x2 = NULL;
107 BIGNUM *y2 = NULL;
3d328a44 108 EVP_MD_CTX *hash = EVP_MD_CTX_new();
3d328a44
JL
109 struct SM2_Ciphertext_st ctext_struct;
110 const EC_GROUP *group = EC_KEY_get0_group(key);
111 const BIGNUM *order = EC_GROUP_get0_order(group);
112 const EC_POINT *P = EC_KEY_get0_public_key(key);
113 EC_POINT *kG = NULL;
114 EC_POINT *kP = NULL;
115 uint8_t *msg_mask = NULL;
3d328a44
JL
116 uint8_t *x2y2 = NULL;
117 uint8_t *C3 = NULL;
1829ff4b 118 size_t field_size;
ed576acd 119 const int C3_size = EVP_MD_get_size(digest);
5ccada09 120 EVP_MD *fetched_digest = NULL;
32ab57cb
SL
121 OSSL_LIB_CTX *libctx = ossl_ec_key_get_libctx(key);
122 const char *propq = ossl_ec_key_get0_propq(key);
3d328a44 123
44d3845d
MC
124 /* NULL these before any "goto done" */
125 ctext_struct.C2 = NULL;
126 ctext_struct.C3 = NULL;
127
1829ff4b 128 if (hash == NULL || C3_size <= 0) {
9311d0c4 129 ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
1829ff4b
MC
130 goto done;
131 }
132
133 field_size = ec_field_size(group);
134 if (field_size == 0) {
9311d0c4 135 ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
44d3845d
MC
136 goto done;
137 }
3d328a44
JL
138
139 kG = EC_POINT_new(group);
140 kP = EC_POINT_new(group);
e077455e
RL
141 if (kG == NULL || kP == NULL) {
142 ERR_raise(ERR_LIB_SM2, ERR_R_EC_LIB);
143 goto done;
144 }
5ccada09 145 ctx = BN_CTX_new_ex(libctx);
e077455e
RL
146 if (ctx == NULL) {
147 ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB);
44d3845d
MC
148 goto done;
149 }
3d328a44
JL
150
151 BN_CTX_start(ctx);
152 k = BN_CTX_get(ctx);
153 x1 = BN_CTX_get(ctx);
154 x2 = BN_CTX_get(ctx);
155 y1 = BN_CTX_get(ctx);
156 y2 = BN_CTX_get(ctx);
157
44d3845d 158 if (y2 == NULL) {
9311d0c4 159 ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB);
2398404e 160 goto done;
44d3845d 161 }
3d328a44
JL
162
163 x2y2 = OPENSSL_zalloc(2 * field_size);
164 C3 = OPENSSL_zalloc(C3_size);
165
e077455e 166 if (x2y2 == NULL || C3 == NULL)
2398404e 167 goto done;
3d328a44
JL
168
169 memset(ciphertext_buf, 0, *ciphertext_len);
170
5cbd2ea3 171 if (!BN_priv_rand_range_ex(k, order, 0, ctx)) {
9311d0c4 172 ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
3d328a44 173 goto done;
44d3845d 174 }
3d328a44 175
44d3845d 176 if (!EC_POINT_mul(group, kG, k, NULL, NULL, ctx)
9cc570d4 177 || !EC_POINT_get_affine_coordinates(group, kG, x1, y1, ctx)
44d3845d 178 || !EC_POINT_mul(group, kP, NULL, P, k, ctx)
9cc570d4 179 || !EC_POINT_get_affine_coordinates(group, kP, x2, y2, ctx)) {
9311d0c4 180 ERR_raise(ERR_LIB_SM2, ERR_R_EC_LIB);
3d328a44 181 goto done;
44d3845d 182 }
3d328a44 183
44d3845d
MC
184 if (BN_bn2binpad(x2, x2y2, field_size) < 0
185 || BN_bn2binpad(y2, x2y2 + field_size, field_size) < 0) {
9311d0c4 186 ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
3d328a44 187 goto done;
44d3845d 188 }
3d328a44
JL
189
190 msg_mask = OPENSSL_zalloc(msg_len);
e077455e 191 if (msg_mask == NULL)
3d328a44
JL
192 goto done;
193
194 /* X9.63 with no salt happens to match the KDF used in SM2 */
32ab57cb
SL
195 if (!ossl_ecdh_kdf_X9_63(msg_mask, msg_len, x2y2, 2 * field_size, NULL, 0,
196 digest, libctx, propq)) {
9311d0c4 197 ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB);
3d328a44 198 goto done;
44d3845d 199 }
3d328a44
JL
200
201 for (i = 0; i != msg_len; ++i)
202 msg_mask[i] ^= msg[i];
203
ed576acd 204 fetched_digest = EVP_MD_fetch(libctx, EVP_MD_get0_name(digest), propq);
5ccada09 205 if (fetched_digest == NULL) {
9311d0c4 206 ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
5ccada09
SL
207 goto done;
208 }
209 if (EVP_DigestInit(hash, fetched_digest) == 0
44d3845d
MC
210 || EVP_DigestUpdate(hash, x2y2, field_size) == 0
211 || EVP_DigestUpdate(hash, msg, msg_len) == 0
212 || EVP_DigestUpdate(hash, x2y2 + field_size, field_size) == 0
213 || EVP_DigestFinal(hash, C3, NULL) == 0) {
9311d0c4 214 ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB);
3d328a44 215 goto done;
44d3845d 216 }
3d328a44
JL
217
218 ctext_struct.C1x = x1;
219 ctext_struct.C1y = y1;
220 ctext_struct.C3 = ASN1_OCTET_STRING_new();
3d328a44 221 ctext_struct.C2 = ASN1_OCTET_STRING_new();
3d328a44 222
44d3845d 223 if (ctext_struct.C3 == NULL || ctext_struct.C2 == NULL) {
e077455e 224 ERR_raise(ERR_LIB_SM2, ERR_R_ASN1_LIB);
44d3845d
MC
225 goto done;
226 }
227 if (!ASN1_OCTET_STRING_set(ctext_struct.C3, C3, C3_size)
228 || !ASN1_OCTET_STRING_set(ctext_struct.C2, msg_mask, msg_len)) {
9311d0c4 229 ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
44d3845d
MC
230 goto done;
231 }
3d328a44 232
44d3845d
MC
233 ciphertext_leni = i2d_SM2_Ciphertext(&ctext_struct, &ciphertext_buf);
234 /* Ensure cast to size_t is safe */
235 if (ciphertext_leni < 0) {
9311d0c4 236 ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
44d3845d
MC
237 goto done;
238 }
239 *ciphertext_len = (size_t)ciphertext_leni;
3d328a44
JL
240
241 rc = 1;
242
243 done:
5ccada09 244 EVP_MD_free(fetched_digest);
44d3845d
MC
245 ASN1_OCTET_STRING_free(ctext_struct.C2);
246 ASN1_OCTET_STRING_free(ctext_struct.C3);
3d328a44
JL
247 OPENSSL_free(msg_mask);
248 OPENSSL_free(x2y2);
249 OPENSSL_free(C3);
250 EVP_MD_CTX_free(hash);
251 BN_CTX_free(ctx);
252 EC_POINT_free(kG);
253 EC_POINT_free(kP);
254 return rc;
255}
256
32ab57cb
SL
257int ossl_sm2_decrypt(const EC_KEY *key,
258 const EVP_MD *digest,
259 const uint8_t *ciphertext, size_t ciphertext_len,
260 uint8_t *ptext_buf, size_t *ptext_len)
3d328a44
JL
261{
262 int rc = 0;
263 int i;
3d328a44
JL
264 BN_CTX *ctx = NULL;
265 const EC_GROUP *group = EC_KEY_get0_group(key);
266 EC_POINT *C1 = NULL;
267 struct SM2_Ciphertext_st *sm2_ctext = NULL;
268 BIGNUM *x2 = NULL;
269 BIGNUM *y2 = NULL;
3d328a44
JL
270 uint8_t *x2y2 = NULL;
271 uint8_t *computed_C3 = NULL;
2167239a 272 const size_t field_size = ec_field_size(group);
ed576acd 273 const int hash_size = EVP_MD_get_size(digest);
3d328a44
JL
274 uint8_t *msg_mask = NULL;
275 const uint8_t *C2 = NULL;
276 const uint8_t *C3 = NULL;
277 int msg_len = 0;
278 EVP_MD_CTX *hash = NULL;
32ab57cb
SL
279 OSSL_LIB_CTX *libctx = ossl_ec_key_get_libctx(key);
280 const char *propq = ossl_ec_key_get0_propq(key);
3d328a44 281
1829ff4b 282 if (field_size == 0 || hash_size <= 0)
3d328a44
JL
283 goto done;
284
285 memset(ptext_buf, 0xFF, *ptext_len);
286
287 sm2_ctext = d2i_SM2_Ciphertext(NULL, &ciphertext, ciphertext_len);
288
245be530 289 if (sm2_ctext == NULL) {
9311d0c4 290 ERR_raise(ERR_LIB_SM2, SM2_R_ASN1_ERROR);
3d328a44 291 goto done;
245be530 292 }
3d328a44 293
245be530 294 if (sm2_ctext->C3->length != hash_size) {
9311d0c4 295 ERR_raise(ERR_LIB_SM2, SM2_R_INVALID_ENCODING);
3d328a44 296 goto done;
245be530 297 }
3d328a44
JL
298
299 C2 = sm2_ctext->C2->data;
300 C3 = sm2_ctext->C3->data;
301 msg_len = sm2_ctext->C2->length;
ad1ca777 302 if (*ptext_len < (size_t)msg_len) {
2576b70d 303 ERR_raise(ERR_LIB_SM2, SM2_R_BUFFER_TOO_SMALL);
ad1ca777
MC
304 goto done;
305 }
3d328a44 306
5ccada09 307 ctx = BN_CTX_new_ex(libctx);
245be530 308 if (ctx == NULL) {
e077455e 309 ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB);
2398404e 310 goto done;
245be530 311 }
3d328a44
JL
312
313 BN_CTX_start(ctx);
314 x2 = BN_CTX_get(ctx);
315 y2 = BN_CTX_get(ctx);
316
245be530 317 if (y2 == NULL) {
9311d0c4 318 ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB);
2398404e 319 goto done;
245be530 320 }
3d328a44
JL
321
322 msg_mask = OPENSSL_zalloc(msg_len);
323 x2y2 = OPENSSL_zalloc(2 * field_size);
324 computed_C3 = OPENSSL_zalloc(hash_size);
325
e077455e 326 if (msg_mask == NULL || x2y2 == NULL || computed_C3 == NULL)
2398404e 327 goto done;
3d328a44
JL
328
329 C1 = EC_POINT_new(group);
245be530 330 if (C1 == NULL) {
e077455e 331 ERR_raise(ERR_LIB_SM2, ERR_R_EC_LIB);
3d328a44 332 goto done;
245be530 333 }
3d328a44 334
9cc570d4
MC
335 if (!EC_POINT_set_affine_coordinates(group, C1, sm2_ctext->C1x,
336 sm2_ctext->C1y, ctx)
245be530
MC
337 || !EC_POINT_mul(group, C1, NULL, C1, EC_KEY_get0_private_key(key),
338 ctx)
9cc570d4 339 || !EC_POINT_get_affine_coordinates(group, C1, x2, y2, ctx)) {
9311d0c4 340 ERR_raise(ERR_LIB_SM2, ERR_R_EC_LIB);
3d328a44 341 goto done;
245be530 342 }
3d328a44 343
245be530
MC
344 if (BN_bn2binpad(x2, x2y2, field_size) < 0
345 || BN_bn2binpad(y2, x2y2 + field_size, field_size) < 0
32ab57cb
SL
346 || !ossl_ecdh_kdf_X9_63(msg_mask, msg_len, x2y2, 2 * field_size,
347 NULL, 0, digest, libctx, propq)) {
9311d0c4 348 ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
3d328a44 349 goto done;
245be530 350 }
3d328a44
JL
351
352 for (i = 0; i != msg_len; ++i)
353 ptext_buf[i] = C2[i] ^ msg_mask[i];
354
355 hash = EVP_MD_CTX_new();
245be530 356 if (hash == NULL) {
e077455e 357 ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB);
2398404e 358 goto done;
245be530 359 }
3d328a44 360
245be530
MC
361 if (!EVP_DigestInit(hash, digest)
362 || !EVP_DigestUpdate(hash, x2y2, field_size)
363 || !EVP_DigestUpdate(hash, ptext_buf, msg_len)
364 || !EVP_DigestUpdate(hash, x2y2 + field_size, field_size)
365 || !EVP_DigestFinal(hash, computed_C3, NULL)) {
9311d0c4 366 ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB);
3d328a44 367 goto done;
245be530 368 }
3d328a44 369
245be530 370 if (CRYPTO_memcmp(computed_C3, C3, hash_size) != 0) {
9311d0c4 371 ERR_raise(ERR_LIB_SM2, SM2_R_INVALID_DIGEST);
3d328a44 372 goto done;
245be530 373 }
3d328a44
JL
374
375 rc = 1;
dceb99a5 376 *ptext_len = msg_len;
3d328a44
JL
377
378 done:
3d328a44
JL
379 if (rc == 0)
380 memset(ptext_buf, 0, *ptext_len);
381
382 OPENSSL_free(msg_mask);
383 OPENSSL_free(x2y2);
384 OPENSSL_free(computed_C3);
385 EC_POINT_free(C1);
386 BN_CTX_free(ctx);
387 SM2_Ciphertext_free(sm2_ctext);
388 EVP_MD_CTX_free(hash);
389
390 return rc;
391}