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