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