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