xref: /openbmc/linux/net/bluetooth/ecdh_helper.c (revision 58771c1cb0023fdd744e76d6cad7716dc4f579ee)
1*58771c1cSSalvatore Benedetto /*
2*58771c1cSSalvatore Benedetto  * ECDH helper functions - KPP wrappings
3*58771c1cSSalvatore Benedetto  *
4*58771c1cSSalvatore Benedetto  * Copyright (C) 2017 Intel Corporation
5*58771c1cSSalvatore Benedetto  *
6*58771c1cSSalvatore Benedetto  * This program is free software; you can redistribute it and/or modify
7*58771c1cSSalvatore Benedetto  * it under the terms of the GNU General Public License version 2 as
8*58771c1cSSalvatore Benedetto  * published by the Free Software Foundation;
9*58771c1cSSalvatore Benedetto  *
10*58771c1cSSalvatore Benedetto  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
11*58771c1cSSalvatore Benedetto  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12*58771c1cSSalvatore Benedetto  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
13*58771c1cSSalvatore Benedetto  * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
14*58771c1cSSalvatore Benedetto  * CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
15*58771c1cSSalvatore Benedetto  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16*58771c1cSSalvatore Benedetto  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17*58771c1cSSalvatore Benedetto  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18*58771c1cSSalvatore Benedetto  *
19*58771c1cSSalvatore Benedetto  * ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
20*58771c1cSSalvatore Benedetto  * COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
21*58771c1cSSalvatore Benedetto  * SOFTWARE IS DISCLAIMED.
22*58771c1cSSalvatore Benedetto  */
23*58771c1cSSalvatore Benedetto #include "ecdh_helper.h"
24*58771c1cSSalvatore Benedetto 
25*58771c1cSSalvatore Benedetto #include <linux/random.h>
26*58771c1cSSalvatore Benedetto #include <linux/scatterlist.h>
27*58771c1cSSalvatore Benedetto #include <crypto/kpp.h>
28*58771c1cSSalvatore Benedetto #include <crypto/ecdh.h>
29*58771c1cSSalvatore Benedetto 
30*58771c1cSSalvatore Benedetto struct ecdh_completion {
31*58771c1cSSalvatore Benedetto 	struct completion completion;
32*58771c1cSSalvatore Benedetto 	int err;
33*58771c1cSSalvatore Benedetto };
34*58771c1cSSalvatore Benedetto 
35*58771c1cSSalvatore Benedetto static void ecdh_complete(struct crypto_async_request *req, int err)
36*58771c1cSSalvatore Benedetto {
37*58771c1cSSalvatore Benedetto 	struct ecdh_completion *res = req->data;
38*58771c1cSSalvatore Benedetto 
39*58771c1cSSalvatore Benedetto 	if (err == -EINPROGRESS)
40*58771c1cSSalvatore Benedetto 		return;
41*58771c1cSSalvatore Benedetto 
42*58771c1cSSalvatore Benedetto 	res->err = err;
43*58771c1cSSalvatore Benedetto 	complete(&res->completion);
44*58771c1cSSalvatore Benedetto }
45*58771c1cSSalvatore Benedetto 
46*58771c1cSSalvatore Benedetto static inline void swap_digits(u64 *in, u64 *out, unsigned int ndigits)
47*58771c1cSSalvatore Benedetto {
48*58771c1cSSalvatore Benedetto 	int i;
49*58771c1cSSalvatore Benedetto 
50*58771c1cSSalvatore Benedetto 	for (i = 0; i < ndigits; i++)
51*58771c1cSSalvatore Benedetto 		out[i] = __swab64(in[ndigits - 1 - i]);
52*58771c1cSSalvatore Benedetto }
53*58771c1cSSalvatore Benedetto 
54*58771c1cSSalvatore Benedetto bool compute_ecdh_secret(const u8 public_key[64], const u8 private_key[32],
55*58771c1cSSalvatore Benedetto 			 u8 secret[32])
56*58771c1cSSalvatore Benedetto {
57*58771c1cSSalvatore Benedetto 	struct crypto_kpp *tfm;
58*58771c1cSSalvatore Benedetto 	struct kpp_request *req;
59*58771c1cSSalvatore Benedetto 	struct ecdh p;
60*58771c1cSSalvatore Benedetto 	struct ecdh_completion result;
61*58771c1cSSalvatore Benedetto 	struct scatterlist src, dst;
62*58771c1cSSalvatore Benedetto 	u8 tmp[64];
63*58771c1cSSalvatore Benedetto 	u8 *buf;
64*58771c1cSSalvatore Benedetto 	unsigned int buf_len;
65*58771c1cSSalvatore Benedetto 	int err = -ENOMEM;
66*58771c1cSSalvatore Benedetto 
67*58771c1cSSalvatore Benedetto 	tfm = crypto_alloc_kpp("ecdh", CRYPTO_ALG_INTERNAL, 0);
68*58771c1cSSalvatore Benedetto 	if (IS_ERR(tfm)) {
69*58771c1cSSalvatore Benedetto 		pr_err("alg: kpp: Failed to load tfm for kpp: %ld\n",
70*58771c1cSSalvatore Benedetto 		       PTR_ERR(tfm));
71*58771c1cSSalvatore Benedetto 		return false;
72*58771c1cSSalvatore Benedetto 	}
73*58771c1cSSalvatore Benedetto 
74*58771c1cSSalvatore Benedetto 	req = kpp_request_alloc(tfm, GFP_KERNEL);
75*58771c1cSSalvatore Benedetto 	if (!req)
76*58771c1cSSalvatore Benedetto 		goto free_kpp;
77*58771c1cSSalvatore Benedetto 
78*58771c1cSSalvatore Benedetto 	init_completion(&result.completion);
79*58771c1cSSalvatore Benedetto 
80*58771c1cSSalvatore Benedetto 	/* Security Manager Protocol holds digits in litte-endian order
81*58771c1cSSalvatore Benedetto 	 * while ECC API expect big-endian data
82*58771c1cSSalvatore Benedetto 	 */
83*58771c1cSSalvatore Benedetto 	swap_digits((u64 *)private_key, (u64 *)tmp, 4);
84*58771c1cSSalvatore Benedetto 	p.key = (char *)tmp;
85*58771c1cSSalvatore Benedetto 	p.key_size = 32;
86*58771c1cSSalvatore Benedetto 	/* Set curve_id */
87*58771c1cSSalvatore Benedetto 	p.curve_id = ECC_CURVE_NIST_P256;
88*58771c1cSSalvatore Benedetto 	buf_len = crypto_ecdh_key_len(&p);
89*58771c1cSSalvatore Benedetto 	buf = kmalloc(buf_len, GFP_KERNEL);
90*58771c1cSSalvatore Benedetto 	if (!buf) {
91*58771c1cSSalvatore Benedetto 		pr_err("alg: kpp: Failed to allocate %d bytes for buf\n",
92*58771c1cSSalvatore Benedetto 		       buf_len);
93*58771c1cSSalvatore Benedetto 		goto free_req;
94*58771c1cSSalvatore Benedetto 	}
95*58771c1cSSalvatore Benedetto 	crypto_ecdh_encode_key(buf, buf_len, &p);
96*58771c1cSSalvatore Benedetto 
97*58771c1cSSalvatore Benedetto 	/* Set A private Key */
98*58771c1cSSalvatore Benedetto 	err = crypto_kpp_set_secret(tfm, (void *)buf, buf_len);
99*58771c1cSSalvatore Benedetto 	if (err)
100*58771c1cSSalvatore Benedetto 		goto free_all;
101*58771c1cSSalvatore Benedetto 
102*58771c1cSSalvatore Benedetto 	swap_digits((u64 *)public_key, (u64 *)tmp, 4); /* x */
103*58771c1cSSalvatore Benedetto 	swap_digits((u64 *)&public_key[32], (u64 *)&tmp[32], 4); /* y */
104*58771c1cSSalvatore Benedetto 
105*58771c1cSSalvatore Benedetto 	sg_init_one(&src, tmp, 64);
106*58771c1cSSalvatore Benedetto 	sg_init_one(&dst, secret, 32);
107*58771c1cSSalvatore Benedetto 	kpp_request_set_input(req, &src, 64);
108*58771c1cSSalvatore Benedetto 	kpp_request_set_output(req, &dst, 32);
109*58771c1cSSalvatore Benedetto 	kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
110*58771c1cSSalvatore Benedetto 				 ecdh_complete, &result);
111*58771c1cSSalvatore Benedetto 	err = crypto_kpp_compute_shared_secret(req);
112*58771c1cSSalvatore Benedetto 	if (err == -EINPROGRESS) {
113*58771c1cSSalvatore Benedetto 		wait_for_completion(&result.completion);
114*58771c1cSSalvatore Benedetto 		err = result.err;
115*58771c1cSSalvatore Benedetto 	}
116*58771c1cSSalvatore Benedetto 	if (err < 0) {
117*58771c1cSSalvatore Benedetto 		pr_err("alg: ecdh: compute shared secret failed. err %d\n",
118*58771c1cSSalvatore Benedetto 		       err);
119*58771c1cSSalvatore Benedetto 		goto free_all;
120*58771c1cSSalvatore Benedetto 	}
121*58771c1cSSalvatore Benedetto 
122*58771c1cSSalvatore Benedetto 	swap_digits((u64 *)secret, (u64 *)tmp, 4);
123*58771c1cSSalvatore Benedetto 	memcpy(secret, tmp, 32);
124*58771c1cSSalvatore Benedetto 
125*58771c1cSSalvatore Benedetto free_all:
126*58771c1cSSalvatore Benedetto 	kzfree(buf);
127*58771c1cSSalvatore Benedetto free_req:
128*58771c1cSSalvatore Benedetto 	kpp_request_free(req);
129*58771c1cSSalvatore Benedetto free_kpp:
130*58771c1cSSalvatore Benedetto 	crypto_free_kpp(tfm);
131*58771c1cSSalvatore Benedetto 	return (err == 0);
132*58771c1cSSalvatore Benedetto }
133*58771c1cSSalvatore Benedetto 
134*58771c1cSSalvatore Benedetto bool generate_ecdh_keys(u8 public_key[64], u8 private_key[32])
135*58771c1cSSalvatore Benedetto {
136*58771c1cSSalvatore Benedetto 	struct crypto_kpp *tfm;
137*58771c1cSSalvatore Benedetto 	struct kpp_request *req;
138*58771c1cSSalvatore Benedetto 	struct ecdh p;
139*58771c1cSSalvatore Benedetto 	struct ecdh_completion result;
140*58771c1cSSalvatore Benedetto 	struct scatterlist dst;
141*58771c1cSSalvatore Benedetto 	u8 tmp[64];
142*58771c1cSSalvatore Benedetto 	u8 *buf;
143*58771c1cSSalvatore Benedetto 	unsigned int buf_len;
144*58771c1cSSalvatore Benedetto 	int err = -ENOMEM;
145*58771c1cSSalvatore Benedetto 	const unsigned short max_tries = 16;
146*58771c1cSSalvatore Benedetto 	unsigned short tries = 0;
147*58771c1cSSalvatore Benedetto 
148*58771c1cSSalvatore Benedetto 	tfm = crypto_alloc_kpp("ecdh", CRYPTO_ALG_INTERNAL, 0);
149*58771c1cSSalvatore Benedetto 	if (IS_ERR(tfm)) {
150*58771c1cSSalvatore Benedetto 		pr_err("alg: kpp: Failed to load tfm for kpp: %ld\n",
151*58771c1cSSalvatore Benedetto 		       PTR_ERR(tfm));
152*58771c1cSSalvatore Benedetto 		return false;
153*58771c1cSSalvatore Benedetto 	}
154*58771c1cSSalvatore Benedetto 
155*58771c1cSSalvatore Benedetto 	req = kpp_request_alloc(tfm, GFP_KERNEL);
156*58771c1cSSalvatore Benedetto 	if (!req)
157*58771c1cSSalvatore Benedetto 		goto free_kpp;
158*58771c1cSSalvatore Benedetto 
159*58771c1cSSalvatore Benedetto 	init_completion(&result.completion);
160*58771c1cSSalvatore Benedetto 
161*58771c1cSSalvatore Benedetto 	/* Set curve_id */
162*58771c1cSSalvatore Benedetto 	p.curve_id = ECC_CURVE_NIST_P256;
163*58771c1cSSalvatore Benedetto 	p.key_size = 32;
164*58771c1cSSalvatore Benedetto 	buf_len = crypto_ecdh_key_len(&p);
165*58771c1cSSalvatore Benedetto 	buf = kmalloc(buf_len, GFP_KERNEL);
166*58771c1cSSalvatore Benedetto 	if (!buf) {
167*58771c1cSSalvatore Benedetto 		pr_err("alg: kpp: Failed to allocate %d bytes for buf\n",
168*58771c1cSSalvatore Benedetto 		       buf_len);
169*58771c1cSSalvatore Benedetto 		goto free_req;
170*58771c1cSSalvatore Benedetto 	}
171*58771c1cSSalvatore Benedetto 
172*58771c1cSSalvatore Benedetto 	do {
173*58771c1cSSalvatore Benedetto 		if (tries++ >= max_tries)
174*58771c1cSSalvatore Benedetto 			goto free_all;
175*58771c1cSSalvatore Benedetto 
176*58771c1cSSalvatore Benedetto 		get_random_bytes(private_key, 32);
177*58771c1cSSalvatore Benedetto 
178*58771c1cSSalvatore Benedetto 		/* Set private Key */
179*58771c1cSSalvatore Benedetto 		p.key = (char *)private_key;
180*58771c1cSSalvatore Benedetto 		crypto_ecdh_encode_key(buf, buf_len, &p);
181*58771c1cSSalvatore Benedetto 		err = crypto_kpp_set_secret(tfm, buf, buf_len);
182*58771c1cSSalvatore Benedetto 		if (err)
183*58771c1cSSalvatore Benedetto 			goto free_all;
184*58771c1cSSalvatore Benedetto 
185*58771c1cSSalvatore Benedetto 		sg_init_one(&dst, tmp, 64);
186*58771c1cSSalvatore Benedetto 		kpp_request_set_output(req, &dst, 64);
187*58771c1cSSalvatore Benedetto 		kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
188*58771c1cSSalvatore Benedetto 					 ecdh_complete, &result);
189*58771c1cSSalvatore Benedetto 
190*58771c1cSSalvatore Benedetto 		err = crypto_kpp_generate_public_key(req);
191*58771c1cSSalvatore Benedetto 
192*58771c1cSSalvatore Benedetto 		if (err == -EINPROGRESS) {
193*58771c1cSSalvatore Benedetto 			wait_for_completion(&result.completion);
194*58771c1cSSalvatore Benedetto 			err = result.err;
195*58771c1cSSalvatore Benedetto 		}
196*58771c1cSSalvatore Benedetto 
197*58771c1cSSalvatore Benedetto 		/* Private key is not valid. Regenerate */
198*58771c1cSSalvatore Benedetto 		if (err == -EINVAL)
199*58771c1cSSalvatore Benedetto 			continue;
200*58771c1cSSalvatore Benedetto 
201*58771c1cSSalvatore Benedetto 		if (err < 0)
202*58771c1cSSalvatore Benedetto 			goto free_all;
203*58771c1cSSalvatore Benedetto 		else
204*58771c1cSSalvatore Benedetto 			break;
205*58771c1cSSalvatore Benedetto 
206*58771c1cSSalvatore Benedetto 	} while (true);
207*58771c1cSSalvatore Benedetto 
208*58771c1cSSalvatore Benedetto 	/* Keys are handed back in little endian as expected by Security
209*58771c1cSSalvatore Benedetto 	 * Manager Protocol
210*58771c1cSSalvatore Benedetto 	 */
211*58771c1cSSalvatore Benedetto 	swap_digits((u64 *)tmp, (u64 *)public_key, 4); /* x */
212*58771c1cSSalvatore Benedetto 	swap_digits((u64 *)&tmp[32], (u64 *)&public_key[32], 4); /* y */
213*58771c1cSSalvatore Benedetto 	swap_digits((u64 *)private_key, (u64 *)tmp, 4);
214*58771c1cSSalvatore Benedetto 	memcpy(private_key, tmp, 32);
215*58771c1cSSalvatore Benedetto 
216*58771c1cSSalvatore Benedetto free_all:
217*58771c1cSSalvatore Benedetto 	kzfree(buf);
218*58771c1cSSalvatore Benedetto free_req:
219*58771c1cSSalvatore Benedetto 	kpp_request_free(req);
220*58771c1cSSalvatore Benedetto free_kpp:
221*58771c1cSSalvatore Benedetto 	crypto_free_kpp(tfm);
222*58771c1cSSalvatore Benedetto 	return (err == 0);
223*58771c1cSSalvatore Benedetto }
224