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(&ltc_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, &ltc_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(&ltc_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(&ltc_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, &ltc_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, &ltc_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(&ltc_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, &ltc_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(&ltc_key);
513 	mp_clear_multi(k, h, NULL);
514 	return res;
515 }
516