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