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