xref: /optee_os/core/lib/libtomcrypt/sm2-kep.c (revision c2c877db0f5e24a3e7720ff71b320facce823999)
1*c2c877dbSJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
2*c2c877dbSJerome Forissier /*
3*c2c877dbSJerome Forissier  * Copyright (c) 2020 Huawei Technologies Co., Ltd
4*c2c877dbSJerome Forissier  */
5*c2c877dbSJerome Forissier 
6*c2c877dbSJerome Forissier #include <crypto/crypto.h>
7*c2c877dbSJerome Forissier #include <stdlib.h>
8*c2c877dbSJerome Forissier #include <string.h>
9*c2c877dbSJerome Forissier #include <string_ext.h>
10*c2c877dbSJerome Forissier #include <tee_api_types.h>
11*c2c877dbSJerome Forissier #include <tee/tee_cryp_utl.h>
12*c2c877dbSJerome Forissier #include <util.h>
13*c2c877dbSJerome Forissier #include <utee_defines.h>
14*c2c877dbSJerome Forissier 
15*c2c877dbSJerome Forissier #include "acipher_helpers.h"
16*c2c877dbSJerome Forissier 
17*c2c877dbSJerome Forissier /* SM2 uses 256 bit unsigned integers in big endian format */
18*c2c877dbSJerome Forissier #define SM2_INT_SIZE_BYTES 32
19*c2c877dbSJerome Forissier 
20*c2c877dbSJerome Forissier /*
21*c2c877dbSJerome Forissier  * Compute a hash of a user's identity and public key
22*c2c877dbSJerome Forissier  * For user A: ZA = SM3(ENTLA || IDA || a || b || xG || yG || xA || yA)
23*c2c877dbSJerome Forissier  */
24*c2c877dbSJerome Forissier static TEE_Result sm2_kep_compute_Z(uint8_t *Z, size_t Zlen, const uint8_t *id,
25*c2c877dbSJerome Forissier 				    size_t idlen, const ecc_key *key)
26*c2c877dbSJerome Forissier {
27*c2c877dbSJerome Forissier 	TEE_Result res = TEE_ERROR_GENERIC;
28*c2c877dbSJerome Forissier 	uint8_t ENTLEN[2] = { };
29*c2c877dbSJerome Forissier 	uint8_t buf[SM2_INT_SIZE_BYTES];
30*c2c877dbSJerome Forissier 	void *ctx = NULL;
31*c2c877dbSJerome Forissier 
32*c2c877dbSJerome Forissier 	if (Zlen < TEE_SM3_HASH_SIZE)
33*c2c877dbSJerome Forissier 		return TEE_ERROR_SHORT_BUFFER;
34*c2c877dbSJerome Forissier 
35*c2c877dbSJerome Forissier 	/*
36*c2c877dbSJerome Forissier 	 * ENTLEN is the length in bits if the user's distinguished identifier
37*c2c877dbSJerome Forissier 	 * encoded over 16 bits in big endian format.
38*c2c877dbSJerome Forissier 	 */
39*c2c877dbSJerome Forissier 	ENTLEN[0] = (idlen * 8) >> 8;
40*c2c877dbSJerome Forissier 	ENTLEN[1] = idlen * 8;
41*c2c877dbSJerome Forissier 
42*c2c877dbSJerome Forissier 	res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SM3);
43*c2c877dbSJerome Forissier 	if (res)
44*c2c877dbSJerome Forissier 		goto out;
45*c2c877dbSJerome Forissier 
46*c2c877dbSJerome Forissier 	res = crypto_hash_init(ctx);
47*c2c877dbSJerome Forissier 	if (res)
48*c2c877dbSJerome Forissier 		goto out;
49*c2c877dbSJerome Forissier 
50*c2c877dbSJerome Forissier 	res = crypto_hash_update(ctx, ENTLEN, sizeof(ENTLEN));
51*c2c877dbSJerome Forissier 	if (res)
52*c2c877dbSJerome Forissier 		goto out;
53*c2c877dbSJerome Forissier 
54*c2c877dbSJerome Forissier 	res = crypto_hash_update(ctx, id, idlen);
55*c2c877dbSJerome Forissier 	if (res)
56*c2c877dbSJerome Forissier 		goto out;
57*c2c877dbSJerome Forissier 
58*c2c877dbSJerome Forissier 	mp_to_unsigned_bin2(key->dp.A, buf, SM2_INT_SIZE_BYTES);
59*c2c877dbSJerome Forissier 	res = crypto_hash_update(ctx, buf, sizeof(buf));
60*c2c877dbSJerome Forissier 	if (res)
61*c2c877dbSJerome Forissier 		goto out;
62*c2c877dbSJerome Forissier 
63*c2c877dbSJerome Forissier 	mp_to_unsigned_bin2(key->dp.B, buf, SM2_INT_SIZE_BYTES);
64*c2c877dbSJerome Forissier 	res = crypto_hash_update(ctx, buf, sizeof(buf));
65*c2c877dbSJerome Forissier 	if (res)
66*c2c877dbSJerome Forissier 		goto out;
67*c2c877dbSJerome Forissier 
68*c2c877dbSJerome Forissier 	mp_to_unsigned_bin2(key->dp.base.x, buf, SM2_INT_SIZE_BYTES);
69*c2c877dbSJerome Forissier 	res = crypto_hash_update(ctx, buf, sizeof(buf));
70*c2c877dbSJerome Forissier 	if (res)
71*c2c877dbSJerome Forissier 		goto out;
72*c2c877dbSJerome Forissier 
73*c2c877dbSJerome Forissier 	mp_to_unsigned_bin2(key->dp.base.y, buf, SM2_INT_SIZE_BYTES);
74*c2c877dbSJerome Forissier 	res = crypto_hash_update(ctx, buf, sizeof(buf));
75*c2c877dbSJerome Forissier 	if (res)
76*c2c877dbSJerome Forissier 		goto out;
77*c2c877dbSJerome Forissier 
78*c2c877dbSJerome Forissier 	mp_to_unsigned_bin2(key->pubkey.x, buf, SM2_INT_SIZE_BYTES);
79*c2c877dbSJerome Forissier 	res = crypto_hash_update(ctx, buf, sizeof(buf));
80*c2c877dbSJerome Forissier 	if (res)
81*c2c877dbSJerome Forissier 		goto out;
82*c2c877dbSJerome Forissier 
83*c2c877dbSJerome Forissier 	mp_to_unsigned_bin2(key->pubkey.y, buf, SM2_INT_SIZE_BYTES);
84*c2c877dbSJerome Forissier 	res = crypto_hash_update(ctx, buf, sizeof(buf));
85*c2c877dbSJerome Forissier 	if (res)
86*c2c877dbSJerome Forissier 		goto out;
87*c2c877dbSJerome Forissier 
88*c2c877dbSJerome Forissier 	res = crypto_hash_final(ctx, Z, TEE_SM3_HASH_SIZE);
89*c2c877dbSJerome Forissier out:
90*c2c877dbSJerome Forissier 	crypto_hash_free_ctx(ctx);
91*c2c877dbSJerome Forissier 	return res;
92*c2c877dbSJerome Forissier }
93*c2c877dbSJerome Forissier 
94*c2c877dbSJerome Forissier /*
95*c2c877dbSJerome Forissier  * Compute a verification value, to be checked against the value sent by the
96*c2c877dbSJerome Forissier  * peer.
97*c2c877dbSJerome Forissier  * On the initiator's side:
98*c2c877dbSJerome Forissier  *   S1 = SM3(0x02 || yU || SM3(xU || ZA || ZB || x1 || y1 || x2 || y2))
99*c2c877dbSJerome Forissier  * On the responder's side:
100*c2c877dbSJerome Forissier  *   S2 = SM3(0x03 || yV || SM3(xV || ZA || ZB || x1 || y1 || x2 || y2))
101*c2c877dbSJerome Forissier  */
102*c2c877dbSJerome Forissier static TEE_Result sm2_kep_compute_S(uint8_t *S, size_t S_len, uint8_t flag,
103*c2c877dbSJerome Forissier 				    ecc_point *UV, const uint8_t *ZAZB,
104*c2c877dbSJerome Forissier 				    size_t ZAZB_len, ecc_key *initiator_eph_key,
105*c2c877dbSJerome Forissier 				    ecc_key *responder_eph_key)
106*c2c877dbSJerome Forissier {
107*c2c877dbSJerome Forissier 	uint8_t hash[TEE_SM3_HASH_SIZE] = { };
108*c2c877dbSJerome Forissier 	TEE_Result res = TEE_ERROR_GENERIC;
109*c2c877dbSJerome Forissier 	uint8_t buf[SM2_INT_SIZE_BYTES];
110*c2c877dbSJerome Forissier 	void *ctx = NULL;
111*c2c877dbSJerome Forissier 
112*c2c877dbSJerome Forissier 	if (S_len < TEE_SM3_HASH_SIZE)
113*c2c877dbSJerome Forissier 		return TEE_ERROR_SHORT_BUFFER;
114*c2c877dbSJerome Forissier 
115*c2c877dbSJerome Forissier 	res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SM3);
116*c2c877dbSJerome Forissier 	if (res)
117*c2c877dbSJerome Forissier 		goto out;
118*c2c877dbSJerome Forissier 
119*c2c877dbSJerome Forissier 	/* Compute the inner hash */
120*c2c877dbSJerome Forissier 
121*c2c877dbSJerome Forissier 	res = crypto_hash_init(ctx);
122*c2c877dbSJerome Forissier 	if (res)
123*c2c877dbSJerome Forissier 		goto out;
124*c2c877dbSJerome Forissier 
125*c2c877dbSJerome Forissier 	/* xU or xV */
126*c2c877dbSJerome Forissier 	mp_to_unsigned_bin2(UV->x, buf, SM2_INT_SIZE_BYTES);
127*c2c877dbSJerome Forissier 	res = crypto_hash_update(ctx, buf, sizeof(buf));
128*c2c877dbSJerome Forissier 	if (res)
129*c2c877dbSJerome Forissier 		goto out;
130*c2c877dbSJerome Forissier 
131*c2c877dbSJerome Forissier 	/* ZA || ZB */
132*c2c877dbSJerome Forissier 	res = crypto_hash_update(ctx, ZAZB, ZAZB_len);
133*c2c877dbSJerome Forissier 	if (res)
134*c2c877dbSJerome Forissier 		goto out;
135*c2c877dbSJerome Forissier 
136*c2c877dbSJerome Forissier 	/* x1 */
137*c2c877dbSJerome Forissier 	mp_to_unsigned_bin2(initiator_eph_key->pubkey.x, buf,
138*c2c877dbSJerome Forissier 			    SM2_INT_SIZE_BYTES);
139*c2c877dbSJerome Forissier 	res = crypto_hash_update(ctx, buf, sizeof(buf));
140*c2c877dbSJerome Forissier 	if (res)
141*c2c877dbSJerome Forissier 		goto out;
142*c2c877dbSJerome Forissier 
143*c2c877dbSJerome Forissier 	/* y1 */
144*c2c877dbSJerome Forissier 	mp_to_unsigned_bin2(initiator_eph_key->pubkey.y, buf,
145*c2c877dbSJerome Forissier 			    SM2_INT_SIZE_BYTES);
146*c2c877dbSJerome Forissier 	res = crypto_hash_update(ctx, buf, sizeof(buf));
147*c2c877dbSJerome Forissier 	if (res)
148*c2c877dbSJerome Forissier 		goto out;
149*c2c877dbSJerome Forissier 
150*c2c877dbSJerome Forissier 	/* x2 */
151*c2c877dbSJerome Forissier 	mp_to_unsigned_bin2(responder_eph_key->pubkey.x, buf,
152*c2c877dbSJerome Forissier 			    SM2_INT_SIZE_BYTES);
153*c2c877dbSJerome Forissier 	res = crypto_hash_update(ctx, buf, sizeof(buf));
154*c2c877dbSJerome Forissier 	if (res)
155*c2c877dbSJerome Forissier 		goto out;
156*c2c877dbSJerome Forissier 
157*c2c877dbSJerome Forissier 	/* y2 */
158*c2c877dbSJerome Forissier 	mp_to_unsigned_bin2(responder_eph_key->pubkey.y, buf,
159*c2c877dbSJerome Forissier 			   SM2_INT_SIZE_BYTES);
160*c2c877dbSJerome Forissier 	res = crypto_hash_update(ctx, buf, sizeof(buf));
161*c2c877dbSJerome Forissier 	if (res)
162*c2c877dbSJerome Forissier 		goto out;
163*c2c877dbSJerome Forissier 
164*c2c877dbSJerome Forissier 	res = crypto_hash_final(ctx, hash, sizeof(hash));
165*c2c877dbSJerome Forissier 	if (res)
166*c2c877dbSJerome Forissier 		goto out;
167*c2c877dbSJerome Forissier 
168*c2c877dbSJerome Forissier 	/* Now compute S */
169*c2c877dbSJerome Forissier 
170*c2c877dbSJerome Forissier 	res = crypto_hash_init(ctx);
171*c2c877dbSJerome Forissier 	if (res)
172*c2c877dbSJerome Forissier 		goto out;
173*c2c877dbSJerome Forissier 
174*c2c877dbSJerome Forissier 	/* 0x02 or 0x03  */
175*c2c877dbSJerome Forissier 	res = crypto_hash_update(ctx, &flag, sizeof(flag));
176*c2c877dbSJerome Forissier 	if (res)
177*c2c877dbSJerome Forissier 		goto out;
178*c2c877dbSJerome Forissier 
179*c2c877dbSJerome Forissier 	/* yU or yV */
180*c2c877dbSJerome Forissier 	mp_to_unsigned_bin2(UV->y, buf, SM2_INT_SIZE_BYTES);
181*c2c877dbSJerome Forissier 	res = crypto_hash_update(ctx, buf, sizeof(buf));
182*c2c877dbSJerome Forissier 	if (res)
183*c2c877dbSJerome Forissier 		goto out;
184*c2c877dbSJerome Forissier 
185*c2c877dbSJerome Forissier 	/* Inner SM3(...) */
186*c2c877dbSJerome Forissier 	res = crypto_hash_update(ctx, hash, sizeof(hash));
187*c2c877dbSJerome Forissier 	if (res)
188*c2c877dbSJerome Forissier 		goto out;
189*c2c877dbSJerome Forissier 
190*c2c877dbSJerome Forissier 	res = crypto_hash_final(ctx, S, TEE_SM3_HASH_SIZE);
191*c2c877dbSJerome Forissier 
192*c2c877dbSJerome Forissier out:
193*c2c877dbSJerome Forissier 	crypto_hash_free_ctx(ctx);
194*c2c877dbSJerome Forissier 	return res;
195*c2c877dbSJerome Forissier 
196*c2c877dbSJerome Forissier }
197*c2c877dbSJerome Forissier 
198*c2c877dbSJerome Forissier /*
199*c2c877dbSJerome Forissier  * GM/T 0003.1‒2012 Part 3 Section 6.1
200*c2c877dbSJerome Forissier  * Key exchange protocol
201*c2c877dbSJerome Forissier  */
202*c2c877dbSJerome Forissier static TEE_Result sm2_kep_derive(ecc_key *my_key, ecc_key *my_eph_key,
203*c2c877dbSJerome Forissier 				 ecc_key *peer_key, ecc_key *peer_eph_key,
204*c2c877dbSJerome Forissier 				 struct sm2_kep_parms *p)
205*c2c877dbSJerome Forissier {
206*c2c877dbSJerome Forissier 	/*
207*c2c877dbSJerome Forissier 	 * Variable names and documented steps reflect the initator side (user A
208*c2c877dbSJerome Forissier 	 * in the spec), but the other side is quite similar hence only one
209*c2c877dbSJerome Forissier 	 * function.
210*c2c877dbSJerome Forissier 	 */
211*c2c877dbSJerome Forissier 	uint8_t xUyUZAZB[2 * SM2_INT_SIZE_BYTES + 2 * TEE_SM3_HASH_SIZE] = { };
212*c2c877dbSJerome Forissier 	ecc_key *initiator_eph_key = p->is_initiator ? my_eph_key :
213*c2c877dbSJerome Forissier 						       peer_eph_key;
214*c2c877dbSJerome Forissier 	ecc_key *responder_eph_key = p->is_initiator ? peer_eph_key :
215*c2c877dbSJerome Forissier 						       my_eph_key;
216*c2c877dbSJerome Forissier 	ecc_key *initiator_key = p->is_initiator ? my_key : peer_key;
217*c2c877dbSJerome Forissier 	ecc_key *responder_key = p->is_initiator ? peer_key : my_key;
218*c2c877dbSJerome Forissier 	TEE_Result res = TEE_ERROR_BAD_STATE;
219*c2c877dbSJerome Forissier 	uint8_t tmp[SM2_INT_SIZE_BYTES];
220*c2c877dbSJerome Forissier 	void *n = my_key->dp.order;
221*c2c877dbSJerome Forissier 	ecc_point *U = NULL;
222*c2c877dbSJerome Forissier 	void *x1bar = NULL;
223*c2c877dbSJerome Forissier 	void *x2bar = NULL;
224*c2c877dbSJerome Forissier 	void *tA = NULL;
225*c2c877dbSJerome Forissier 	void *h = NULL;
226*c2c877dbSJerome Forissier 	void *htA = NULL;
227*c2c877dbSJerome Forissier 	void *mp = NULL;
228*c2c877dbSJerome Forissier 	void *mu = NULL;
229*c2c877dbSJerome Forissier 	void *ma = NULL;
230*c2c877dbSJerome Forissier 	void *one = NULL;
231*c2c877dbSJerome Forissier 	int ltc_res = 0;
232*c2c877dbSJerome Forissier 	int inf = 0;
233*c2c877dbSJerome Forissier 
234*c2c877dbSJerome Forissier 	ltc_res = mp_init_multi(&x1bar, &x2bar, &tA, &h, &htA, &mu, &ma, &one,
235*c2c877dbSJerome Forissier 				NULL);
236*c2c877dbSJerome Forissier 	if (ltc_res != CRYPT_OK) {
237*c2c877dbSJerome Forissier 		res = TEE_ERROR_OUT_OF_MEMORY;
238*c2c877dbSJerome Forissier 		goto out;
239*c2c877dbSJerome Forissier 	}
240*c2c877dbSJerome Forissier 
241*c2c877dbSJerome Forissier 	U = ltc_ecc_new_point();
242*c2c877dbSJerome Forissier 	if (!U) {
243*c2c877dbSJerome Forissier 		res = TEE_ERROR_OUT_OF_MEMORY;
244*c2c877dbSJerome Forissier 		goto out;
245*c2c877dbSJerome Forissier 	}
246*c2c877dbSJerome Forissier 
247*c2c877dbSJerome Forissier 	/*
248*c2c877dbSJerome Forissier 	 * Steps A1-A3 are supposedly done already (generate ephemeral key, send
249*c2c877dbSJerome Forissier 	 * it to peer).
250*c2c877dbSJerome Forissier 	 * Step A4: (x1, y1) = RA; x1bar = 2^w + (x1 & (2^w - 1))
251*c2c877dbSJerome Forissier 	 */
252*c2c877dbSJerome Forissier 
253*c2c877dbSJerome Forissier 	mp_to_unsigned_bin2(my_eph_key->pubkey.x, tmp, SM2_INT_SIZE_BYTES);
254*c2c877dbSJerome Forissier 	tmp[SM2_INT_SIZE_BYTES / 2] |= 0x80;
255*c2c877dbSJerome Forissier 	mp_read_unsigned_bin(x1bar, tmp + SM2_INT_SIZE_BYTES / 2,
256*c2c877dbSJerome Forissier 			     SM2_INT_SIZE_BYTES / 2);
257*c2c877dbSJerome Forissier 
258*c2c877dbSJerome Forissier 	/* Step A5: tA = (dA + x1bar * rA) mod n */
259*c2c877dbSJerome Forissier 
260*c2c877dbSJerome Forissier 	ltc_res = mp_mulmod(x1bar, my_eph_key->k, n, tA);
261*c2c877dbSJerome Forissier 	if (ltc_res != CRYPT_OK)
262*c2c877dbSJerome Forissier 		goto out;
263*c2c877dbSJerome Forissier 
264*c2c877dbSJerome Forissier 	ltc_res = mp_addmod(tA, my_key->k, n, tA);
265*c2c877dbSJerome Forissier 	if (ltc_res != CRYPT_OK)
266*c2c877dbSJerome Forissier 		goto out;
267*c2c877dbSJerome Forissier 
268*c2c877dbSJerome Forissier 	/* Step A6: verify whether RB verifies the curve equation */
269*c2c877dbSJerome Forissier 
270*c2c877dbSJerome Forissier 	ltc_res = ltc_ecc_is_point(&peer_eph_key->dp, peer_eph_key->pubkey.x,
271*c2c877dbSJerome Forissier 				   peer_eph_key->pubkey.y);
272*c2c877dbSJerome Forissier 	if (ltc_res != CRYPT_OK)
273*c2c877dbSJerome Forissier 		goto out;
274*c2c877dbSJerome Forissier 
275*c2c877dbSJerome Forissier 	/* Step A6 (continued): (x2, y2) = RB; x2bar = 2^w + (x2 & (2^w - 1)) */
276*c2c877dbSJerome Forissier 
277*c2c877dbSJerome Forissier 	mp_to_unsigned_bin2(peer_eph_key->pubkey.x, tmp, SM2_INT_SIZE_BYTES);
278*c2c877dbSJerome Forissier 	tmp[SM2_INT_SIZE_BYTES / 2] |= 0x80;
279*c2c877dbSJerome Forissier 	mp_read_unsigned_bin(x2bar, tmp + SM2_INT_SIZE_BYTES / 2,
280*c2c877dbSJerome Forissier 			     SM2_INT_SIZE_BYTES / 2);
281*c2c877dbSJerome Forissier 
282*c2c877dbSJerome Forissier 
283*c2c877dbSJerome Forissier 	/* Step A7: compute U = [h.tA](PB + [x2bar]RB) and check for infinity */
284*c2c877dbSJerome Forissier 
285*c2c877dbSJerome Forissier 	ltc_res = mp_montgomery_setup(peer_key->dp.prime, &mp);
286*c2c877dbSJerome Forissier 	if (ltc_res != CRYPT_OK)
287*c2c877dbSJerome Forissier 		goto out;
288*c2c877dbSJerome Forissier 
289*c2c877dbSJerome Forissier 	ltc_res = mp_montgomery_normalization(mu, peer_key->dp.prime);
290*c2c877dbSJerome Forissier 	if (ltc_res != CRYPT_OK)
291*c2c877dbSJerome Forissier 		goto out;
292*c2c877dbSJerome Forissier 
293*c2c877dbSJerome Forissier 	ltc_res = mp_mulmod(peer_key->dp.A, mu, peer_key->dp.prime, ma);
294*c2c877dbSJerome Forissier 	if (ltc_res != CRYPT_OK)
295*c2c877dbSJerome Forissier 		goto out;
296*c2c877dbSJerome Forissier 
297*c2c877dbSJerome Forissier 	ltc_res = mp_set_int(one, 1);
298*c2c877dbSJerome Forissier 	if (ltc_res != CRYPT_OK)
299*c2c877dbSJerome Forissier 		goto out;
300*c2c877dbSJerome Forissier 
301*c2c877dbSJerome Forissier 	ltc_res = ltc_ecc_mul2add(&peer_key->pubkey, one, &peer_eph_key->pubkey,
302*c2c877dbSJerome Forissier 				  x2bar, U, ma, peer_key->dp.prime);
303*c2c877dbSJerome Forissier 	if (ltc_res != CRYPT_OK)
304*c2c877dbSJerome Forissier 		goto out;
305*c2c877dbSJerome Forissier 
306*c2c877dbSJerome Forissier 	ltc_res = mp_set_int(h, peer_key->dp.cofactor);
307*c2c877dbSJerome Forissier 	if (ltc_res != CRYPT_OK)
308*c2c877dbSJerome Forissier 		goto out;
309*c2c877dbSJerome Forissier 
310*c2c877dbSJerome Forissier 	ltc_res = mp_mul(h, tA, htA);
311*c2c877dbSJerome Forissier 	if (ltc_res != CRYPT_OK)
312*c2c877dbSJerome Forissier 		goto out;
313*c2c877dbSJerome Forissier 
314*c2c877dbSJerome Forissier 	ltc_res = ltc_ecc_mulmod(htA, U, U, peer_key->dp.A, peer_key->dp.prime,
315*c2c877dbSJerome Forissier 				 1);
316*c2c877dbSJerome Forissier 	if (ltc_res != CRYPT_OK)
317*c2c877dbSJerome Forissier 		goto out;
318*c2c877dbSJerome Forissier 
319*c2c877dbSJerome Forissier 	ltc_res = ltc_ecc_is_point_at_infinity(U, peer_key->dp.prime, &inf);
320*c2c877dbSJerome Forissier 	if (ltc_res != CRYPT_OK)
321*c2c877dbSJerome Forissier 		goto out;
322*c2c877dbSJerome Forissier 
323*c2c877dbSJerome Forissier 	if (inf)
324*c2c877dbSJerome Forissier 		goto out;
325*c2c877dbSJerome Forissier 
326*c2c877dbSJerome Forissier 	/* Step A8: compute KA = KDF(xU || yU || ZA || ZB, klen) */
327*c2c877dbSJerome Forissier 
328*c2c877dbSJerome Forissier 	/* xU */
329*c2c877dbSJerome Forissier 	mp_to_unsigned_bin2(U->x, xUyUZAZB, SM2_INT_SIZE_BYTES);
330*c2c877dbSJerome Forissier 
331*c2c877dbSJerome Forissier 	/* yU */
332*c2c877dbSJerome Forissier 	mp_to_unsigned_bin2(U->y, xUyUZAZB + SM2_INT_SIZE_BYTES,
333*c2c877dbSJerome Forissier 			    SM2_INT_SIZE_BYTES);
334*c2c877dbSJerome Forissier 
335*c2c877dbSJerome Forissier 	/* ZA */
336*c2c877dbSJerome Forissier 	res = sm2_kep_compute_Z(xUyUZAZB + 2 * SM2_INT_SIZE_BYTES,
337*c2c877dbSJerome Forissier 				TEE_SM3_HASH_SIZE, p->initiator_id,
338*c2c877dbSJerome Forissier 				p->initiator_id_len, initiator_key);
339*c2c877dbSJerome Forissier 	if (res)
340*c2c877dbSJerome Forissier 		goto out;
341*c2c877dbSJerome Forissier 
342*c2c877dbSJerome Forissier 	/* ZB */
343*c2c877dbSJerome Forissier 	res = sm2_kep_compute_Z(xUyUZAZB + 2 * SM2_INT_SIZE_BYTES +
344*c2c877dbSJerome Forissier 					TEE_SM3_HASH_SIZE,
345*c2c877dbSJerome Forissier 				TEE_SM3_HASH_SIZE, p->responder_id,
346*c2c877dbSJerome Forissier 				p->responder_id_len, responder_key);
347*c2c877dbSJerome Forissier 	if (res)
348*c2c877dbSJerome Forissier 		goto out;
349*c2c877dbSJerome Forissier 
350*c2c877dbSJerome Forissier 	res = sm2_kdf(xUyUZAZB, sizeof(xUyUZAZB), p->out, p->out_len);
351*c2c877dbSJerome Forissier 	if (res)
352*c2c877dbSJerome Forissier 		goto out;
353*c2c877dbSJerome Forissier 
354*c2c877dbSJerome Forissier 	/* Step A9: compute S1 and check S1 == SB */
355*c2c877dbSJerome Forissier 
356*c2c877dbSJerome Forissier 	if (p->conf_in) {
357*c2c877dbSJerome Forissier 		uint8_t S1[TEE_SM3_HASH_SIZE];
358*c2c877dbSJerome Forissier 		uint8_t flag = p->is_initiator ? 0x02 : 0x03;
359*c2c877dbSJerome Forissier 
360*c2c877dbSJerome Forissier 		if (p->conf_in_len < TEE_SM3_HASH_SIZE) {
361*c2c877dbSJerome Forissier 			res = TEE_ERROR_BAD_PARAMETERS;
362*c2c877dbSJerome Forissier 			goto out;
363*c2c877dbSJerome Forissier 		}
364*c2c877dbSJerome Forissier 		res = sm2_kep_compute_S(S1, sizeof(S1), flag, U,
365*c2c877dbSJerome Forissier 					xUyUZAZB + 2 * SM2_INT_SIZE_BYTES,
366*c2c877dbSJerome Forissier 					2 * SM2_INT_SIZE_BYTES,
367*c2c877dbSJerome Forissier 					initiator_eph_key, responder_eph_key);
368*c2c877dbSJerome Forissier 		if (res)
369*c2c877dbSJerome Forissier 			goto out;
370*c2c877dbSJerome Forissier 
371*c2c877dbSJerome Forissier 		if (consttime_memcmp(S1, p->conf_in, sizeof(S1))) {
372*c2c877dbSJerome Forissier 			/* Verification failed */
373*c2c877dbSJerome Forissier 			res = TEE_ERROR_BAD_STATE;
374*c2c877dbSJerome Forissier 			goto out;
375*c2c877dbSJerome Forissier 		}
376*c2c877dbSJerome Forissier 	}
377*c2c877dbSJerome Forissier 
378*c2c877dbSJerome Forissier 	/* Step A10: compute SA */
379*c2c877dbSJerome Forissier 
380*c2c877dbSJerome Forissier 	if (p->conf_out) {
381*c2c877dbSJerome Forissier 		uint8_t flag = p->is_initiator ? 0x03 : 0x02;
382*c2c877dbSJerome Forissier 
383*c2c877dbSJerome Forissier 		if (p->conf_out_len < TEE_SM3_HASH_SIZE) {
384*c2c877dbSJerome Forissier 			res = TEE_ERROR_BAD_PARAMETERS;
385*c2c877dbSJerome Forissier 			goto out;
386*c2c877dbSJerome Forissier 		}
387*c2c877dbSJerome Forissier 
388*c2c877dbSJerome Forissier 		res = sm2_kep_compute_S(p->conf_out, TEE_SM3_HASH_SIZE, flag, U,
389*c2c877dbSJerome Forissier 					xUyUZAZB + 2 * SM2_INT_SIZE_BYTES,
390*c2c877dbSJerome Forissier 					2 * SM2_INT_SIZE_BYTES,
391*c2c877dbSJerome Forissier 					initiator_eph_key, responder_eph_key);
392*c2c877dbSJerome Forissier 		if (res)
393*c2c877dbSJerome Forissier 			goto out;
394*c2c877dbSJerome Forissier 	}
395*c2c877dbSJerome Forissier out:
396*c2c877dbSJerome Forissier 	mp_montgomery_free(mp);
397*c2c877dbSJerome Forissier 	ltc_ecc_del_point(U);
398*c2c877dbSJerome Forissier 	mp_clear_multi(x1bar, x2bar, tA, h, htA, mu, ma, one, NULL);
399*c2c877dbSJerome Forissier 	return res;
400*c2c877dbSJerome Forissier }
401*c2c877dbSJerome Forissier 
402*c2c877dbSJerome Forissier TEE_Result crypto_acipher_sm2_kep_derive(struct ecc_keypair *my_key,
403*c2c877dbSJerome Forissier 					 struct ecc_keypair *my_eph_key,
404*c2c877dbSJerome Forissier 					 struct ecc_public_key *peer_key,
405*c2c877dbSJerome Forissier 					 struct ecc_public_key *peer_eph_key,
406*c2c877dbSJerome Forissier 					 struct sm2_kep_parms *p)
407*c2c877dbSJerome Forissier {
408*c2c877dbSJerome Forissier 	TEE_Result res = TEE_SUCCESS;
409*c2c877dbSJerome Forissier 	ecc_key ltc_my_key = { };
410*c2c877dbSJerome Forissier 	ecc_key ltc_my_eph_key = { };
411*c2c877dbSJerome Forissier 	ecc_key ltc_peer_key = { };
412*c2c877dbSJerome Forissier 	ecc_key ltc_peer_eph_key = { };
413*c2c877dbSJerome Forissier 
414*c2c877dbSJerome Forissier 	res = ecc_populate_ltc_private_key(&ltc_my_key, my_key,
415*c2c877dbSJerome Forissier 					   TEE_ALG_SM2_KEP, NULL);
416*c2c877dbSJerome Forissier 	if (res)
417*c2c877dbSJerome Forissier 		goto out;
418*c2c877dbSJerome Forissier 
419*c2c877dbSJerome Forissier 	res = ecc_populate_ltc_private_key(&ltc_my_eph_key, my_eph_key,
420*c2c877dbSJerome Forissier 					   TEE_ALG_SM2_KEP, NULL);
421*c2c877dbSJerome Forissier 	if (res)
422*c2c877dbSJerome Forissier 		goto out;
423*c2c877dbSJerome Forissier 
424*c2c877dbSJerome Forissier 	res = ecc_populate_ltc_public_key(&ltc_peer_key, peer_key,
425*c2c877dbSJerome Forissier 					  TEE_ALG_SM2_KEP, NULL);
426*c2c877dbSJerome Forissier 	if (res)
427*c2c877dbSJerome Forissier 		goto out;
428*c2c877dbSJerome Forissier 
429*c2c877dbSJerome Forissier 	res = ecc_populate_ltc_public_key(&ltc_peer_eph_key, peer_eph_key,
430*c2c877dbSJerome Forissier 					  TEE_ALG_SM2_KEP, NULL);
431*c2c877dbSJerome Forissier 	if (res)
432*c2c877dbSJerome Forissier 		goto out;
433*c2c877dbSJerome Forissier 
434*c2c877dbSJerome Forissier 	res = sm2_kep_derive(&ltc_my_key, &ltc_my_eph_key, &ltc_peer_key,
435*c2c877dbSJerome Forissier 			     &ltc_peer_eph_key, p);
436*c2c877dbSJerome Forissier out:
437*c2c877dbSJerome Forissier 	ecc_free(&ltc_peer_eph_key);
438*c2c877dbSJerome Forissier 	ecc_free(&ltc_peer_key);
439*c2c877dbSJerome Forissier 	ecc_free(&ltc_my_eph_key);
440*c2c877dbSJerome Forissier 	ecc_free(&ltc_my_key);
441*c2c877dbSJerome Forissier 	return res;
442*c2c877dbSJerome Forissier }
443*c2c877dbSJerome Forissier 
444