xref: /optee_os/core/drivers/crypto/hisilicon/hpre_montgomery.c (revision a420305232cabde42cf87e7bcdccb059c1eb2bf2)
1*a4203052Syuzexi // SPDX-License-Identifier: BSD-2-Clause
2*a4203052Syuzexi /*
3*a4203052Syuzexi  * Copyright (c) 2022-2024, HiSilicon Technologies Co., Ltd.
4*a4203052Syuzexi  * Kunpeng hardware accelerator hpre montgomery algorithm implementation.
5*a4203052Syuzexi  */
6*a4203052Syuzexi #include <drvcrypt.h>
7*a4203052Syuzexi #include <drvcrypt_acipher.h>
8*a4203052Syuzexi #include <initcall.h>
9*a4203052Syuzexi #include <malloc.h>
10*a4203052Syuzexi #include <rng_support.h>
11*a4203052Syuzexi #include <stdlib_ext.h>
12*a4203052Syuzexi #include <string.h>
13*a4203052Syuzexi #include <string_ext.h>
14*a4203052Syuzexi #include <trace.h>
15*a4203052Syuzexi 
16*a4203052Syuzexi #include "hpre_main.h"
17*a4203052Syuzexi #include "hpre_montgomery.h"
18*a4203052Syuzexi 
19*a4203052Syuzexi #define X25519_CURVE_INDEX 0
20*a4203052Syuzexi #define X448_CURVE_INDEX 1
21*a4203052Syuzexi 
22*a4203052Syuzexi struct hpre_mgm_curve {
23*a4203052Syuzexi 	uint32_t key_bits;
24*a4203052Syuzexi 	const uint8_t *p;
25*a4203052Syuzexi 	const uint8_t *a;
26*a4203052Syuzexi 	const uint8_t *x;
27*a4203052Syuzexi };
28*a4203052Syuzexi 
29*a4203052Syuzexi /* NID_X25519 */
30*a4203052Syuzexi /* p = (2 ^ 255 - 19) big endian */
31*a4203052Syuzexi static const uint8_t g_x25519_p[] = {
32*a4203052Syuzexi 	0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
33*a4203052Syuzexi 	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
34*a4203052Syuzexi 	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED
35*a4203052Syuzexi };
36*a4203052Syuzexi 
37*a4203052Syuzexi /* a = (486662 - 2) / 4  = 121665 big endian */
38*a4203052Syuzexi static const uint8_t g_x25519_a[] = {
39*a4203052Syuzexi 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
40*a4203052Syuzexi 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
41*a4203052Syuzexi 	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xDB, 0x41
42*a4203052Syuzexi };
43*a4203052Syuzexi 
44*a4203052Syuzexi /* big endian */
45*a4203052Syuzexi static const uint8_t g_x25519_gx[] = {
46*a4203052Syuzexi 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
47*a4203052Syuzexi 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
48*a4203052Syuzexi 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09
49*a4203052Syuzexi };
50*a4203052Syuzexi 
51*a4203052Syuzexi /* NID_X448 */
52*a4203052Syuzexi /* p = (2 ^ 448 - 2 ^ 224 - 1) big endian */
53*a4203052Syuzexi static const uint8_t g_x448_p[] = {
54*a4203052Syuzexi 	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
55*a4203052Syuzexi 	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
56*a4203052Syuzexi 	0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
57*a4203052Syuzexi 	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
58*a4203052Syuzexi 	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
59*a4203052Syuzexi };
60*a4203052Syuzexi 
61*a4203052Syuzexi /* a = (156326 - 2) / 4  = 39081 big endian */
62*a4203052Syuzexi static const uint8_t g_x448_a[] = {
63*a4203052Syuzexi 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64*a4203052Syuzexi 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65*a4203052Syuzexi 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66*a4203052Syuzexi 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
67*a4203052Syuzexi 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0xA9
68*a4203052Syuzexi };
69*a4203052Syuzexi 
70*a4203052Syuzexi /* big endian */
71*a4203052Syuzexi static const uint8_t g_x448_gx[] = {
72*a4203052Syuzexi 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73*a4203052Syuzexi 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74*a4203052Syuzexi 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75*a4203052Syuzexi 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76*a4203052Syuzexi 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05
77*a4203052Syuzexi };
78*a4203052Syuzexi 
79*a4203052Syuzexi static const struct hpre_mgm_curve g_curve_list[] = {
80*a4203052Syuzexi 	{
81*a4203052Syuzexi 		.key_bits = 256,
82*a4203052Syuzexi 		.p = g_x25519_p,
83*a4203052Syuzexi 		.a = g_x25519_a,
84*a4203052Syuzexi 		.x = g_x25519_gx,
85*a4203052Syuzexi 	}, {
86*a4203052Syuzexi 		.key_bits = 448,
87*a4203052Syuzexi 		.p = g_x448_p,
88*a4203052Syuzexi 		.a = g_x448_a,
89*a4203052Syuzexi 		.x = g_x448_gx,
90*a4203052Syuzexi 	}
91*a4203052Syuzexi };
92*a4203052Syuzexi 
93*a4203052Syuzexi static TEE_Result
hpre_montgomery_alloc_keypair(struct montgomery_keypair * key,size_t size_bits)94*a4203052Syuzexi hpre_montgomery_alloc_keypair(struct montgomery_keypair *key,
95*a4203052Syuzexi 			      size_t size_bits)
96*a4203052Syuzexi {
97*a4203052Syuzexi 	size_t key_size = BITS_TO_BYTES(size_bits);
98*a4203052Syuzexi 
99*a4203052Syuzexi 	if (!key || (size_bits != X25519_KEY_BITS &&
100*a4203052Syuzexi 		     size_bits != X448_KEY_BITS)) {
101*a4203052Syuzexi 		EMSG("Invalid input parameter");
102*a4203052Syuzexi 		return TEE_ERROR_BAD_PARAMETERS;
103*a4203052Syuzexi 	}
104*a4203052Syuzexi 
105*a4203052Syuzexi 	key->priv = calloc(1, key_size);
106*a4203052Syuzexi 	if (!key->priv)
107*a4203052Syuzexi 		goto priv_err;
108*a4203052Syuzexi 
109*a4203052Syuzexi 	key->pub = calloc(1, key_size);
110*a4203052Syuzexi 	if (!key->pub)
111*a4203052Syuzexi 		goto pub_err;
112*a4203052Syuzexi 
113*a4203052Syuzexi 	return TEE_SUCCESS;
114*a4203052Syuzexi pub_err:
115*a4203052Syuzexi 	free(key->priv);
116*a4203052Syuzexi 	key->priv = NULL;
117*a4203052Syuzexi priv_err:
118*a4203052Syuzexi 	EMSG("HPRE montgomery alloc key pair fail");
119*a4203052Syuzexi 
120*a4203052Syuzexi 	return TEE_ERROR_OUT_OF_MEMORY;
121*a4203052Syuzexi }
122*a4203052Syuzexi 
gen_random_privkey(uint8_t * priv,size_t key_bits)123*a4203052Syuzexi static TEE_Result gen_random_privkey(uint8_t *priv, size_t key_bits)
124*a4203052Syuzexi {
125*a4203052Syuzexi 	size_t key_size = BITS_TO_BYTES(key_bits);
126*a4203052Syuzexi 	TEE_Result ret = TEE_SUCCESS;
127*a4203052Syuzexi 
128*a4203052Syuzexi 	if (!priv) {
129*a4203052Syuzexi 		EMSG("Privkey param is NULL");
130*a4203052Syuzexi 		return TEE_ERROR_BAD_PARAMETERS;
131*a4203052Syuzexi 	}
132*a4203052Syuzexi 
133*a4203052Syuzexi 	ret = hw_get_random_bytes(priv, key_size);
134*a4203052Syuzexi 	if (ret) {
135*a4203052Syuzexi 		EMSG("Fail to fill privkey");
136*a4203052Syuzexi 		return TEE_ERROR_NO_DATA;
137*a4203052Syuzexi 	}
138*a4203052Syuzexi 
139*a4203052Syuzexi 	return ret;
140*a4203052Syuzexi }
141*a4203052Syuzexi 
142*a4203052Syuzexi static enum hisi_drv_status
hpre_montgomery_params_alloc(struct hpre_montgomery_msg * msg)143*a4203052Syuzexi hpre_montgomery_params_alloc(struct hpre_montgomery_msg *msg)
144*a4203052Syuzexi {
145*a4203052Syuzexi 	uint32_t size = HPRE_MONTGOMERY_TOTAL_BUF_SIZE(msg->key_bytes);
146*a4203052Syuzexi 
147*a4203052Syuzexi 	msg->key = calloc(1, size);
148*a4203052Syuzexi 	if (!msg->key) {
149*a4203052Syuzexi 		EMSG("Fail to alloc montgomery key buf");
150*a4203052Syuzexi 		return HISI_QM_DRVCRYPT_ENOMEM;
151*a4203052Syuzexi 	}
152*a4203052Syuzexi 
153*a4203052Syuzexi 	msg->key_dma = virt_to_phys(msg->key);
154*a4203052Syuzexi 	msg->in = msg->key + HPRE_X_KEY_SIZE(msg->key_bytes);
155*a4203052Syuzexi 	msg->in_dma = msg->key_dma + HPRE_X_KEY_SIZE(msg->key_bytes);
156*a4203052Syuzexi 	msg->out = msg->in + msg->key_bytes;
157*a4203052Syuzexi 	msg->out_dma = msg->in_dma + msg->key_bytes;
158*a4203052Syuzexi 
159*a4203052Syuzexi 	return HISI_QM_DRVCRYPT_NO_ERR;
160*a4203052Syuzexi }
161*a4203052Syuzexi 
hpre_montgomery_params_free(struct hpre_montgomery_msg * msg)162*a4203052Syuzexi static void hpre_montgomery_params_free(struct hpre_montgomery_msg *msg)
163*a4203052Syuzexi {
164*a4203052Syuzexi 	if (msg->key) {
165*a4203052Syuzexi 		memzero_explicit(msg->key, HPRE_X_KEY_SIZE(msg->key_bytes));
166*a4203052Syuzexi 		free(msg->key);
167*a4203052Syuzexi 		msg->key = NULL;
168*a4203052Syuzexi 	}
169*a4203052Syuzexi }
170*a4203052Syuzexi 
171*a4203052Syuzexi static enum hisi_drv_status
hpre_montgomery_params_pretreatment(struct hpre_montgomery_msg * msg)172*a4203052Syuzexi hpre_montgomery_params_pretreatment(struct hpre_montgomery_msg *msg)
173*a4203052Syuzexi {
174*a4203052Syuzexi 	uint8_t *p = msg->key;
175*a4203052Syuzexi 	uint8_t *a = p + msg->key_bytes;
176*a4203052Syuzexi 	uint8_t *k = a + msg->key_bytes;
177*a4203052Syuzexi 	uint8_t *u = msg->in;
178*a4203052Syuzexi 	uint8_t *dst = k;
179*a4203052Syuzexi 	uint32_t bsize = msg->key_bytes;
180*a4203052Syuzexi 	uint32_t dsize = msg->curve_bytes;
181*a4203052Syuzexi 	/*
182*a4203052Syuzexi 	 * It is a constraint of HPRE hardware that key_bytes will be set
183*a4203052Syuzexi 	 * to 72 when curve_bytes is between 48 and 72, and the high-order
184*a4203052Syuzexi 	 * bits will be set to 0.
185*a4203052Syuzexi 	 */
186*a4203052Syuzexi 	uint32_t offset = bsize - dsize;
187*a4203052Syuzexi 	int ret = 0;
188*a4203052Syuzexi 
189*a4203052Syuzexi 	/*
190*a4203052Syuzexi 	 * This is a pretreatment of X25519 with a 32-byte integer,
191*a4203052Syuzexi 	 * as described in RFC 7748:
192*a4203052Syuzexi 	 * Set the three LSB of the first byte and MSB of the last
193*a4203052Syuzexi 	 * to zero, set the second MSB of the last byte to 1.
194*a4203052Syuzexi 	 * When receiving u-array, set MSB of last byte to zero.
195*a4203052Syuzexi 	 * HPRE hardware module uses big-endian mode, so the bytes to be
196*a4203052Syuzexi 	 * set are reversed compared to RFC 7748
197*a4203052Syuzexi 	 */
198*a4203052Syuzexi 	if (msg->key_bytes == BITS_TO_BYTES(X25519_KEY_BITS)) {
199*a4203052Syuzexi 		dst[31] &= 0xF8;
200*a4203052Syuzexi 		dst[0] &= 0x7F;
201*a4203052Syuzexi 		dst[0] |= 0x40;
202*a4203052Syuzexi 		u[0] &= 0x7F;
203*a4203052Syuzexi 	} else {
204*a4203052Syuzexi 		/*
205*a4203052Syuzexi 		 * This is a pretreatment of X448 with a 56-byte integer,
206*a4203052Syuzexi 		 * as described in RFC 7748:
207*a4203052Syuzexi 		 * For X448, set the two LSB of the first byte to 0, and MSB of the
208*a4203052Syuzexi 		 * last byte to 1.
209*a4203052Syuzexi 		 * HPRE hardware module uses big-endian mode, so the bytes to be
210*a4203052Syuzexi 		 * set are reversed compared to RFC 7748
211*a4203052Syuzexi 		 */
212*a4203052Syuzexi 		dst[55 + offset] &= 0xFC;
213*a4203052Syuzexi 		dst[0 + offset] |= 0x80;
214*a4203052Syuzexi 	}
215*a4203052Syuzexi 
216*a4203052Syuzexi 	ret = memcmp(u + offset, p + offset, dsize);
217*a4203052Syuzexi 	if (ret >= 0) {
218*a4203052Syuzexi 		EMSG("u >= p");
219*a4203052Syuzexi 		return HISI_QM_DRVCRYPT_EINVAL;
220*a4203052Syuzexi 	}
221*a4203052Syuzexi 
222*a4203052Syuzexi 	return HISI_QM_DRVCRYPT_NO_ERR;
223*a4203052Syuzexi }
224*a4203052Syuzexi 
225*a4203052Syuzexi static enum hisi_drv_status
hpre_montgomery_params_fill(const struct hpre_mgm_curve * curve,struct hpre_montgomery_msg * msg,uint8_t * privkey,uint8_t * pubkey)226*a4203052Syuzexi hpre_montgomery_params_fill(const struct hpre_mgm_curve *curve,
227*a4203052Syuzexi 			    struct hpre_montgomery_msg *msg,
228*a4203052Syuzexi 			    uint8_t *privkey, uint8_t *pubkey)
229*a4203052Syuzexi {
230*a4203052Syuzexi 	uint8_t *p = msg->key;
231*a4203052Syuzexi 	uint8_t *a = p + msg->key_bytes;
232*a4203052Syuzexi 	uint8_t *k = a + msg->key_bytes;
233*a4203052Syuzexi 	uint8_t *x = msg->in;
234*a4203052Syuzexi 	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
235*a4203052Syuzexi 
236*a4203052Syuzexi 	memcpy(p, curve->p, msg->curve_bytes);
237*a4203052Syuzexi 	memcpy(a, curve->a, msg->curve_bytes);
238*a4203052Syuzexi 	memcpy(k, privkey, msg->curve_bytes);
239*a4203052Syuzexi 	msg->x_bytes = msg->curve_bytes;
240*a4203052Syuzexi 	if (!pubkey)
241*a4203052Syuzexi 		memcpy(x, curve->x, msg->x_bytes);
242*a4203052Syuzexi 	else
243*a4203052Syuzexi 		memcpy(x, pubkey, msg->x_bytes);
244*a4203052Syuzexi 
245*a4203052Syuzexi 	ret = hpre_bin_from_crypto_bin(p, p, msg->key_bytes, msg->curve_bytes);
246*a4203052Syuzexi 	if (ret) {
247*a4203052Syuzexi 		EMSG("Fail to transfer montgomery p from crypto_bin to hpre_bin");
248*a4203052Syuzexi 		return ret;
249*a4203052Syuzexi 	}
250*a4203052Syuzexi 
251*a4203052Syuzexi 	ret = hpre_bin_from_crypto_bin(a, a, msg->key_bytes, msg->curve_bytes);
252*a4203052Syuzexi 	if (ret) {
253*a4203052Syuzexi 		EMSG("Fail to transfer montgomery a from crypto_bin to hpre_bin");
254*a4203052Syuzexi 		return ret;
255*a4203052Syuzexi 	}
256*a4203052Syuzexi 
257*a4203052Syuzexi 	ret = hpre_bin_from_crypto_bin(k, k, msg->key_bytes, msg->curve_bytes);
258*a4203052Syuzexi 	if (ret) {
259*a4203052Syuzexi 		EMSG("Fail to transfer montgomery k from crypto_bin to hpre_bin");
260*a4203052Syuzexi 		return ret;
261*a4203052Syuzexi 	}
262*a4203052Syuzexi 
263*a4203052Syuzexi 	ret = hpre_bin_from_crypto_bin(x, x, msg->key_bytes, msg->x_bytes);
264*a4203052Syuzexi 	if (ret) {
265*a4203052Syuzexi 		EMSG("Fail to transfer montgomery x from crypto_bin to hpre_bin");
266*a4203052Syuzexi 		return ret;
267*a4203052Syuzexi 	}
268*a4203052Syuzexi 
269*a4203052Syuzexi 	return hpre_montgomery_params_pretreatment(msg);
270*a4203052Syuzexi }
271*a4203052Syuzexi 
272*a4203052Syuzexi static TEE_Result
hpre_montgomery_request_init(const struct hpre_mgm_curve * curve,struct hpre_montgomery_msg * msg,uint8_t * privkey,uint8_t * pubkey)273*a4203052Syuzexi hpre_montgomery_request_init(const struct hpre_mgm_curve *curve,
274*a4203052Syuzexi 			     struct hpre_montgomery_msg *msg,
275*a4203052Syuzexi 			     uint8_t *privkey,
276*a4203052Syuzexi 			     uint8_t *pubkey)
277*a4203052Syuzexi {
278*a4203052Syuzexi 	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
279*a4203052Syuzexi 
280*a4203052Syuzexi 	msg->alg_type = HPRE_ALG_X_DH_MULTIPLY;
281*a4203052Syuzexi 	msg->curve_bytes = BITS_TO_BYTES(curve->key_bits);
282*a4203052Syuzexi 
283*a4203052Syuzexi 	if (curve->key_bits == X25519_KEY_BITS) {
284*a4203052Syuzexi 		msg->key_bytes = BITS_TO_BYTES(HPRE_HW_X25519_KBITS);
285*a4203052Syuzexi 	} else if (curve->key_bits == X448_KEY_BITS) {
286*a4203052Syuzexi 		msg->key_bytes = BITS_TO_BYTES(HPRE_HW_X448_KBITS);
287*a4203052Syuzexi 	} else {
288*a4203052Syuzexi 		EMSG("Curve key bits param error");
289*a4203052Syuzexi 		return TEE_ERROR_BAD_PARAMETERS;
290*a4203052Syuzexi 	}
291*a4203052Syuzexi 
292*a4203052Syuzexi 	ret = hpre_montgomery_params_alloc(msg);
293*a4203052Syuzexi 	if (ret)
294*a4203052Syuzexi 		return TEE_ERROR_OUT_OF_MEMORY;
295*a4203052Syuzexi 
296*a4203052Syuzexi 	ret = hpre_montgomery_params_fill(curve, msg, privkey, pubkey);
297*a4203052Syuzexi 	if (ret) {
298*a4203052Syuzexi 		hpre_montgomery_params_free(msg);
299*a4203052Syuzexi 		return TEE_ERROR_BAD_STATE;
300*a4203052Syuzexi 	}
301*a4203052Syuzexi 
302*a4203052Syuzexi 	return TEE_SUCCESS;
303*a4203052Syuzexi }
304*a4203052Syuzexi 
hpre_montgomery_request_deinit(struct hpre_montgomery_msg * msg)305*a4203052Syuzexi static void hpre_montgomery_request_deinit(struct hpre_montgomery_msg *msg)
306*a4203052Syuzexi {
307*a4203052Syuzexi 	hpre_montgomery_params_free(msg);
308*a4203052Syuzexi }
309*a4203052Syuzexi 
hpre_montgomery_fill_sqe(void * bd,void * info)310*a4203052Syuzexi static enum hisi_drv_status hpre_montgomery_fill_sqe(void *bd, void *info)
311*a4203052Syuzexi {
312*a4203052Syuzexi 	struct hpre_montgomery_msg *msg = info;
313*a4203052Syuzexi 	struct hpre_sqe *sqe = bd;
314*a4203052Syuzexi 
315*a4203052Syuzexi 	sqe->w0 = msg->alg_type | SHIFT_U32(0x1, HPRE_DONE_SHIFT);
316*a4203052Syuzexi 	sqe->task_len1 = TASK_LENGTH(msg->key_bytes);
317*a4203052Syuzexi 	sqe->key = msg->key_dma;
318*a4203052Syuzexi 	sqe->in = msg->in_dma;
319*a4203052Syuzexi 	sqe->out = msg->out_dma;
320*a4203052Syuzexi 
321*a4203052Syuzexi 	return HISI_QM_DRVCRYPT_NO_ERR;
322*a4203052Syuzexi }
323*a4203052Syuzexi 
hpre_montgomery_parse_sqe(void * bd,void * info)324*a4203052Syuzexi static enum hisi_drv_status hpre_montgomery_parse_sqe(void *bd, void *info)
325*a4203052Syuzexi {
326*a4203052Syuzexi 	struct hpre_montgomery_msg *msg = info;
327*a4203052Syuzexi 	struct hpre_sqe *sqe = bd;
328*a4203052Syuzexi 	uint8_t *rx = msg->out;
329*a4203052Syuzexi 	uint16_t err = 0;
330*a4203052Syuzexi 	uint16_t err1 = 0;
331*a4203052Syuzexi 	uint16_t done = 0;
332*a4203052Syuzexi 
333*a4203052Syuzexi 	err = HPRE_TASK_ETYPE(sqe->w0);
334*a4203052Syuzexi 	err1 = HPRE_TASK_ETYPE1(sqe->w0);
335*a4203052Syuzexi 	done = HPRE_TASK_DONE(sqe->w0);
336*a4203052Syuzexi 	if (done != HPRE_HW_TASK_DONE || err || err1) {
337*a4203052Syuzexi 		EMSG("HPRE do x_dh fail! done=0x%"PRIX16", etype=0x%"PRIX16",etype1=0x%"PRIX16,
338*a4203052Syuzexi 		     done, err, err1);
339*a4203052Syuzexi 		if (done == HPRE_HW_TASK_INIT) {
340*a4203052Syuzexi 			msg->result = HISI_QM_DRVCRYPT_ENOPROC;
341*a4203052Syuzexi 			return HISI_QM_DRVCRYPT_ENOPROC;
342*a4203052Syuzexi 		}
343*a4203052Syuzexi 
344*a4203052Syuzexi 		msg->result = HISI_QM_DRVCRYPT_IN_EPARA;
345*a4203052Syuzexi 		return HISI_QM_DRVCRYPT_IN_EPARA;
346*a4203052Syuzexi 	}
347*a4203052Syuzexi 
348*a4203052Syuzexi 	if (hpre_bin_to_crypto_bin(rx, rx, msg->key_bytes, msg->curve_bytes)) {
349*a4203052Syuzexi 		EMSG("Fail to transfer x_dh out from hpre_bin to crypto_bin");
350*a4203052Syuzexi 		msg->result = HISI_QM_DRVCRYPT_EINVAL;
351*a4203052Syuzexi 		return HISI_QM_DRVCRYPT_EINVAL;
352*a4203052Syuzexi 	}
353*a4203052Syuzexi 
354*a4203052Syuzexi 	return HISI_QM_DRVCRYPT_NO_ERR;
355*a4203052Syuzexi }
356*a4203052Syuzexi 
hpre_montgomery_do_task(struct hpre_montgomery_msg * msg)357*a4203052Syuzexi static TEE_Result hpre_montgomery_do_task(struct hpre_montgomery_msg *msg)
358*a4203052Syuzexi {
359*a4203052Syuzexi 	struct hisi_qp *montgomery_qp = NULL;
360*a4203052Syuzexi 	TEE_Result res = TEE_SUCCESS;
361*a4203052Syuzexi 	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
362*a4203052Syuzexi 
363*a4203052Syuzexi 	montgomery_qp = hpre_create_qp(HISI_QM_CHANNEL_TYPE1);
364*a4203052Syuzexi 	if (!montgomery_qp) {
365*a4203052Syuzexi 		EMSG("Fail to create montgomery qp");
366*a4203052Syuzexi 		return TEE_ERROR_BUSY;
367*a4203052Syuzexi 	}
368*a4203052Syuzexi 
369*a4203052Syuzexi 	montgomery_qp->fill_sqe = hpre_montgomery_fill_sqe;
370*a4203052Syuzexi 	montgomery_qp->parse_sqe = hpre_montgomery_parse_sqe;
371*a4203052Syuzexi 	ret = hisi_qp_send(montgomery_qp, msg);
372*a4203052Syuzexi 	if (ret) {
373*a4203052Syuzexi 		EMSG("Fail to send task, ret=%d", ret);
374*a4203052Syuzexi 		res = TEE_ERROR_BAD_STATE;
375*a4203052Syuzexi 		goto done;
376*a4203052Syuzexi 	}
377*a4203052Syuzexi 
378*a4203052Syuzexi 	ret = hisi_qp_recv_sync(montgomery_qp, msg);
379*a4203052Syuzexi 	if (ret) {
380*a4203052Syuzexi 		EMSG("Recv task error, ret=%d", ret);
381*a4203052Syuzexi 		res = TEE_ERROR_BAD_STATE;
382*a4203052Syuzexi 	}
383*a4203052Syuzexi 
384*a4203052Syuzexi done:
385*a4203052Syuzexi 	hisi_qm_release_qp(montgomery_qp);
386*a4203052Syuzexi 
387*a4203052Syuzexi 	return res;
388*a4203052Syuzexi }
389*a4203052Syuzexi 
hpre_montgomery_gen_keypair(struct montgomery_keypair * key,size_t size_bits)390*a4203052Syuzexi static TEE_Result hpre_montgomery_gen_keypair(struct montgomery_keypair *key,
391*a4203052Syuzexi 					      size_t size_bits)
392*a4203052Syuzexi {
393*a4203052Syuzexi 	struct hpre_montgomery_msg msg = { };
394*a4203052Syuzexi 	const struct hpre_mgm_curve *curve = NULL;
395*a4203052Syuzexi 	TEE_Result ret = TEE_SUCCESS;
396*a4203052Syuzexi 
397*a4203052Syuzexi 	if (!key || !key->priv || !key->pub) {
398*a4203052Syuzexi 		EMSG("Invalid montgomery_gen_keypair input parameters");
399*a4203052Syuzexi 		return TEE_ERROR_BAD_PARAMETERS;
400*a4203052Syuzexi 	}
401*a4203052Syuzexi 
402*a4203052Syuzexi 	if (size_bits == X25519_KEY_BITS)
403*a4203052Syuzexi 		curve = &g_curve_list[X25519_CURVE_INDEX];
404*a4203052Syuzexi 	else if (size_bits == X448_KEY_BITS)
405*a4203052Syuzexi 		curve = &g_curve_list[X448_CURVE_INDEX];
406*a4203052Syuzexi 	else
407*a4203052Syuzexi 		return TEE_ERROR_BAD_PARAMETERS;
408*a4203052Syuzexi 
409*a4203052Syuzexi 	ret = gen_random_privkey(key->priv, size_bits);
410*a4203052Syuzexi 	if (ret) {
411*a4203052Syuzexi 		EMSG("Fail to gen privkey");
412*a4203052Syuzexi 		return ret;
413*a4203052Syuzexi 	}
414*a4203052Syuzexi 
415*a4203052Syuzexi 	ret = hpre_montgomery_request_init(curve, &msg, key->priv, NULL);
416*a4203052Syuzexi 	if (ret) {
417*a4203052Syuzexi 		EMSG("Fail to init montgomery key pair");
418*a4203052Syuzexi 		return ret;
419*a4203052Syuzexi 	}
420*a4203052Syuzexi 
421*a4203052Syuzexi 	ret = hpre_montgomery_do_task(&msg);
422*a4203052Syuzexi 	if (ret) {
423*a4203052Syuzexi 		EMSG("Fail to do montgomery key pair task ret = 0x%"PRIX32, ret);
424*a4203052Syuzexi 		goto done;
425*a4203052Syuzexi 	}
426*a4203052Syuzexi 	memcpy(key->pub, msg.out, msg.curve_bytes);
427*a4203052Syuzexi 
428*a4203052Syuzexi done:
429*a4203052Syuzexi 	hpre_montgomery_request_deinit(&msg);
430*a4203052Syuzexi 
431*a4203052Syuzexi 	return ret;
432*a4203052Syuzexi }
433*a4203052Syuzexi 
434*a4203052Syuzexi static TEE_Result
hpre_montgomery_do_shared_secret(struct drvcrypt_secret_data * sdata)435*a4203052Syuzexi hpre_montgomery_do_shared_secret(struct drvcrypt_secret_data *sdata)
436*a4203052Syuzexi {
437*a4203052Syuzexi 	struct hpre_montgomery_msg msg = { };
438*a4203052Syuzexi 	const struct hpre_mgm_curve *curve = NULL;
439*a4203052Syuzexi 	struct montgomery_keypair *key = NULL;
440*a4203052Syuzexi 	uint8_t *pubkey = NULL;
441*a4203052Syuzexi 	TEE_Result ret = TEE_SUCCESS;
442*a4203052Syuzexi 
443*a4203052Syuzexi 	if (!sdata || !sdata->key_priv || !sdata->key_pub) {
444*a4203052Syuzexi 		EMSG("Invalid montgomery_do_shared_secret input parameters");
445*a4203052Syuzexi 		return TEE_ERROR_BAD_PARAMETERS;
446*a4203052Syuzexi 	}
447*a4203052Syuzexi 
448*a4203052Syuzexi 	key = sdata->key_priv;
449*a4203052Syuzexi 	pubkey = sdata->key_pub;
450*a4203052Syuzexi 	if (sdata->size_sec == BITS_TO_BYTES(X25519_KEY_BITS))
451*a4203052Syuzexi 		curve = &g_curve_list[X25519_CURVE_INDEX];
452*a4203052Syuzexi 	else if (sdata->size_sec == BITS_TO_BYTES(X448_KEY_BITS))
453*a4203052Syuzexi 		curve = &g_curve_list[X448_CURVE_INDEX];
454*a4203052Syuzexi 	else
455*a4203052Syuzexi 		return TEE_ERROR_BAD_PARAMETERS;
456*a4203052Syuzexi 
457*a4203052Syuzexi 	ret = hpre_montgomery_request_init(curve, &msg, key->priv, pubkey);
458*a4203052Syuzexi 	if (ret) {
459*a4203052Syuzexi 		EMSG("Fail to init montgomery shared secret");
460*a4203052Syuzexi 		return ret;
461*a4203052Syuzexi 	}
462*a4203052Syuzexi 
463*a4203052Syuzexi 	ret = hpre_montgomery_do_task(&msg);
464*a4203052Syuzexi 	if (ret) {
465*a4203052Syuzexi 		EMSG("Fail to do montgomery shared secret task! ret = 0x%"PRIX32,
466*a4203052Syuzexi 		     ret);
467*a4203052Syuzexi 		goto done;
468*a4203052Syuzexi 	}
469*a4203052Syuzexi 	memcpy(sdata->secret.data, msg.out, msg.curve_bytes);
470*a4203052Syuzexi 	sdata->secret.length = msg.curve_bytes;
471*a4203052Syuzexi 	memzero_explicit(msg.out, msg.curve_bytes);
472*a4203052Syuzexi 
473*a4203052Syuzexi done:
474*a4203052Syuzexi 	hpre_montgomery_request_deinit(&msg);
475*a4203052Syuzexi 
476*a4203052Syuzexi 	return ret;
477*a4203052Syuzexi }
478*a4203052Syuzexi 
479*a4203052Syuzexi static struct drvcrypt_montgomery driver_x25519 = {
480*a4203052Syuzexi 	.alloc_keypair = hpre_montgomery_alloc_keypair,
481*a4203052Syuzexi 	.gen_keypair = hpre_montgomery_gen_keypair,
482*a4203052Syuzexi 	.shared_secret = hpre_montgomery_do_shared_secret,
483*a4203052Syuzexi };
484*a4203052Syuzexi 
485*a4203052Syuzexi static struct drvcrypt_montgomery driver_x448 = {
486*a4203052Syuzexi 	.alloc_keypair = hpre_montgomery_alloc_keypair,
487*a4203052Syuzexi 	.gen_keypair = hpre_montgomery_gen_keypair,
488*a4203052Syuzexi 	.shared_secret = hpre_montgomery_do_shared_secret,
489*a4203052Syuzexi };
490*a4203052Syuzexi 
hpre_montgomery_init(void)491*a4203052Syuzexi static TEE_Result hpre_montgomery_init(void)
492*a4203052Syuzexi {
493*a4203052Syuzexi 	TEE_Result ret = TEE_SUCCESS;
494*a4203052Syuzexi 
495*a4203052Syuzexi 	ret = drvcrypt_register_x25519(&driver_x25519);
496*a4203052Syuzexi 	if (ret != TEE_SUCCESS) {
497*a4203052Syuzexi 		EMSG("Hpre x25519 register to crypto fail");
498*a4203052Syuzexi 		return ret;
499*a4203052Syuzexi 	}
500*a4203052Syuzexi 
501*a4203052Syuzexi 	ret = drvcrypt_register_x448(&driver_x448);
502*a4203052Syuzexi 	if (ret != TEE_SUCCESS) {
503*a4203052Syuzexi 		EMSG("Hpre x448 register to crypto fail");
504*a4203052Syuzexi 		return ret;
505*a4203052Syuzexi 	}
506*a4203052Syuzexi 
507*a4203052Syuzexi 	return ret;
508*a4203052Syuzexi }
509*a4203052Syuzexi 
510*a4203052Syuzexi driver_init(hpre_montgomery_init);
511