1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (c) 2019 Huawei Technologies Co., Ltd
4 */
5
6 #include <crypto/crypto.h>
7 #include <crypto/sm2-kdf.h>
8 #include <io.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <string_ext.h>
12 #include <tee_api_types.h>
13 #include <tee/tee_cryp_utl.h>
14 #include <trace.h>
15 #include <util.h>
16 #include <utee_defines.h>
17
18 #include "acipher_helpers.h"
19
20 /* SM2 uses 256 bit unsigned integers in big endian format */
21 #define SM2_INT_SIZE_BYTES 32
22
23 static TEE_Result
sm2_uncompressed_bytes_to_point(ecc_point * p,const ltc_ecc_dp * dp,const uint8_t * x1y1,size_t max_size,size_t * consumed)24 sm2_uncompressed_bytes_to_point(ecc_point *p, const ltc_ecc_dp *dp,
25 const uint8_t *x1y1, size_t max_size,
26 size_t *consumed)
27 {
28 uint8_t *ptr = (uint8_t *)x1y1;
29 uint8_t one[] = { 1 };
30 int ltc_res = 0;
31
32 if (max_size < (size_t)(2 * SM2_INT_SIZE_BYTES))
33 return TEE_ERROR_BAD_PARAMETERS;
34
35 ltc_res = mp_read_unsigned_bin(p->x, ptr, SM2_INT_SIZE_BYTES);
36 if (ltc_res != CRYPT_OK)
37 return TEE_ERROR_BAD_PARAMETERS;
38
39 ptr += SM2_INT_SIZE_BYTES;
40
41 ltc_res = mp_read_unsigned_bin(p->y, ptr, SM2_INT_SIZE_BYTES);
42 if (ltc_res != CRYPT_OK)
43 return TEE_ERROR_BAD_PARAMETERS;
44
45 ltc_res = ltc_ecc_is_point(dp, p->x, p->y);
46 if (ltc_res != CRYPT_OK)
47 return TEE_ERROR_BAD_PARAMETERS;
48
49 mp_read_unsigned_bin(p->z, one, sizeof(one));
50
51 *consumed = 2 * SM2_INT_SIZE_BYTES + 1; /* PC */
52
53 return TEE_SUCCESS;
54 }
55
56 /*
57 * GM/T 0003.1‒2012 Part 1 Section 4.2.9
58 * Conversion of a byte string @buf to a point @p. Makes sure @p is on the curve
59 * defined by domain parameters @dp.
60 * Note: only the uncompressed form is supported. Uncompressed and hybrid forms
61 * are TBD.
62 */
sm2_bytes_to_point(ecc_point * p,const ltc_ecc_dp * dp,const uint8_t * buf,size_t max_size,size_t * consumed)63 static TEE_Result sm2_bytes_to_point(ecc_point *p, const ltc_ecc_dp *dp,
64 const uint8_t *buf, size_t max_size,
65 size_t *consumed)
66 {
67 uint8_t PC = 0;
68
69 if (!max_size)
70 return TEE_ERROR_BAD_PARAMETERS;
71
72 PC = buf[0];
73
74 switch (PC) {
75 case 0x02:
76 case 0x03:
77 /* Compressed form */
78 return TEE_ERROR_NOT_SUPPORTED;
79 case 0x04:
80 /* UNcompressed form */
81 return sm2_uncompressed_bytes_to_point(p, dp, buf + 1,
82 max_size - 1, consumed);
83 case 0x06:
84 case 0x07:
85 /* Hybrid form */
86 return TEE_ERROR_NOT_SUPPORTED;
87 default:
88 return TEE_ERROR_BAD_PARAMETERS;
89 }
90
91 return TEE_ERROR_GENERIC;
92 }
93
is_zero(const uint8_t * buf,size_t size)94 static bool is_zero(const uint8_t *buf, size_t size)
95 {
96 uint8_t v = 0;
97 size_t i = 0;
98
99 for (i = 0; i < size; i++)
100 v |= buf[i];
101
102 return !v;
103 }
104
105 /*
106 * GM/T 0003.1‒2012 Part 4 Section 7.1
107 * Decryption algorithm
108 */
sm2_ltc_pke_decrypt(struct ecc_keypair * key,const uint8_t * src,size_t src_len,uint8_t * dst,size_t * dst_len)109 TEE_Result sm2_ltc_pke_decrypt(struct ecc_keypair *key, const uint8_t *src,
110 size_t src_len, uint8_t *dst, size_t *dst_len)
111 {
112 TEE_Result res = TEE_SUCCESS;
113 uint8_t x2y2[64] = { };
114 ecc_key ltc_key = { };
115 ecc_point *C1 = NULL;
116 size_t C1_len = 0;
117 ecc_point *S = NULL;
118 ecc_point *x2y2p = NULL;
119 void *ctx = NULL;
120 int ltc_res = 0;
121 void *h = NULL;
122 int inf = 0;
123 uint8_t *t = NULL;
124 size_t C2_len = 0;
125 size_t i = 0;
126 size_t out_len = 0;
127 uint8_t *eom = NULL;
128 uint8_t u[TEE_SM3_HASH_SIZE] = { };
129
130 /*
131 * Input buffer src is (C1 || C2 || C3)
132 * - C1 represents a point (should be on the curve)
133 * - C2 is the encrypted message
134 * - C3 is a SM3 hash
135 */
136
137 res = ecc_populate_ltc_private_key(<c_key, key, TEE_ALG_SM2_PKE,
138 NULL);
139 if (res)
140 goto out;
141
142 /* Step B1: read and validate point C1 from encrypted message */
143
144 C1 = ltc_ecc_new_point();
145 if (!C1) {
146 res = TEE_ERROR_OUT_OF_MEMORY;
147 goto out;
148 }
149
150 res = sm2_bytes_to_point(C1, <c_key.dp, src, src_len, &C1_len);
151 if (res)
152 goto out;
153
154 /* Step B2: S = [h]C1 */
155
156 if (ltc_key.dp.cofactor != 1) {
157 S = ltc_ecc_new_point();
158 if (!S) {
159 res = TEE_ERROR_OUT_OF_MEMORY;
160 goto out;
161 }
162
163 ltc_res = mp_init_multi(&h, NULL);
164 if (ltc_res != CRYPT_OK) {
165 res = TEE_ERROR_OUT_OF_MEMORY;
166 goto out;
167 }
168
169 ltc_res = mp_set_int(h, ltc_key.dp.cofactor);
170 if (ltc_res != CRYPT_OK) {
171 res = TEE_ERROR_BAD_STATE;
172 goto out;
173 }
174
175 ltc_res = ltc_ecc_mulmod(h, C1, S, ltc_key.dp.A,
176 ltc_key.dp.prime, 1);
177 if (ltc_res != CRYPT_OK) {
178 res = TEE_ERROR_BAD_STATE;
179 goto out;
180 }
181
182 ltc_res = ltc_ecc_is_point_at_infinity(S, ltc_key.dp.prime,
183 &inf);
184 } else {
185 ltc_res = ltc_ecc_is_point_at_infinity(C1, ltc_key.dp.prime,
186 &inf);
187 }
188 if (ltc_res != CRYPT_OK || inf) {
189 res = TEE_ERROR_BAD_STATE;
190 goto out;
191 }
192
193 /* Step B3: (x2, y2) = [dB]C1 */
194
195 x2y2p = ltc_ecc_new_point();
196 if (!x2y2p) {
197 res = TEE_ERROR_OUT_OF_MEMORY;
198 goto out;
199 }
200
201 ltc_res = ltc_ecc_mulmod(ltc_key.k, C1, x2y2p, ltc_key.dp.A,
202 ltc_key.dp.prime, 1);
203 if (ltc_res != CRYPT_OK) {
204 res = TEE_ERROR_BAD_STATE;
205 goto out;
206 }
207
208 if (mp_unsigned_bin_size(x2y2p->x) > SM2_INT_SIZE_BYTES ||
209 mp_unsigned_bin_size(x2y2p->y) > SM2_INT_SIZE_BYTES) {
210 res = TEE_ERROR_BAD_STATE;
211 goto out;
212 }
213
214 mp_to_unsigned_bin2(x2y2p->x, x2y2, SM2_INT_SIZE_BYTES);
215 mp_to_unsigned_bin2(x2y2p->y, x2y2 + SM2_INT_SIZE_BYTES,
216 SM2_INT_SIZE_BYTES);
217
218 /* Step B4: t = KDF(x2 || y2, klen) */
219
220 /* C = C1 || C2 || C3 */
221 if (src_len <= C1_len + TEE_SM3_HASH_SIZE) {
222 res = TEE_ERROR_BAD_PARAMETERS;
223 goto out;
224 }
225
226 C2_len = src_len - C1_len - TEE_SM3_HASH_SIZE;
227
228 t = calloc(1, C2_len);
229 if (!t) {
230 res = TEE_ERROR_OUT_OF_MEMORY;
231 goto out;
232 }
233
234 res = sm2_kdf(x2y2, sizeof(x2y2), t, C2_len);
235 if (res)
236 goto out;
237
238 if (is_zero(t, C2_len)) {
239 res = TEE_ERROR_CIPHERTEXT_INVALID;
240 goto out;
241 }
242
243 /* Step B5: get C2 from C and compute Mprime = C2 (+) t */
244
245 out_len = MIN(*dst_len, C2_len);
246 for (i = 0; i < out_len; i++)
247 dst[i] = src[C1_len + i] ^ t[i];
248 *dst_len = out_len;
249 if (out_len < C2_len) {
250 eom = calloc(1, C2_len - out_len);
251 if (!eom) {
252 res = TEE_ERROR_OUT_OF_MEMORY;
253 goto out;
254 }
255 for (i = out_len; i < C2_len; i++)
256 eom[i - out_len] = src[C1_len + i] ^ t[i];
257 }
258
259 /* Step B6: compute u = Hash(x2 || M' || y2) and compare with C3 */
260
261 res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SM3);
262 if (res)
263 goto out;
264 res = crypto_hash_init(ctx);
265 if (res)
266 goto out;
267 res = crypto_hash_update(ctx, x2y2, SM2_INT_SIZE_BYTES);
268 if (res)
269 goto out;
270 res = crypto_hash_update(ctx, dst, out_len);
271 if (res)
272 goto out;
273 if (out_len < C2_len) {
274 res = crypto_hash_update(ctx, eom, C2_len - out_len);
275 if (res)
276 goto out;
277 }
278 res = crypto_hash_update(ctx, x2y2 + SM2_INT_SIZE_BYTES,
279 SM2_INT_SIZE_BYTES);
280 if (res)
281 goto out;
282 res = crypto_hash_final(ctx, u, sizeof(u));
283 if (res)
284 goto out;
285
286 if (consttime_memcmp(u, src + C1_len + C2_len, TEE_SM3_HASH_SIZE)) {
287 res = TEE_ERROR_CIPHERTEXT_INVALID;
288 goto out;
289 }
290 out:
291 free(eom);
292 free(t);
293 crypto_hash_free_ctx(ctx);
294 ltc_ecc_del_point(x2y2p);
295 ltc_ecc_del_point(S);
296 ltc_ecc_del_point(C1);
297 mp_clear_multi(h, NULL);
298 ecc_free(<c_key);
299 return res;
300 }
301
302 /*
303 * GM/T 0003.1‒2012 Part 1 Section 4.2.8
304 * Conversion of point @p to a byte string @buf (uncompressed form).
305 */
sm2_point_to_bytes(uint8_t * buf,size_t * size,const ecc_point * p)306 static TEE_Result sm2_point_to_bytes(uint8_t *buf, size_t *size,
307 const ecc_point *p)
308 {
309 size_t xsize = mp_unsigned_bin_size(p->x);
310 size_t ysize = mp_unsigned_bin_size(p->y);
311 size_t sz = 2 * SM2_INT_SIZE_BYTES + 1;
312
313 if (xsize > SM2_INT_SIZE_BYTES || ysize > SM2_INT_SIZE_BYTES ||
314 *size < sz)
315 return TEE_ERROR_BAD_STATE;
316
317 memset(buf, 0, sz);
318 buf[0] = 0x04; /* Uncompressed form indicator */
319 mp_to_unsigned_bin2(p->x, buf + 1, SM2_INT_SIZE_BYTES);
320 mp_to_unsigned_bin2(p->y, buf + 1 + SM2_INT_SIZE_BYTES,
321 SM2_INT_SIZE_BYTES);
322
323 *size = sz;
324
325 return TEE_SUCCESS;
326 }
327
328 /*
329 * GM/T 0003.1‒2012 Part 4 Section 6.1
330 * Encryption algorithm
331 */
sm2_ltc_pke_encrypt(struct ecc_public_key * key,const uint8_t * src,size_t src_len,uint8_t * dst,size_t * dst_len)332 TEE_Result sm2_ltc_pke_encrypt(struct ecc_public_key *key, const uint8_t *src,
333 size_t src_len, uint8_t *dst, size_t *dst_len)
334 {
335 TEE_Result res = TEE_SUCCESS;
336 ecc_key ltc_key = { };
337 ecc_point *x2y2p = NULL;
338 ecc_point *C1 = NULL;
339 ecc_point *S = NULL;
340 uint8_t x2y2[64] = { };
341 uint8_t *t = NULL;
342 int ltc_res = 0;
343 void *k = NULL;
344 void *h = NULL;
345 int inf = 0;
346 size_t C1_len = 0;
347 void *ctx = NULL;
348 size_t i = 0;
349
350 ltc_res = mp_init_multi(&k, &h, NULL);
351 if (ltc_res != CRYPT_OK)
352 return TEE_ERROR_OUT_OF_MEMORY;
353
354 res = ecc_populate_ltc_public_key(<c_key, key, TEE_ALG_SM2_PKE, NULL);
355 if (res)
356 goto out;
357
358 /* Step A1: generate random number 1 <= k < n */
359
360 ltc_res = rand_bn_upto(k, ltc_key.dp.order, NULL,
361 find_prng("prng_crypto"));
362 if (ltc_res != CRYPT_OK) {
363 res = TEE_ERROR_BAD_STATE;
364 goto out;
365 }
366
367 /* Step A2: compute C1 = [k]G */
368
369 C1 = ltc_ecc_new_point();
370 if (!C1) {
371 res = TEE_ERROR_OUT_OF_MEMORY;
372 goto out;
373 }
374
375 ltc_res = ltc_ecc_mulmod(k, <c_key.dp.base, C1, ltc_key.dp.A,
376 ltc_key.dp.prime, 1);
377 if (ltc_res != CRYPT_OK) {
378 res = TEE_ERROR_BAD_STATE;
379 goto out;
380 }
381
382 /* Step A3: compute S = [h]PB and check for infinity */
383
384 if (ltc_key.dp.cofactor != 1) {
385 S = ltc_ecc_new_point();
386 if (!S) {
387 res = TEE_ERROR_OUT_OF_MEMORY;
388 goto out;
389 }
390
391 ltc_res = mp_set_int(h, ltc_key.dp.cofactor);
392 if (ltc_res != CRYPT_OK) {
393 res = TEE_ERROR_BAD_STATE;
394 goto out;
395 }
396
397 ltc_res = ltc_ecc_mulmod(h, <c_key.pubkey, S, ltc_key.dp.A,
398 ltc_key.dp.prime, 1);
399 if (ltc_res != CRYPT_OK) {
400 res = TEE_ERROR_BAD_STATE;
401 goto out;
402 }
403
404 ltc_res = ltc_ecc_is_point_at_infinity(S, ltc_key.dp.prime,
405 &inf);
406 } else {
407 ltc_res = ltc_ecc_is_point_at_infinity(<c_key.pubkey,
408 ltc_key.dp.prime, &inf);
409 }
410 if (ltc_res != CRYPT_OK) {
411 res = TEE_ERROR_BAD_STATE;
412 goto out;
413 }
414 if (inf) {
415 res = TEE_ERROR_BAD_STATE;
416 goto out;
417 }
418
419 /* Step A4: compute (x2, y2) = [k]PB */
420
421 x2y2p = ltc_ecc_new_point();
422 if (!x2y2p) {
423 res = TEE_ERROR_OUT_OF_MEMORY;
424 goto out;
425 }
426
427 ltc_res = ltc_ecc_mulmod(k, <c_key.pubkey, x2y2p, ltc_key.dp.A,
428 ltc_key.dp.prime, 1);
429 if (ltc_res != CRYPT_OK) {
430 res = TEE_ERROR_BAD_STATE;
431 goto out;
432 }
433
434 if (mp_unsigned_bin_size(x2y2p->x) > SM2_INT_SIZE_BYTES ||
435 mp_unsigned_bin_size(x2y2p->y) > SM2_INT_SIZE_BYTES) {
436 res = TEE_ERROR_BAD_STATE;
437 goto out;
438 }
439
440 mp_to_unsigned_bin2(x2y2p->x, x2y2, SM2_INT_SIZE_BYTES);
441 mp_to_unsigned_bin2(x2y2p->y, x2y2 + SM2_INT_SIZE_BYTES,
442 SM2_INT_SIZE_BYTES);
443
444 /* Step A5: compute t = KDF(x2 || y2, klen) */
445
446 t = calloc(1, src_len);
447 if (!t) {
448 res = TEE_ERROR_OUT_OF_MEMORY;
449 goto out;
450 }
451
452 res = sm2_kdf(x2y2, sizeof(x2y2), t, src_len);
453 if (res)
454 goto out;
455
456 if (is_zero(t, src_len)) {
457 res = TEE_ERROR_CIPHERTEXT_INVALID;
458 goto out;
459 }
460
461 /*
462 * Steps A6, A7, A8:
463 * Compute C2 = M (+) t
464 * Compute C3 = Hash(x2 || M || y2)
465 * Output C = C1 || C2 || C3
466 */
467
468 /* C1 */
469 C1_len = *dst_len;
470 res = sm2_point_to_bytes(dst, &C1_len, C1);
471 if (res)
472 goto out;
473
474 if (*dst_len < C1_len + src_len + TEE_SM3_HASH_SIZE) {
475 *dst_len = C1_len + src_len + TEE_SM3_HASH_SIZE;
476 res = TEE_ERROR_SHORT_BUFFER;
477 goto out;
478 }
479
480 /* C2 */
481 for (i = 0; i < src_len; i++)
482 dst[i + C1_len] = src[i] ^ t[i];
483
484 /* C3 */
485 res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SM3);
486 if (res)
487 goto out;
488 res = crypto_hash_init(ctx);
489 if (res)
490 goto out;
491 res = crypto_hash_update(ctx, x2y2, SM2_INT_SIZE_BYTES);
492 if (res)
493 goto out;
494 res = crypto_hash_update(ctx, src, src_len);
495 if (res)
496 goto out;
497 res = crypto_hash_update(ctx, x2y2 + SM2_INT_SIZE_BYTES,
498 SM2_INT_SIZE_BYTES);
499 if (res)
500 goto out;
501 res = crypto_hash_final(ctx, dst + C1_len + src_len, TEE_SM3_HASH_SIZE);
502 if (res)
503 goto out;
504
505 *dst_len = C1_len + src_len + TEE_SM3_HASH_SIZE;
506 out:
507 crypto_hash_free_ctx(ctx);
508 free(t);
509 ltc_ecc_del_point(x2y2p);
510 ltc_ecc_del_point(S);
511 ltc_ecc_del_point(C1);
512 ecc_free(<c_key);
513 mp_clear_multi(k, h, NULL);
514 return res;
515 }
516