1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2020-21 Huawei Technologies Co., Ltd
4  */
5 
6 #include <crypto/crypto.h>
7 #include <crypto/sm2-kdf.h>
8 #include <mbedtls/bignum.h>
9 #include <mbedtls/ecp.h>
10 #include <string_ext.h>
11 #include <tee_api_types.h>
12 #include <utee_defines.h>
13 
14 #include "mbed_helpers.h"
15 
16 /* SM2 uses 256 bit unsigned integers in big endian format */
17 #define SM2_INT_SIZE_BYTES 32
18 
19 /* The public x and y values extracted from a public or private ECC key */
20 struct key_xy {
21 	mbedtls_mpi *x;
22 	mbedtls_mpi *y;
23 };
24 
25 /*
26  * Compute a hash of a user's identity and public key
27  * For user A: ZA = SM3(ENTLA || IDA || a || b || xG || yG || xA || yA)
28  */
sm2_kep_compute_Z(const mbedtls_ecp_group * grp,uint8_t * Z,size_t Zlen,const uint8_t * id,size_t idlen,struct key_xy * key)29 static TEE_Result sm2_kep_compute_Z(const mbedtls_ecp_group *grp, uint8_t *Z,
30 				    size_t Zlen, const uint8_t *id,
31 				    size_t idlen, struct key_xy *key)
32 {
33 	TEE_Result res = TEE_ERROR_GENERIC;
34 	uint8_t ENTLEN[2] = { };
35 	uint8_t buf[SM2_INT_SIZE_BYTES] = { };
36 	void *ctx = NULL;
37 	int mres = 0;
38 
39 	if (Zlen < TEE_SM3_HASH_SIZE)
40 		return TEE_ERROR_SHORT_BUFFER;
41 
42 	/*
43 	 * ENTLEN is the length in bits if the user's distinguished identifier
44 	 * encoded over 16 bits in big endian format.
45 	 */
46 	ENTLEN[0] = (idlen * 8) >> 8;
47 	ENTLEN[1] = idlen * 8;
48 
49 	res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SM3);
50 	if (res)
51 		goto out;
52 
53 	res = crypto_hash_init(ctx);
54 	if (res)
55 		goto out;
56 
57 	res = crypto_hash_update(ctx, ENTLEN, sizeof(ENTLEN));
58 	if (res)
59 		goto out;
60 
61 	res = crypto_hash_update(ctx, id, idlen);
62 	if (res)
63 		goto out;
64 
65 	mres = mbedtls_mpi_write_binary(&grp->A, buf, SM2_INT_SIZE_BYTES);
66 	if (mres) {
67 		res = TEE_ERROR_GENERIC;
68 		goto out;
69 	}
70 	res = crypto_hash_update(ctx, buf, sizeof(buf));
71 	if (res)
72 		goto out;
73 
74 	mres = mbedtls_mpi_write_binary(&grp->B, buf, SM2_INT_SIZE_BYTES);
75 	if (mres) {
76 		res = TEE_ERROR_GENERIC;
77 		goto out;
78 	}
79 	res = crypto_hash_update(ctx, buf, sizeof(buf));
80 	if (res)
81 		goto out;
82 
83 	mres = mbedtls_mpi_write_binary(&grp->G.X, buf, SM2_INT_SIZE_BYTES);
84 	if (mres) {
85 		res = TEE_ERROR_GENERIC;
86 		goto out;
87 	}
88 	res = crypto_hash_update(ctx, buf, sizeof(buf));
89 	if (res)
90 		goto out;
91 
92 	mres = mbedtls_mpi_write_binary(&grp->G.Y, buf, SM2_INT_SIZE_BYTES);
93 	if (mres) {
94 		res = TEE_ERROR_GENERIC;
95 		goto out;
96 	}
97 	res = crypto_hash_update(ctx, buf, sizeof(buf));
98 	if (res)
99 		goto out;
100 
101 	mres = mbedtls_mpi_write_binary(key->x, buf, SM2_INT_SIZE_BYTES);
102 	if (mres) {
103 		res = TEE_ERROR_GENERIC;
104 		goto out;
105 	}
106 	res = crypto_hash_update(ctx, buf, sizeof(buf));
107 	if (res)
108 		goto out;
109 
110 	mres = mbedtls_mpi_write_binary(key->y, buf, SM2_INT_SIZE_BYTES);
111 	if (mres) {
112 		res = TEE_ERROR_GENERIC;
113 		goto out;
114 	}
115 	res = crypto_hash_update(ctx, buf, sizeof(buf));
116 	if (res)
117 		goto out;
118 
119 	res = crypto_hash_final(ctx, Z, TEE_SM3_HASH_SIZE);
120 out:
121 	crypto_hash_free_ctx(ctx);
122 	return res;
123 }
124 
125 /*
126  * Compute a verification value, to be checked against the value sent by the
127  * peer.
128  * On the initiator's side:
129  *   S1 = SM3(0x02 || yU || SM3(xU || ZA || ZB || x1 || y1 || x2 || y2))
130  * On the responder's side:
131  *   S2 = SM3(0x03 || yV || SM3(xV || ZA || ZB || x1 || y1 || x2 || y2))
132  */
sm2_kep_compute_S(uint8_t * S,size_t S_len,uint8_t flag,mbedtls_ecp_point * UV,const uint8_t * ZAZB,size_t ZAZB_len,struct key_xy * initiator_eph_key,struct key_xy * responder_eph_key)133 static TEE_Result sm2_kep_compute_S(uint8_t *S, size_t S_len, uint8_t flag,
134 				    mbedtls_ecp_point *UV, const uint8_t *ZAZB,
135 				    size_t ZAZB_len,
136 				    struct key_xy *initiator_eph_key,
137 				    struct key_xy *responder_eph_key)
138 {
139 	uint8_t hash[TEE_SM3_HASH_SIZE] = { };
140 	TEE_Result res = TEE_ERROR_GENERIC;
141 	uint8_t buf[SM2_INT_SIZE_BYTES];
142 	void *ctx = NULL;
143 	int mres = 0;
144 
145 	if (S_len < TEE_SM3_HASH_SIZE)
146 		return TEE_ERROR_SHORT_BUFFER;
147 
148 	res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SM3);
149 	if (res)
150 		goto out;
151 
152 	/* Compute the inner hash */
153 
154 	res = crypto_hash_init(ctx);
155 	if (res)
156 		goto out;
157 
158 	/* xU or xV */
159 	mres = mbedtls_mpi_write_binary(&UV->X, buf, SM2_INT_SIZE_BYTES);
160 	if (mres) {
161 		res = TEE_ERROR_GENERIC;
162 		goto out;
163 	}
164 	res = crypto_hash_update(ctx, buf, sizeof(buf));
165 	if (res)
166 		goto out;
167 
168 	/* ZA || ZB */
169 	res = crypto_hash_update(ctx, ZAZB, ZAZB_len);
170 	if (res)
171 		goto out;
172 
173 	/* x1 */
174 	mres = mbedtls_mpi_write_binary(initiator_eph_key->x, buf,
175 					SM2_INT_SIZE_BYTES);
176 	if (mres) {
177 		res = TEE_ERROR_GENERIC;
178 		goto out;
179 	}
180 	res = crypto_hash_update(ctx, buf, sizeof(buf));
181 	if (res)
182 		goto out;
183 
184 	/* y1 */
185 	mres = mbedtls_mpi_write_binary(initiator_eph_key->y, buf,
186 					SM2_INT_SIZE_BYTES);
187 	if (mres) {
188 		res = TEE_ERROR_GENERIC;
189 		goto out;
190 	}
191 	res = crypto_hash_update(ctx, buf, sizeof(buf));
192 	if (res)
193 		goto out;
194 
195 	/* x2 */
196 	mres = mbedtls_mpi_write_binary(responder_eph_key->x, buf,
197 					SM2_INT_SIZE_BYTES);
198 	if (mres) {
199 		res = TEE_ERROR_GENERIC;
200 		goto out;
201 	}
202 	res = crypto_hash_update(ctx, buf, sizeof(buf));
203 	if (res)
204 		goto out;
205 
206 	/* y2 */
207 	mres = mbedtls_mpi_write_binary(responder_eph_key->y, buf,
208 					SM2_INT_SIZE_BYTES);
209 	if (mres) {
210 		res = TEE_ERROR_GENERIC;
211 		goto out;
212 	}
213 	res = crypto_hash_update(ctx, buf, sizeof(buf));
214 	if (res)
215 		goto out;
216 
217 	res = crypto_hash_final(ctx, hash, sizeof(hash));
218 	if (res)
219 		goto out;
220 
221 	/* Now compute S */
222 
223 	res = crypto_hash_init(ctx);
224 	if (res)
225 		goto out;
226 
227 	/* 0x02 or 0x03  */
228 	res = crypto_hash_update(ctx, &flag, sizeof(flag));
229 	if (res)
230 		goto out;
231 
232 	/* yU or yV */
233 	mres = mbedtls_mpi_write_binary(&UV->Y, buf, SM2_INT_SIZE_BYTES);
234 	if (mres) {
235 		res = TEE_ERROR_GENERIC;
236 		goto out;
237 	}
238 	res = crypto_hash_update(ctx, buf, sizeof(buf));
239 	if (res)
240 		goto out;
241 
242 	/* Inner SM3(...) */
243 	res = crypto_hash_update(ctx, hash, sizeof(hash));
244 	if (res)
245 		goto out;
246 
247 	res = crypto_hash_final(ctx, S, TEE_SM3_HASH_SIZE);
248 
249 out:
250 	crypto_hash_free_ctx(ctx);
251 	return res;
252 
253 }
254 
extract_xy_from_keypair(struct key_xy * xy,const struct ecc_keypair * pair)255 static void extract_xy_from_keypair(struct key_xy *xy,
256 				    const struct ecc_keypair *pair)
257 {
258 	xy->x = (mbedtls_mpi *)pair->x;
259 	xy->y = (mbedtls_mpi *)pair->y;
260 	/* Other fields are not used */
261 }
262 
extract_xy_from_public_key(struct key_xy * xy,const struct ecc_public_key * from)263 static void extract_xy_from_public_key(struct key_xy *xy,
264 				       const struct ecc_public_key *from)
265 {
266 	xy->x = (mbedtls_mpi *)from->x;
267 	xy->y = (mbedtls_mpi *)from->y;
268 }
269 
270 /*
271  * GM/T 0003.1‒2012 Part 3 Section 6.1
272  * Key exchange protocol
273  */
crypto_acipher_sm2_kep_derive(struct ecc_keypair * my_key,struct ecc_keypair * my_eph_key,struct ecc_public_key * peer_key,struct ecc_public_key * peer_eph_key,struct sm2_kep_parms * p)274 TEE_Result crypto_acipher_sm2_kep_derive(struct ecc_keypair *my_key,
275 					 struct ecc_keypair *my_eph_key,
276 					 struct ecc_public_key *peer_key,
277 					 struct ecc_public_key *peer_eph_key,
278 					 struct sm2_kep_parms *p)
279 {
280 	/*
281 	 * Variable names and documented steps reflect the initator side (user A
282 	 * in the spec), but the other side is quite similar hence only one
283 	 * function.
284 	 */
285 	uint8_t xUyUZAZB[2 * SM2_INT_SIZE_BYTES + 2 * TEE_SM3_HASH_SIZE] = { };
286 	struct key_xy initiator_eph_key = { };
287 	struct key_xy responder_eph_key = { };
288 	struct key_xy initiator_key = { };
289 	struct key_xy responder_key = { };
290 	TEE_Result res = TEE_ERROR_BAD_STATE;
291 	uint8_t tmp[SM2_INT_SIZE_BYTES] = { };
292 	mbedtls_ecp_group grp = { };
293 	mbedtls_ecp_point PB = { };
294 	mbedtls_ecp_point RB = { };
295 	mbedtls_ecp_point U = { };
296 	mbedtls_mpi x1bar = { };
297 	mbedtls_mpi x2bar = { };
298 	mbedtls_mpi tA = { };
299 	mbedtls_mpi h = { };
300 	mbedtls_mpi htA = { };
301 	mbedtls_mpi one = { };
302 	int mres = 0;
303 
304 	if (p->is_initiator) {
305 		extract_xy_from_keypair(&initiator_eph_key, my_eph_key);
306 		extract_xy_from_public_key(&responder_eph_key, peer_eph_key);
307 		extract_xy_from_keypair(&initiator_key, my_key);
308 		extract_xy_from_public_key(&responder_key, peer_key);
309 	} else {
310 		extract_xy_from_public_key(&initiator_eph_key, peer_eph_key);
311 		extract_xy_from_keypair(&responder_eph_key, my_eph_key);
312 		extract_xy_from_public_key(&initiator_key, peer_key);
313 		extract_xy_from_keypair(&responder_key, my_key);
314 	}
315 
316 	mbedtls_mpi_init(&x1bar);
317 	mbedtls_mpi_init(&x2bar);
318 	mbedtls_mpi_init(&tA);
319 	mbedtls_mpi_init(&h);
320 	mbedtls_mpi_init(&htA);
321 	mbedtls_mpi_init(&one);
322 
323 	mbedtls_ecp_point_init(&PB);
324 	mbedtls_ecp_point_init(&RB);
325 	mbedtls_ecp_point_init(&U);
326 
327 	mbedtls_ecp_group_init(&grp);
328 	mres = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SM2);
329 	if (mres)
330 		goto out;
331 
332 	/*
333 	 * Steps A1-A3 are supposedly done already (generate ephemeral key, send
334 	 * it to peer).
335 	 * Step A4: (x1, y1) = RA; x1bar = 2^w + (x1 & (2^w - 1))
336 	 */
337 
338 	mres = mbedtls_mpi_write_binary((mbedtls_mpi *)my_eph_key->x, tmp,
339 					SM2_INT_SIZE_BYTES);
340 	if (mres)
341 		goto out;
342 	tmp[SM2_INT_SIZE_BYTES / 2] |= 0x80;
343 	mres = mbedtls_mpi_read_binary(&x1bar,  tmp + SM2_INT_SIZE_BYTES / 2,
344 				       SM2_INT_SIZE_BYTES / 2);
345 	if (mres)
346 		goto out;
347 
348 	/* Step A5: tA = (dA + x1bar * rA) mod n */
349 
350 	mres = mbedtls_mpi_mul_mpi(&tA, &x1bar, (mbedtls_mpi *)my_eph_key->d);
351 	if (mres)
352 		goto out;
353 	mres = mbedtls_mpi_mod_mpi(&tA, &tA, &grp.N);
354 	if (mres)
355 		goto out;
356 	mres = mbedtls_mpi_add_mpi(&tA, &tA, (mbedtls_mpi *)my_key->d);
357 	if (mres)
358 		goto out;
359 	mres = mbedtls_mpi_mod_mpi(&tA, &tA, &grp.N);
360 	if (mres)
361 		goto out;
362 
363 	/* Step A6: verify whether RB verifies the curve equation */
364 
365 	mbedtls_mpi_copy(&RB.X, (mbedtls_mpi *)peer_eph_key->x);
366 	mbedtls_mpi_copy(&RB.Y, (mbedtls_mpi *)peer_eph_key->y);
367 	mbedtls_mpi_lset(&RB.Z, 1);
368 	mres = mbedtls_ecp_check_pubkey(&grp, &RB);
369 	if (mres)
370 		goto out;
371 
372 	/* Step A6 (continued): (x2, y2) = RB; x2bar = 2^w + (x2 & (2^w - 1)) */
373 
374 	mres = mbedtls_mpi_write_binary((mbedtls_mpi *)peer_eph_key->x, tmp,
375 					SM2_INT_SIZE_BYTES);
376 	if (mres)
377 		goto out;
378 	tmp[SM2_INT_SIZE_BYTES / 2] |= 0x80;
379 	mres = mbedtls_mpi_read_binary(&x2bar,  tmp + SM2_INT_SIZE_BYTES / 2,
380 				SM2_INT_SIZE_BYTES / 2);
381 	if (mres)
382 		goto out;
383 
384 	/* Step A7: compute U = [h.tA](PB + [x2bar]RB) and check for infinity */
385 
386 	mres = mbedtls_mpi_copy(&PB.X, (mbedtls_mpi *)peer_key->x);
387 	if (mres)
388 		goto out;
389 	mres = mbedtls_mpi_copy(&PB.Y, (mbedtls_mpi *)peer_key->y);
390 	if (mres)
391 		goto out;
392 	mres = mbedtls_mpi_lset(&PB.Z, 1);
393 	if (mres)
394 		goto out;
395 	mres = mbedtls_mpi_lset(&one, 1);
396 	if (mres)
397 		goto out;
398 
399 	mres = mbedtls_ecp_muladd(&grp, &U, &one, &PB, &x2bar, &RB);
400 	if (mres)
401 		goto out;
402 
403 	/* Note: the cofactor for SM2 is 1 so [h.tA] == tA */
404 	mres = mbedtls_ecp_mul(&grp, &U, &tA, &U, mbd_rand, NULL);
405 	if (mres)
406 		goto out;
407 
408 	/*
409 	 * "Point is zero" is same as "point is at infinity". Returns 1 if
410 	 * point is zero, < 0 on error and 0 if point is non-zero.
411 	 */
412 	mres = mbedtls_ecp_is_zero(&U);
413 	if (mres)
414 		goto out;
415 
416 	/* Step A8: compute KA = KDF(xU || yU || ZA || ZB, klen) */
417 
418 	/* xU */
419 	mres = mbedtls_mpi_write_binary(&U.X, xUyUZAZB, SM2_INT_SIZE_BYTES);
420 	if (mres)
421 		goto out;
422 
423 	/* yU */
424 	mres = mbedtls_mpi_write_binary(&U.Y, xUyUZAZB + SM2_INT_SIZE_BYTES,
425 					SM2_INT_SIZE_BYTES);
426 	if (mres)
427 		goto out;
428 
429 	/* ZA */
430 	res = sm2_kep_compute_Z(&grp, xUyUZAZB + 2 * SM2_INT_SIZE_BYTES,
431 				TEE_SM3_HASH_SIZE, p->initiator_id,
432 				p->initiator_id_len, &initiator_key);
433 	if (res)
434 		goto out;
435 
436 	/* ZB */
437 	res = sm2_kep_compute_Z(&grp, xUyUZAZB + 2 * SM2_INT_SIZE_BYTES +
438 					TEE_SM3_HASH_SIZE,
439 				TEE_SM3_HASH_SIZE, p->responder_id,
440 				p->responder_id_len, &responder_key);
441 	if (res)
442 		goto out;
443 
444 	res = sm2_kdf(xUyUZAZB, sizeof(xUyUZAZB), p->out, p->out_len);
445 	if (res)
446 		goto out;
447 
448 	/* Step A9: compute S1 and check S1 == SB */
449 
450 	if (p->conf_in) {
451 		uint8_t S1[TEE_SM3_HASH_SIZE] = { };
452 		uint8_t flag = p->is_initiator ? 0x02 : 0x03;
453 
454 		if (p->conf_in_len < TEE_SM3_HASH_SIZE) {
455 			res = TEE_ERROR_BAD_PARAMETERS;
456 			goto out;
457 		}
458 		res = sm2_kep_compute_S(S1, sizeof(S1), flag, &U,
459 					xUyUZAZB + 2 * SM2_INT_SIZE_BYTES,
460 					2 * SM2_INT_SIZE_BYTES,
461 					&initiator_eph_key, &responder_eph_key);
462 		if (res)
463 			goto out;
464 
465 		if (consttime_memcmp(S1, p->conf_in, sizeof(S1))) {
466 			/* Verification failed */
467 			res = TEE_ERROR_BAD_STATE;
468 			goto out;
469 		}
470 	}
471 
472 	/* Step A10: compute SA */
473 
474 	if (p->conf_out) {
475 		uint8_t flag = p->is_initiator ? 0x03 : 0x02;
476 
477 		if (p->conf_out_len < TEE_SM3_HASH_SIZE) {
478 			res = TEE_ERROR_BAD_PARAMETERS;
479 			goto out;
480 		}
481 
482 		res = sm2_kep_compute_S(p->conf_out, TEE_SM3_HASH_SIZE, flag,
483 					&U, xUyUZAZB + 2 * SM2_INT_SIZE_BYTES,
484 					2 * SM2_INT_SIZE_BYTES,
485 					&initiator_eph_key, &responder_eph_key);
486 	}
487 out:
488 	mbedtls_mpi_free(&x1bar);
489 	mbedtls_mpi_free(&x2bar);
490 	mbedtls_mpi_free(&tA);
491 	mbedtls_mpi_free(&h);
492 	mbedtls_mpi_free(&htA);
493 	mbedtls_mpi_free(&one);
494 	mbedtls_ecp_point_free(&PB);
495 	mbedtls_ecp_point_free(&RB);
496 	mbedtls_ecp_point_free(&U);
497 	mbedtls_ecp_group_free(&grp);
498 	return res;
499 }
500