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