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