xref: /aosp_15_r20/external/libwebsockets/lib/tls/openssl/lws-genec.c (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
1*1c60b9acSAndroid Build Coastguard Worker  /*
2*1c60b9acSAndroid Build Coastguard Worker  * libwebsockets - small server side websockets and web server implementation
3*1c60b9acSAndroid Build Coastguard Worker  *
4*1c60b9acSAndroid Build Coastguard Worker  * Copyright (C) 2010 - 2019 Andy Green <[email protected]>
5*1c60b9acSAndroid Build Coastguard Worker  *
6*1c60b9acSAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a copy
7*1c60b9acSAndroid Build Coastguard Worker  * of this software and associated documentation files (the "Software"), to
8*1c60b9acSAndroid Build Coastguard Worker  * deal in the Software without restriction, including without limitation the
9*1c60b9acSAndroid Build Coastguard Worker  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10*1c60b9acSAndroid Build Coastguard Worker  * sell copies of the Software, and to permit persons to whom the Software is
11*1c60b9acSAndroid Build Coastguard Worker  * furnished to do so, subject to the following conditions:
12*1c60b9acSAndroid Build Coastguard Worker  *
13*1c60b9acSAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be included in
14*1c60b9acSAndroid Build Coastguard Worker  * all copies or substantial portions of the Software.
15*1c60b9acSAndroid Build Coastguard Worker  *
16*1c60b9acSAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*1c60b9acSAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*1c60b9acSAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19*1c60b9acSAndroid Build Coastguard Worker  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*1c60b9acSAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21*1c60b9acSAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22*1c60b9acSAndroid Build Coastguard Worker  * IN THE SOFTWARE.
23*1c60b9acSAndroid Build Coastguard Worker  *
24*1c60b9acSAndroid Build Coastguard Worker  *  lws_genec provides an EC abstraction api in lws that works the
25*1c60b9acSAndroid Build Coastguard Worker  *  same whether you are using openssl or mbedtls crypto functions underneath.
26*1c60b9acSAndroid Build Coastguard Worker  */
27*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-core.h"
28*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-tls-openssl.h"
29*1c60b9acSAndroid Build Coastguard Worker 
30*1c60b9acSAndroid Build Coastguard Worker #if !defined(OPENSSL_NO_EC) && defined(LWS_HAVE_EC_KEY_new_by_curve_name) && \
31*1c60b9acSAndroid Build Coastguard Worker     (OPENSSL_VERSION_NUMBER >= 0x30000000l) && \
32*1c60b9acSAndroid Build Coastguard Worker      !defined(LWS_SUPPRESS_DEPRECATED_API_WARNINGS)
33*1c60b9acSAndroid Build Coastguard Worker /* msvc doesn't have #warning... */
34*1c60b9acSAndroid Build Coastguard Worker #error "You probably need LWS_SUPPRESS_DEPRECATED_API_WARNINGS"
35*1c60b9acSAndroid Build Coastguard Worker #endif
36*1c60b9acSAndroid Build Coastguard Worker 
37*1c60b9acSAndroid Build Coastguard Worker #if defined(USE_WOLFSSL)
38*1c60b9acSAndroid Build Coastguard Worker #include "openssl/ecdh.h"
39*1c60b9acSAndroid Build Coastguard Worker #endif
40*1c60b9acSAndroid Build Coastguard Worker 
41*1c60b9acSAndroid Build Coastguard Worker /*
42*1c60b9acSAndroid Build Coastguard Worker  * Care: many openssl apis return 1 for success.  These are translated to the
43*1c60b9acSAndroid Build Coastguard Worker  * lws convention of 0 for success.
44*1c60b9acSAndroid Build Coastguard Worker  */
45*1c60b9acSAndroid Build Coastguard Worker 
46*1c60b9acSAndroid Build Coastguard Worker #if defined(USE_WOLFSSL)
EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX * p)47*1c60b9acSAndroid Build Coastguard Worker EVP_PKEY * EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *p)
48*1c60b9acSAndroid Build Coastguard Worker {
49*1c60b9acSAndroid Build Coastguard Worker 	return p->pkey;
50*1c60b9acSAndroid Build Coastguard Worker }
51*1c60b9acSAndroid Build Coastguard Worker #endif
52*1c60b9acSAndroid Build Coastguard Worker 
53*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_HAVE_ECDSA_SIG_set0)
54*1c60b9acSAndroid Build Coastguard Worker static void
ECDSA_SIG_get0(const ECDSA_SIG * sig,const BIGNUM ** pr,const BIGNUM ** ps)55*1c60b9acSAndroid Build Coastguard Worker ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
56*1c60b9acSAndroid Build Coastguard Worker {
57*1c60b9acSAndroid Build Coastguard Worker     if (pr != NULL)
58*1c60b9acSAndroid Build Coastguard Worker         *pr = sig->r;
59*1c60b9acSAndroid Build Coastguard Worker     if (ps != NULL)
60*1c60b9acSAndroid Build Coastguard Worker         *ps = sig->s;
61*1c60b9acSAndroid Build Coastguard Worker }
62*1c60b9acSAndroid Build Coastguard Worker 
63*1c60b9acSAndroid Build Coastguard Worker static int
ECDSA_SIG_set0(ECDSA_SIG * sig,BIGNUM * r,BIGNUM * s)64*1c60b9acSAndroid Build Coastguard Worker ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s)
65*1c60b9acSAndroid Build Coastguard Worker {
66*1c60b9acSAndroid Build Coastguard Worker 	if (r == NULL || s == NULL)
67*1c60b9acSAndroid Build Coastguard Worker 		return 0;
68*1c60b9acSAndroid Build Coastguard Worker 	BN_clear_free(sig->r);
69*1c60b9acSAndroid Build Coastguard Worker 	BN_clear_free(sig->s);
70*1c60b9acSAndroid Build Coastguard Worker 	sig->r = r;
71*1c60b9acSAndroid Build Coastguard Worker 	sig->s = s;
72*1c60b9acSAndroid Build Coastguard Worker 
73*1c60b9acSAndroid Build Coastguard Worker 	return 1;
74*1c60b9acSAndroid Build Coastguard Worker }
75*1c60b9acSAndroid Build Coastguard Worker #endif
76*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_HAVE_BN_bn2binpad)
BN_bn2binpad(const BIGNUM * a,unsigned char * to,int tolen)77*1c60b9acSAndroid Build Coastguard Worker int BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen)
78*1c60b9acSAndroid Build Coastguard Worker {
79*1c60b9acSAndroid Build Coastguard Worker     int i;
80*1c60b9acSAndroid Build Coastguard Worker #if !defined(USE_WOLFSSL)
81*1c60b9acSAndroid Build Coastguard Worker     BN_ULONG l;
82*1c60b9acSAndroid Build Coastguard Worker #endif
83*1c60b9acSAndroid Build Coastguard Worker 
84*1c60b9acSAndroid Build Coastguard Worker #if !defined(LIBRESSL_VERSION_NUMBER) && !defined(USE_WOLFSSL)
85*1c60b9acSAndroid Build Coastguard Worker     bn_check_top(a);
86*1c60b9acSAndroid Build Coastguard Worker #endif
87*1c60b9acSAndroid Build Coastguard Worker     i = BN_num_bytes(a);
88*1c60b9acSAndroid Build Coastguard Worker 
89*1c60b9acSAndroid Build Coastguard Worker     /* Add leading zeroes if necessary */
90*1c60b9acSAndroid Build Coastguard Worker     if (tolen > i) {
91*1c60b9acSAndroid Build Coastguard Worker         memset(to, 0, (size_t)(tolen - i));
92*1c60b9acSAndroid Build Coastguard Worker         to += tolen - i;
93*1c60b9acSAndroid Build Coastguard Worker     }
94*1c60b9acSAndroid Build Coastguard Worker #if defined(USE_WOLFSSL)
95*1c60b9acSAndroid Build Coastguard Worker     BN_bn2bin(a, to);
96*1c60b9acSAndroid Build Coastguard Worker #else
97*1c60b9acSAndroid Build Coastguard Worker     while (i--) {
98*1c60b9acSAndroid Build Coastguard Worker         l = a->d[i / BN_BYTES];
99*1c60b9acSAndroid Build Coastguard Worker         *(to++) = (unsigned char)(l >> (8 * (i % BN_BYTES))) & 0xff;
100*1c60b9acSAndroid Build Coastguard Worker     }
101*1c60b9acSAndroid Build Coastguard Worker #endif
102*1c60b9acSAndroid Build Coastguard Worker     return tolen;
103*1c60b9acSAndroid Build Coastguard Worker }
104*1c60b9acSAndroid Build Coastguard Worker #endif
105*1c60b9acSAndroid Build Coastguard Worker 
106*1c60b9acSAndroid Build Coastguard Worker const struct lws_ec_curves lws_ec_curves[4] = {
107*1c60b9acSAndroid Build Coastguard Worker 	/*
108*1c60b9acSAndroid Build Coastguard Worker 	 * These are the curves we are willing to use by default...
109*1c60b9acSAndroid Build Coastguard Worker 	 *
110*1c60b9acSAndroid Build Coastguard Worker 	 * The 3 recommended+ (P-256) and optional curves in RFC7518 7.6
111*1c60b9acSAndroid Build Coastguard Worker 	 *
112*1c60b9acSAndroid Build Coastguard Worker 	 * Specific keys lengths from RFC8422 p20
113*1c60b9acSAndroid Build Coastguard Worker 	 */
114*1c60b9acSAndroid Build Coastguard Worker 	{ "P-256", NID_X9_62_prime256v1, 32 },
115*1c60b9acSAndroid Build Coastguard Worker 	{ "P-384", NID_secp384r1,	 48 },
116*1c60b9acSAndroid Build Coastguard Worker 	{ "P-521", NID_secp521r1,	 66 },
117*1c60b9acSAndroid Build Coastguard Worker 
118*1c60b9acSAndroid Build Coastguard Worker 	{ NULL, 0, 0 }
119*1c60b9acSAndroid Build Coastguard Worker };
120*1c60b9acSAndroid Build Coastguard Worker 
121*1c60b9acSAndroid Build Coastguard Worker static int
lws_genec_eckey_import(int nid,EVP_PKEY * pkey,const struct lws_gencrypto_keyelem * el)122*1c60b9acSAndroid Build Coastguard Worker lws_genec_eckey_import(int nid, EVP_PKEY *pkey,
123*1c60b9acSAndroid Build Coastguard Worker 		       const struct lws_gencrypto_keyelem *el)
124*1c60b9acSAndroid Build Coastguard Worker {
125*1c60b9acSAndroid Build Coastguard Worker 	EC_KEY *ec = EC_KEY_new_by_curve_name(nid);
126*1c60b9acSAndroid Build Coastguard Worker 	BIGNUM *bn_d, *bn_x, *bn_y;
127*1c60b9acSAndroid Build Coastguard Worker 	int n;
128*1c60b9acSAndroid Build Coastguard Worker 
129*1c60b9acSAndroid Build Coastguard Worker 	if (!ec)
130*1c60b9acSAndroid Build Coastguard Worker 		return -1;
131*1c60b9acSAndroid Build Coastguard Worker 
132*1c60b9acSAndroid Build Coastguard Worker 	/*
133*1c60b9acSAndroid Build Coastguard Worker 	 * EC_KEY contains
134*1c60b9acSAndroid Build Coastguard Worker 	 *
135*1c60b9acSAndroid Build Coastguard Worker 	 * EC_GROUP * 	group
136*1c60b9acSAndroid Build Coastguard Worker 	 * EC_POINT * 	pub_key
137*1c60b9acSAndroid Build Coastguard Worker 	 * BIGNUM * 	priv_key  (ie, d)
138*1c60b9acSAndroid Build Coastguard Worker 	 */
139*1c60b9acSAndroid Build Coastguard Worker 
140*1c60b9acSAndroid Build Coastguard Worker 	bn_x = BN_bin2bn(el[LWS_GENCRYPTO_EC_KEYEL_X].buf,
141*1c60b9acSAndroid Build Coastguard Worker 			 (int)el[LWS_GENCRYPTO_EC_KEYEL_X].len, NULL);
142*1c60b9acSAndroid Build Coastguard Worker 	if (!bn_x) {
143*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: BN_bin2bn (x) fail\n", __func__);
144*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
145*1c60b9acSAndroid Build Coastguard Worker 	}
146*1c60b9acSAndroid Build Coastguard Worker 	bn_y = BN_bin2bn(el[LWS_GENCRYPTO_EC_KEYEL_Y].buf,
147*1c60b9acSAndroid Build Coastguard Worker 			(int)el[LWS_GENCRYPTO_EC_KEYEL_Y].len, NULL);
148*1c60b9acSAndroid Build Coastguard Worker 	if (!bn_y) {
149*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: BN_bin2bn (y) fail\n", __func__);
150*1c60b9acSAndroid Build Coastguard Worker 		goto bail1;
151*1c60b9acSAndroid Build Coastguard Worker 	}
152*1c60b9acSAndroid Build Coastguard Worker 
153*1c60b9acSAndroid Build Coastguard Worker 	/*
154*1c60b9acSAndroid Build Coastguard Worker 	 * EC_KEY_set_public_key_affine_coordinates sets the public key for
155*1c60b9acSAndroid Build Coastguard Worker 	 * key based on its affine co-ordinates, i.e. it constructs an
156*1c60b9acSAndroid Build Coastguard Worker 	 * EC_POINT object based on the supplied x and y values and sets
157*1c60b9acSAndroid Build Coastguard Worker 	 * the public key to be this EC_POINT. It will also performs
158*1c60b9acSAndroid Build Coastguard Worker 	 * certain sanity checks on the key to confirm that it is valid.
159*1c60b9acSAndroid Build Coastguard Worker 	 */
160*1c60b9acSAndroid Build Coastguard Worker 
161*1c60b9acSAndroid Build Coastguard Worker #if defined(USE_WOLFSSL)
162*1c60b9acSAndroid Build Coastguard Worker 	n = wolfSSL_EC_POINT_set_affine_coordinates_GFp(ec->group,
163*1c60b9acSAndroid Build Coastguard Worker                                                 ec->pub_key,
164*1c60b9acSAndroid Build Coastguard Worker                                                 bn_x, bn_y,
165*1c60b9acSAndroid Build Coastguard Worker                                                 NULL);
166*1c60b9acSAndroid Build Coastguard Worker #else
167*1c60b9acSAndroid Build Coastguard Worker 	n = EC_KEY_set_public_key_affine_coordinates(ec, bn_x, bn_y);
168*1c60b9acSAndroid Build Coastguard Worker #endif
169*1c60b9acSAndroid Build Coastguard Worker 	BN_free(bn_x);
170*1c60b9acSAndroid Build Coastguard Worker 	BN_free(bn_y);
171*1c60b9acSAndroid Build Coastguard Worker 	if (n != 1) {
172*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: EC_KEY_set_public_key_affine_coordinates fail:\n",
173*1c60b9acSAndroid Build Coastguard Worker 			 __func__);
174*1c60b9acSAndroid Build Coastguard Worker 		lws_tls_err_describe_clear();
175*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
176*1c60b9acSAndroid Build Coastguard Worker 	}
177*1c60b9acSAndroid Build Coastguard Worker 
178*1c60b9acSAndroid Build Coastguard Worker 	if (el[LWS_GENCRYPTO_EC_KEYEL_D].len) {
179*1c60b9acSAndroid Build Coastguard Worker 		bn_d = BN_bin2bn(el[LWS_GENCRYPTO_EC_KEYEL_D].buf,
180*1c60b9acSAndroid Build Coastguard Worker 				(int)el[LWS_GENCRYPTO_EC_KEYEL_D].len, NULL);
181*1c60b9acSAndroid Build Coastguard Worker 		if (!bn_d) {
182*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: BN_bin2bn (d) fail\n", __func__);
183*1c60b9acSAndroid Build Coastguard Worker 			goto bail;
184*1c60b9acSAndroid Build Coastguard Worker 		}
185*1c60b9acSAndroid Build Coastguard Worker 
186*1c60b9acSAndroid Build Coastguard Worker 		n = EC_KEY_set_private_key(ec, bn_d);
187*1c60b9acSAndroid Build Coastguard Worker 		BN_clear_free(bn_d);
188*1c60b9acSAndroid Build Coastguard Worker 		if (n != 1) {
189*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: EC_KEY_set_private_key fail\n", __func__);
190*1c60b9acSAndroid Build Coastguard Worker 			goto bail;
191*1c60b9acSAndroid Build Coastguard Worker 		}
192*1c60b9acSAndroid Build Coastguard Worker 	}
193*1c60b9acSAndroid Build Coastguard Worker 
194*1c60b9acSAndroid Build Coastguard Worker 	/* explicitly confirm the key pieces are consistent */
195*1c60b9acSAndroid Build Coastguard Worker 
196*1c60b9acSAndroid Build Coastguard Worker #if !defined(USE_WOLFSSL)
197*1c60b9acSAndroid Build Coastguard Worker 	if (EC_KEY_check_key(ec) != 1) {
198*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: EC_KEY_set_private_key fail\n", __func__);
199*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
200*1c60b9acSAndroid Build Coastguard Worker 	}
201*1c60b9acSAndroid Build Coastguard Worker #endif
202*1c60b9acSAndroid Build Coastguard Worker 
203*1c60b9acSAndroid Build Coastguard Worker 	n = EVP_PKEY_assign_EC_KEY(pkey, ec);
204*1c60b9acSAndroid Build Coastguard Worker 	if (n != 1) {
205*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: EVP_PKEY_set1_EC_KEY failed\n", __func__);
206*1c60b9acSAndroid Build Coastguard Worker 		return -1;
207*1c60b9acSAndroid Build Coastguard Worker 	}
208*1c60b9acSAndroid Build Coastguard Worker 
209*1c60b9acSAndroid Build Coastguard Worker 	return 0;
210*1c60b9acSAndroid Build Coastguard Worker 
211*1c60b9acSAndroid Build Coastguard Worker bail1:
212*1c60b9acSAndroid Build Coastguard Worker 	BN_free(bn_x);
213*1c60b9acSAndroid Build Coastguard Worker bail:
214*1c60b9acSAndroid Build Coastguard Worker 	EC_KEY_free(ec);
215*1c60b9acSAndroid Build Coastguard Worker 
216*1c60b9acSAndroid Build Coastguard Worker 	return -1;
217*1c60b9acSAndroid Build Coastguard Worker }
218*1c60b9acSAndroid Build Coastguard Worker 
219*1c60b9acSAndroid Build Coastguard Worker static int
lws_genec_keypair_import(struct lws_genec_ctx * ctx,const struct lws_ec_curves * curve_table,EVP_PKEY_CTX ** pctx,const struct lws_gencrypto_keyelem * el)220*1c60b9acSAndroid Build Coastguard Worker lws_genec_keypair_import(struct lws_genec_ctx *ctx,
221*1c60b9acSAndroid Build Coastguard Worker 			 const struct lws_ec_curves *curve_table,
222*1c60b9acSAndroid Build Coastguard Worker 			 EVP_PKEY_CTX **pctx,
223*1c60b9acSAndroid Build Coastguard Worker 			 const struct lws_gencrypto_keyelem *el)
224*1c60b9acSAndroid Build Coastguard Worker {
225*1c60b9acSAndroid Build Coastguard Worker 	EVP_PKEY *pkey = NULL;
226*1c60b9acSAndroid Build Coastguard Worker 	const struct lws_ec_curves *curve;
227*1c60b9acSAndroid Build Coastguard Worker 
228*1c60b9acSAndroid Build Coastguard Worker 	if (el[LWS_GENCRYPTO_EC_KEYEL_CRV].len < 4)
229*1c60b9acSAndroid Build Coastguard Worker 		return -2;
230*1c60b9acSAndroid Build Coastguard Worker 
231*1c60b9acSAndroid Build Coastguard Worker 	curve = lws_genec_curve(curve_table,
232*1c60b9acSAndroid Build Coastguard Worker 				(char *)el[LWS_GENCRYPTO_EC_KEYEL_CRV].buf);
233*1c60b9acSAndroid Build Coastguard Worker 	if (!curve)
234*1c60b9acSAndroid Build Coastguard Worker 		return -3;
235*1c60b9acSAndroid Build Coastguard Worker 
236*1c60b9acSAndroid Build Coastguard Worker 	if ((el[LWS_GENCRYPTO_EC_KEYEL_D].len &&
237*1c60b9acSAndroid Build Coastguard Worker 	     el[LWS_GENCRYPTO_EC_KEYEL_D].len != curve->key_bytes) ||
238*1c60b9acSAndroid Build Coastguard Worker 	    el[LWS_GENCRYPTO_EC_KEYEL_X].len != curve->key_bytes ||
239*1c60b9acSAndroid Build Coastguard Worker 	    el[LWS_GENCRYPTO_EC_KEYEL_Y].len != curve->key_bytes)
240*1c60b9acSAndroid Build Coastguard Worker 		return -4;
241*1c60b9acSAndroid Build Coastguard Worker 
242*1c60b9acSAndroid Build Coastguard Worker 	ctx->has_private = !!el[LWS_GENCRYPTO_EC_KEYEL_D].len;
243*1c60b9acSAndroid Build Coastguard Worker 
244*1c60b9acSAndroid Build Coastguard Worker 	pkey = EVP_PKEY_new();
245*1c60b9acSAndroid Build Coastguard Worker 	if (!pkey)
246*1c60b9acSAndroid Build Coastguard Worker 		return -7;
247*1c60b9acSAndroid Build Coastguard Worker 
248*1c60b9acSAndroid Build Coastguard Worker 	if (lws_genec_eckey_import(curve->tls_lib_nid, pkey, el)) {
249*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: lws_genec_eckey_import fail\n", __func__);
250*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
251*1c60b9acSAndroid Build Coastguard Worker 	}
252*1c60b9acSAndroid Build Coastguard Worker 
253*1c60b9acSAndroid Build Coastguard Worker 	*pctx = EVP_PKEY_CTX_new(pkey, NULL);
254*1c60b9acSAndroid Build Coastguard Worker 	EVP_PKEY_free(pkey);
255*1c60b9acSAndroid Build Coastguard Worker 	pkey = NULL;
256*1c60b9acSAndroid Build Coastguard Worker 
257*1c60b9acSAndroid Build Coastguard Worker 	if (!*pctx)
258*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
259*1c60b9acSAndroid Build Coastguard Worker 
260*1c60b9acSAndroid Build Coastguard Worker 	return 0;
261*1c60b9acSAndroid Build Coastguard Worker 
262*1c60b9acSAndroid Build Coastguard Worker bail:
263*1c60b9acSAndroid Build Coastguard Worker 	if (pkey)
264*1c60b9acSAndroid Build Coastguard Worker 		EVP_PKEY_free(pkey);
265*1c60b9acSAndroid Build Coastguard Worker 
266*1c60b9acSAndroid Build Coastguard Worker 	if (*pctx) {
267*1c60b9acSAndroid Build Coastguard Worker 		EVP_PKEY_CTX_free(*pctx);
268*1c60b9acSAndroid Build Coastguard Worker 		*pctx = NULL;
269*1c60b9acSAndroid Build Coastguard Worker 	}
270*1c60b9acSAndroid Build Coastguard Worker 
271*1c60b9acSAndroid Build Coastguard Worker 	return -9;
272*1c60b9acSAndroid Build Coastguard Worker }
273*1c60b9acSAndroid Build Coastguard Worker 
274*1c60b9acSAndroid Build Coastguard Worker int
lws_genecdh_create(struct lws_genec_ctx * ctx,struct lws_context * context,const struct lws_ec_curves * curve_table)275*1c60b9acSAndroid Build Coastguard Worker lws_genecdh_create(struct lws_genec_ctx *ctx, struct lws_context *context,
276*1c60b9acSAndroid Build Coastguard Worker 		   const struct lws_ec_curves *curve_table)
277*1c60b9acSAndroid Build Coastguard Worker {
278*1c60b9acSAndroid Build Coastguard Worker 	ctx->context = context;
279*1c60b9acSAndroid Build Coastguard Worker 	ctx->ctx[0] = NULL;
280*1c60b9acSAndroid Build Coastguard Worker 	ctx->ctx[1] = NULL;
281*1c60b9acSAndroid Build Coastguard Worker 	ctx->curve_table = curve_table;
282*1c60b9acSAndroid Build Coastguard Worker 	ctx->genec_alg = LEGENEC_ECDH;
283*1c60b9acSAndroid Build Coastguard Worker 
284*1c60b9acSAndroid Build Coastguard Worker 	return 0;
285*1c60b9acSAndroid Build Coastguard Worker }
286*1c60b9acSAndroid Build Coastguard Worker 
287*1c60b9acSAndroid Build Coastguard Worker int
lws_genecdsa_create(struct lws_genec_ctx * ctx,struct lws_context * context,const struct lws_ec_curves * curve_table)288*1c60b9acSAndroid Build Coastguard Worker lws_genecdsa_create(struct lws_genec_ctx *ctx, struct lws_context *context,
289*1c60b9acSAndroid Build Coastguard Worker 		    const struct lws_ec_curves *curve_table)
290*1c60b9acSAndroid Build Coastguard Worker {
291*1c60b9acSAndroid Build Coastguard Worker 	ctx->context = context;
292*1c60b9acSAndroid Build Coastguard Worker 	ctx->ctx[0] = NULL;
293*1c60b9acSAndroid Build Coastguard Worker 	ctx->ctx[1] = NULL;
294*1c60b9acSAndroid Build Coastguard Worker 	ctx->curve_table = curve_table;
295*1c60b9acSAndroid Build Coastguard Worker 	ctx->genec_alg = LEGENEC_ECDSA;
296*1c60b9acSAndroid Build Coastguard Worker 
297*1c60b9acSAndroid Build Coastguard Worker 	return 0;
298*1c60b9acSAndroid Build Coastguard Worker }
299*1c60b9acSAndroid Build Coastguard Worker 
300*1c60b9acSAndroid Build Coastguard Worker int
lws_genecdh_set_key(struct lws_genec_ctx * ctx,struct lws_gencrypto_keyelem * el,enum enum_lws_dh_side side)301*1c60b9acSAndroid Build Coastguard Worker lws_genecdh_set_key(struct lws_genec_ctx *ctx, struct lws_gencrypto_keyelem *el,
302*1c60b9acSAndroid Build Coastguard Worker 		    enum enum_lws_dh_side side)
303*1c60b9acSAndroid Build Coastguard Worker {
304*1c60b9acSAndroid Build Coastguard Worker 	if (ctx->genec_alg != LEGENEC_ECDH)
305*1c60b9acSAndroid Build Coastguard Worker 		return -1;
306*1c60b9acSAndroid Build Coastguard Worker 
307*1c60b9acSAndroid Build Coastguard Worker 	return lws_genec_keypair_import(ctx, ctx->curve_table, &ctx->ctx[side], el);
308*1c60b9acSAndroid Build Coastguard Worker }
309*1c60b9acSAndroid Build Coastguard Worker 
310*1c60b9acSAndroid Build Coastguard Worker int
lws_genecdsa_set_key(struct lws_genec_ctx * ctx,const struct lws_gencrypto_keyelem * el)311*1c60b9acSAndroid Build Coastguard Worker lws_genecdsa_set_key(struct lws_genec_ctx *ctx,
312*1c60b9acSAndroid Build Coastguard Worker 		     const struct lws_gencrypto_keyelem *el)
313*1c60b9acSAndroid Build Coastguard Worker {
314*1c60b9acSAndroid Build Coastguard Worker 	if (ctx->genec_alg != LEGENEC_ECDSA)
315*1c60b9acSAndroid Build Coastguard Worker 		return -1;
316*1c60b9acSAndroid Build Coastguard Worker 
317*1c60b9acSAndroid Build Coastguard Worker 	return lws_genec_keypair_import(ctx, ctx->curve_table, &ctx->ctx[0], el);
318*1c60b9acSAndroid Build Coastguard Worker }
319*1c60b9acSAndroid Build Coastguard Worker 
320*1c60b9acSAndroid Build Coastguard Worker static void
lws_genec_keypair_destroy(EVP_PKEY_CTX ** pctx)321*1c60b9acSAndroid Build Coastguard Worker lws_genec_keypair_destroy(EVP_PKEY_CTX **pctx)
322*1c60b9acSAndroid Build Coastguard Worker {
323*1c60b9acSAndroid Build Coastguard Worker 	if (!*pctx)
324*1c60b9acSAndroid Build Coastguard Worker 		return;
325*1c60b9acSAndroid Build Coastguard Worker 
326*1c60b9acSAndroid Build Coastguard Worker //	lwsl_err("%p\n", EVP_PKEY_get1_EC_KEY(EVP_PKEY_CTX_get0_pkey(*pctx)));
327*1c60b9acSAndroid Build Coastguard Worker 
328*1c60b9acSAndroid Build Coastguard Worker //	EC_KEY_free(EVP_PKEY_get1_EC_KEY(EVP_PKEY_CTX_get0_pkey(*pctx)));
329*1c60b9acSAndroid Build Coastguard Worker 
330*1c60b9acSAndroid Build Coastguard Worker 	EVP_PKEY_CTX_free(*pctx);
331*1c60b9acSAndroid Build Coastguard Worker 	*pctx = NULL;
332*1c60b9acSAndroid Build Coastguard Worker }
333*1c60b9acSAndroid Build Coastguard Worker 
334*1c60b9acSAndroid Build Coastguard Worker void
lws_genec_destroy(struct lws_genec_ctx * ctx)335*1c60b9acSAndroid Build Coastguard Worker lws_genec_destroy(struct lws_genec_ctx *ctx)
336*1c60b9acSAndroid Build Coastguard Worker {
337*1c60b9acSAndroid Build Coastguard Worker 	if (ctx->ctx[0])
338*1c60b9acSAndroid Build Coastguard Worker 		lws_genec_keypair_destroy(&ctx->ctx[0]);
339*1c60b9acSAndroid Build Coastguard Worker 	if (ctx->ctx[1])
340*1c60b9acSAndroid Build Coastguard Worker 		lws_genec_keypair_destroy(&ctx->ctx[1]);
341*1c60b9acSAndroid Build Coastguard Worker }
342*1c60b9acSAndroid Build Coastguard Worker 
343*1c60b9acSAndroid Build Coastguard Worker static int
lws_genec_new_keypair(struct lws_genec_ctx * ctx,enum enum_lws_dh_side side,const char * curve_name,struct lws_gencrypto_keyelem * el)344*1c60b9acSAndroid Build Coastguard Worker lws_genec_new_keypair(struct lws_genec_ctx *ctx, enum enum_lws_dh_side side,
345*1c60b9acSAndroid Build Coastguard Worker 		      const char *curve_name, struct lws_gencrypto_keyelem *el)
346*1c60b9acSAndroid Build Coastguard Worker {
347*1c60b9acSAndroid Build Coastguard Worker 	const struct lws_ec_curves *curve;
348*1c60b9acSAndroid Build Coastguard Worker 	const EC_POINT *pubkey;
349*1c60b9acSAndroid Build Coastguard Worker 	EVP_PKEY *pkey = NULL;
350*1c60b9acSAndroid Build Coastguard Worker 	int ret = -29, n, m;
351*1c60b9acSAndroid Build Coastguard Worker 	BIGNUM *bn[3];
352*1c60b9acSAndroid Build Coastguard Worker 	EC_KEY *ec;
353*1c60b9acSAndroid Build Coastguard Worker 
354*1c60b9acSAndroid Build Coastguard Worker 	curve = lws_genec_curve(ctx->curve_table, curve_name);
355*1c60b9acSAndroid Build Coastguard Worker 	if (!curve) {
356*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: curve '%s' not supported\n",
357*1c60b9acSAndroid Build Coastguard Worker 			 __func__, curve_name);
358*1c60b9acSAndroid Build Coastguard Worker 
359*1c60b9acSAndroid Build Coastguard Worker 		return -22;
360*1c60b9acSAndroid Build Coastguard Worker 	}
361*1c60b9acSAndroid Build Coastguard Worker 
362*1c60b9acSAndroid Build Coastguard Worker 	ec = EC_KEY_new_by_curve_name(curve->tls_lib_nid);
363*1c60b9acSAndroid Build Coastguard Worker 	if (!ec) {
364*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: unknown nid %d\n", __func__, curve->tls_lib_nid);
365*1c60b9acSAndroid Build Coastguard Worker 		return -23;
366*1c60b9acSAndroid Build Coastguard Worker 	}
367*1c60b9acSAndroid Build Coastguard Worker 
368*1c60b9acSAndroid Build Coastguard Worker 	if (EC_KEY_generate_key(ec) != 1) {
369*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: EC_KEY_generate_key failed\n", __func__);
370*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
371*1c60b9acSAndroid Build Coastguard Worker 	}
372*1c60b9acSAndroid Build Coastguard Worker 
373*1c60b9acSAndroid Build Coastguard Worker 	pkey = EVP_PKEY_new();
374*1c60b9acSAndroid Build Coastguard Worker 	if (!pkey)
375*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
376*1c60b9acSAndroid Build Coastguard Worker 
377*1c60b9acSAndroid Build Coastguard Worker 	if (EVP_PKEY_set1_EC_KEY(pkey, ec) != 1) {
378*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: EVP_PKEY_assign_EC_KEY failed\n", __func__);
379*1c60b9acSAndroid Build Coastguard Worker 		goto bail1;
380*1c60b9acSAndroid Build Coastguard Worker 	}
381*1c60b9acSAndroid Build Coastguard Worker 
382*1c60b9acSAndroid Build Coastguard Worker 	ctx->ctx[side] = EVP_PKEY_CTX_new(pkey, NULL);
383*1c60b9acSAndroid Build Coastguard Worker 	if (!ctx->ctx[side]) {
384*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: EVP_PKEY_CTX_new failed\n", __func__);
385*1c60b9acSAndroid Build Coastguard Worker 		goto bail1;
386*1c60b9acSAndroid Build Coastguard Worker 	}
387*1c60b9acSAndroid Build Coastguard Worker 
388*1c60b9acSAndroid Build Coastguard Worker 	/*
389*1c60b9acSAndroid Build Coastguard Worker 	 * we need to capture the individual element BIGNUMs into
390*1c60b9acSAndroid Build Coastguard Worker 	 * lws_gencrypto_keyelem, so they can be serialized, used in jwk etc
391*1c60b9acSAndroid Build Coastguard Worker 	 */
392*1c60b9acSAndroid Build Coastguard Worker 
393*1c60b9acSAndroid Build Coastguard Worker 	pubkey = EC_KEY_get0_public_key(ec);
394*1c60b9acSAndroid Build Coastguard Worker 	if (!pubkey) {
395*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: EC_KEY_get0_public_key failed\n", __func__);
396*1c60b9acSAndroid Build Coastguard Worker 		goto bail1;
397*1c60b9acSAndroid Build Coastguard Worker 	}
398*1c60b9acSAndroid Build Coastguard Worker 
399*1c60b9acSAndroid Build Coastguard Worker 	bn[0] = BN_new();
400*1c60b9acSAndroid Build Coastguard Worker 	bn[1] = (BIGNUM *)EC_KEY_get0_private_key(ec);
401*1c60b9acSAndroid Build Coastguard Worker 	bn[2] = BN_new();
402*1c60b9acSAndroid Build Coastguard Worker 
403*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAVE_EC_POINT_get_affine_coordinates)
404*1c60b9acSAndroid Build Coastguard Worker 	if (EC_POINT_get_affine_coordinates(EC_KEY_get0_group(ec),
405*1c60b9acSAndroid Build Coastguard Worker #else
406*1c60b9acSAndroid Build Coastguard Worker 	if (EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec),
407*1c60b9acSAndroid Build Coastguard Worker #endif
408*1c60b9acSAndroid Build Coastguard Worker 		        pubkey, bn[0], bn[2], NULL) != 1) {
409*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: EC_POINT_get_affine_coordinates_GFp failed\n",
410*1c60b9acSAndroid Build Coastguard Worker 			 __func__);
411*1c60b9acSAndroid Build Coastguard Worker 		goto bail2;
412*1c60b9acSAndroid Build Coastguard Worker 	}
413*1c60b9acSAndroid Build Coastguard Worker 
414*1c60b9acSAndroid Build Coastguard Worker 	el[LWS_GENCRYPTO_EC_KEYEL_CRV].len = (uint32_t)strlen(curve_name) + 1;
415*1c60b9acSAndroid Build Coastguard Worker 	el[LWS_GENCRYPTO_EC_KEYEL_CRV].buf =
416*1c60b9acSAndroid Build Coastguard Worker 			lws_malloc(el[LWS_GENCRYPTO_EC_KEYEL_CRV].len, "ec");
417*1c60b9acSAndroid Build Coastguard Worker 	if (!el[LWS_GENCRYPTO_EC_KEYEL_CRV].buf) {
418*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: OOM\n", __func__);
419*1c60b9acSAndroid Build Coastguard Worker 		goto bail2;
420*1c60b9acSAndroid Build Coastguard Worker 	}
421*1c60b9acSAndroid Build Coastguard Worker 
422*1c60b9acSAndroid Build Coastguard Worker 	strcpy((char *)el[LWS_GENCRYPTO_EC_KEYEL_CRV].buf, curve_name);
423*1c60b9acSAndroid Build Coastguard Worker 
424*1c60b9acSAndroid Build Coastguard Worker 	for (n = LWS_GENCRYPTO_EC_KEYEL_X; n < LWS_GENCRYPTO_EC_KEYEL_COUNT;
425*1c60b9acSAndroid Build Coastguard Worker 	     n++) {
426*1c60b9acSAndroid Build Coastguard Worker 		el[n].len = curve->key_bytes;
427*1c60b9acSAndroid Build Coastguard Worker 		el[n].buf = lws_malloc(curve->key_bytes, "ec");
428*1c60b9acSAndroid Build Coastguard Worker 		if (!el[n].buf)
429*1c60b9acSAndroid Build Coastguard Worker 			goto bail2;
430*1c60b9acSAndroid Build Coastguard Worker 
431*1c60b9acSAndroid Build Coastguard Worker 		m = BN_bn2binpad(bn[n - 1], el[n].buf, (int32_t)el[n].len);
432*1c60b9acSAndroid Build Coastguard Worker 		if ((uint32_t)m != el[n].len)
433*1c60b9acSAndroid Build Coastguard Worker 			goto bail2;
434*1c60b9acSAndroid Build Coastguard Worker 	}
435*1c60b9acSAndroid Build Coastguard Worker 
436*1c60b9acSAndroid Build Coastguard Worker 	ctx->has_private = 1;
437*1c60b9acSAndroid Build Coastguard Worker 
438*1c60b9acSAndroid Build Coastguard Worker 	ret = 0;
439*1c60b9acSAndroid Build Coastguard Worker 
440*1c60b9acSAndroid Build Coastguard Worker bail2:
441*1c60b9acSAndroid Build Coastguard Worker 	BN_clear_free(bn[0]);
442*1c60b9acSAndroid Build Coastguard Worker 	BN_clear_free(bn[2]);
443*1c60b9acSAndroid Build Coastguard Worker bail1:
444*1c60b9acSAndroid Build Coastguard Worker 	EVP_PKEY_free(pkey);
445*1c60b9acSAndroid Build Coastguard Worker bail:
446*1c60b9acSAndroid Build Coastguard Worker 	EC_KEY_free(ec);
447*1c60b9acSAndroid Build Coastguard Worker 
448*1c60b9acSAndroid Build Coastguard Worker 	return ret;
449*1c60b9acSAndroid Build Coastguard Worker }
450*1c60b9acSAndroid Build Coastguard Worker 
451*1c60b9acSAndroid Build Coastguard Worker int
lws_genecdh_new_keypair(struct lws_genec_ctx * ctx,enum enum_lws_dh_side side,const char * curve_name,struct lws_gencrypto_keyelem * el)452*1c60b9acSAndroid Build Coastguard Worker lws_genecdh_new_keypair(struct lws_genec_ctx *ctx, enum enum_lws_dh_side side,
453*1c60b9acSAndroid Build Coastguard Worker 			const char *curve_name,
454*1c60b9acSAndroid Build Coastguard Worker 			struct lws_gencrypto_keyelem *el)
455*1c60b9acSAndroid Build Coastguard Worker {
456*1c60b9acSAndroid Build Coastguard Worker 	if (ctx->genec_alg != LEGENEC_ECDH)
457*1c60b9acSAndroid Build Coastguard Worker 		return -1;
458*1c60b9acSAndroid Build Coastguard Worker 
459*1c60b9acSAndroid Build Coastguard Worker 	return lws_genec_new_keypair(ctx, side, curve_name, el);
460*1c60b9acSAndroid Build Coastguard Worker }
461*1c60b9acSAndroid Build Coastguard Worker 
462*1c60b9acSAndroid Build Coastguard Worker int
lws_genecdsa_new_keypair(struct lws_genec_ctx * ctx,const char * curve_name,struct lws_gencrypto_keyelem * el)463*1c60b9acSAndroid Build Coastguard Worker lws_genecdsa_new_keypair(struct lws_genec_ctx *ctx, const char *curve_name,
464*1c60b9acSAndroid Build Coastguard Worker 			 struct lws_gencrypto_keyelem *el)
465*1c60b9acSAndroid Build Coastguard Worker {
466*1c60b9acSAndroid Build Coastguard Worker 	if (ctx->genec_alg != LEGENEC_ECDSA)
467*1c60b9acSAndroid Build Coastguard Worker 		return -1;
468*1c60b9acSAndroid Build Coastguard Worker 
469*1c60b9acSAndroid Build Coastguard Worker 	return lws_genec_new_keypair(ctx, LDHS_OURS, curve_name, el);
470*1c60b9acSAndroid Build Coastguard Worker }
471*1c60b9acSAndroid Build Coastguard Worker 
472*1c60b9acSAndroid Build Coastguard Worker #if 0
473*1c60b9acSAndroid Build Coastguard Worker int
474*1c60b9acSAndroid Build Coastguard Worker lws_genecdsa_hash_sign(struct lws_genec_ctx *ctx, const uint8_t *in,
475*1c60b9acSAndroid Build Coastguard Worker 		       enum lws_genhash_types hash_type,
476*1c60b9acSAndroid Build Coastguard Worker 		       uint8_t *sig, size_t sig_len)
477*1c60b9acSAndroid Build Coastguard Worker {
478*1c60b9acSAndroid Build Coastguard Worker 	const EVP_MD *md = lws_gencrypto_openssl_hash_to_EVP_MD(hash_type);
479*1c60b9acSAndroid Build Coastguard Worker 	EVP_MD_CTX *mdctx = NULL;
480*1c60b9acSAndroid Build Coastguard Worker 
481*1c60b9acSAndroid Build Coastguard Worker 	if (ctx->genec_alg != LEGENEC_ECDSA)
482*1c60b9acSAndroid Build Coastguard Worker 		return -1;
483*1c60b9acSAndroid Build Coastguard Worker 
484*1c60b9acSAndroid Build Coastguard Worker 	if (!md)
485*1c60b9acSAndroid Build Coastguard Worker 		return -1;
486*1c60b9acSAndroid Build Coastguard Worker 
487*1c60b9acSAndroid Build Coastguard Worker 	mdctx = EVP_MD_CTX_create();
488*1c60b9acSAndroid Build Coastguard Worker 	if (!mdctx)
489*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
490*1c60b9acSAndroid Build Coastguard Worker 
491*1c60b9acSAndroid Build Coastguard Worker 	if (EVP_DigestSignInit(mdctx, NULL, md, NULL,
492*1c60b9acSAndroid Build Coastguard Worker 			       EVP_PKEY_CTX_get0_pkey(ctx->ctx))) {
493*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: EVP_DigestSignInit failed\n", __func__);
494*1c60b9acSAndroid Build Coastguard Worker 
495*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
496*1c60b9acSAndroid Build Coastguard Worker 	}
497*1c60b9acSAndroid Build Coastguard Worker 	if (EVP_DigestSignUpdate(mdctx, in, EVP_MD_size(md))) {
498*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: EVP_DigestSignUpdate failed\n", __func__);
499*1c60b9acSAndroid Build Coastguard Worker 
500*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
501*1c60b9acSAndroid Build Coastguard Worker 	}
502*1c60b9acSAndroid Build Coastguard Worker 	if (EVP_DigestSignFinal(mdctx, sig, &sig_len)) {
503*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: EVP_DigestSignFinal failed\n", __func__);
504*1c60b9acSAndroid Build Coastguard Worker 
505*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
506*1c60b9acSAndroid Build Coastguard Worker 	}
507*1c60b9acSAndroid Build Coastguard Worker 
508*1c60b9acSAndroid Build Coastguard Worker 	EVP_MD_CTX_free(mdctx);
509*1c60b9acSAndroid Build Coastguard Worker 
510*1c60b9acSAndroid Build Coastguard Worker 	return (int)sig_len;
511*1c60b9acSAndroid Build Coastguard Worker bail:
512*1c60b9acSAndroid Build Coastguard Worker 	if (mdctx)
513*1c60b9acSAndroid Build Coastguard Worker 		EVP_MD_CTX_free(mdctx);
514*1c60b9acSAndroid Build Coastguard Worker 
515*1c60b9acSAndroid Build Coastguard Worker 	return -1;
516*1c60b9acSAndroid Build Coastguard Worker }
517*1c60b9acSAndroid Build Coastguard Worker #endif
518*1c60b9acSAndroid Build Coastguard Worker 
519*1c60b9acSAndroid Build Coastguard Worker int
lws_genecdsa_hash_sign_jws(struct lws_genec_ctx * ctx,const uint8_t * in,enum lws_genhash_types hash_type,int keybits,uint8_t * sig,size_t sig_len)520*1c60b9acSAndroid Build Coastguard Worker lws_genecdsa_hash_sign_jws(struct lws_genec_ctx *ctx, const uint8_t *in,
521*1c60b9acSAndroid Build Coastguard Worker 			   enum lws_genhash_types hash_type, int keybits,
522*1c60b9acSAndroid Build Coastguard Worker 			   uint8_t *sig, size_t sig_len)
523*1c60b9acSAndroid Build Coastguard Worker {
524*1c60b9acSAndroid Build Coastguard Worker 	int ret = -1, n, keybytes = lws_gencrypto_bits_to_bytes(keybits);
525*1c60b9acSAndroid Build Coastguard Worker 	size_t hs = lws_genhash_size(hash_type);
526*1c60b9acSAndroid Build Coastguard Worker 	const BIGNUM *r = NULL, *s = NULL;
527*1c60b9acSAndroid Build Coastguard Worker 	ECDSA_SIG *ecdsasig;
528*1c60b9acSAndroid Build Coastguard Worker 	EC_KEY *eckey;
529*1c60b9acSAndroid Build Coastguard Worker 
530*1c60b9acSAndroid Build Coastguard Worker 	if (ctx->genec_alg != LEGENEC_ECDSA) {
531*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: ctx alg %d\n", __func__, ctx->genec_alg);
532*1c60b9acSAndroid Build Coastguard Worker 		return -1;
533*1c60b9acSAndroid Build Coastguard Worker 	}
534*1c60b9acSAndroid Build Coastguard Worker 
535*1c60b9acSAndroid Build Coastguard Worker 	if (!ctx->has_private)
536*1c60b9acSAndroid Build Coastguard Worker 		return -1;
537*1c60b9acSAndroid Build Coastguard Worker 
538*1c60b9acSAndroid Build Coastguard Worker 	if ((int)sig_len != (int)(keybytes * 2)) {
539*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: sig buff %d < %d\n", __func__,
540*1c60b9acSAndroid Build Coastguard Worker 			    (int)sig_len, (int)(hs * 2));
541*1c60b9acSAndroid Build Coastguard Worker 		return -1;
542*1c60b9acSAndroid Build Coastguard Worker 	}
543*1c60b9acSAndroid Build Coastguard Worker 
544*1c60b9acSAndroid Build Coastguard Worker 	eckey = EVP_PKEY_get1_EC_KEY(EVP_PKEY_CTX_get0_pkey(ctx->ctx[0]));
545*1c60b9acSAndroid Build Coastguard Worker 
546*1c60b9acSAndroid Build Coastguard Worker 	/*
547*1c60b9acSAndroid Build Coastguard Worker 	 * The ECDSA P-256 SHA-256 digital signature is generated as follows:
548*1c60b9acSAndroid Build Coastguard Worker 	 *
549*1c60b9acSAndroid Build Coastguard Worker 	 * 1.  Generate a digital signature of the JWS Signing Input using ECDSA
550*1c60b9acSAndroid Build Coastguard Worker 	 *     P-256 SHA-256 with the desired private key.  The output will be
551*1c60b9acSAndroid Build Coastguard Worker 	 *     the pair (R, S), where R and S are 256-bit unsigned integers.
552*1c60b9acSAndroid Build Coastguard Worker 	 *
553*1c60b9acSAndroid Build Coastguard Worker 	 * 2.  Turn R and S into octet sequences in big-endian order, with each
554*1c60b9acSAndroid Build Coastguard Worker 	 *     array being be 32 octets long.  The octet sequence
555*1c60b9acSAndroid Build Coastguard Worker 	 *     representations MUST NOT be shortened to omit any leading zero
556*1c60b9acSAndroid Build Coastguard Worker 	 *     octets contained in the values.
557*1c60b9acSAndroid Build Coastguard Worker 	 *
558*1c60b9acSAndroid Build Coastguard Worker 	 * 3.  Concatenate the two octet sequences in the order R and then S.
559*1c60b9acSAndroid Build Coastguard Worker 	 *     (Note that many ECDSA implementations will directly produce this
560*1c60b9acSAndroid Build Coastguard Worker 	 *     concatenation as their output.)
561*1c60b9acSAndroid Build Coastguard Worker 	 *
562*1c60b9acSAndroid Build Coastguard Worker 	 * 4.  The resulting 64-octet sequence is the JWS Signature value.
563*1c60b9acSAndroid Build Coastguard Worker 	 */
564*1c60b9acSAndroid Build Coastguard Worker 
565*1c60b9acSAndroid Build Coastguard Worker 	ecdsasig = ECDSA_do_sign(in, (int)hs, eckey);
566*1c60b9acSAndroid Build Coastguard Worker 	EC_KEY_free(eckey);
567*1c60b9acSAndroid Build Coastguard Worker 	if (!ecdsasig) {
568*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: ECDSA_do_sign fail\n", __func__);
569*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
570*1c60b9acSAndroid Build Coastguard Worker 	}
571*1c60b9acSAndroid Build Coastguard Worker 
572*1c60b9acSAndroid Build Coastguard Worker 	ECDSA_SIG_get0(ecdsasig, &r, &s);
573*1c60b9acSAndroid Build Coastguard Worker 
574*1c60b9acSAndroid Build Coastguard Worker 	/*
575*1c60b9acSAndroid Build Coastguard Worker 	 * in the 521-bit case, we have to pad the last byte as it only
576*1c60b9acSAndroid Build Coastguard Worker 	 * generates 65 bytes
577*1c60b9acSAndroid Build Coastguard Worker 	 */
578*1c60b9acSAndroid Build Coastguard Worker 
579*1c60b9acSAndroid Build Coastguard Worker 	n = BN_bn2binpad(r, sig, keybytes);
580*1c60b9acSAndroid Build Coastguard Worker 	if (n != keybytes) {
581*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: bignum r fail %d %d\n", __func__, n, keybytes);
582*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
583*1c60b9acSAndroid Build Coastguard Worker 	}
584*1c60b9acSAndroid Build Coastguard Worker 
585*1c60b9acSAndroid Build Coastguard Worker 	n = BN_bn2binpad(s, sig + keybytes, keybytes);
586*1c60b9acSAndroid Build Coastguard Worker 	if (n != keybytes) {
587*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: bignum s fail %d %d\n", __func__, n, keybytes);
588*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
589*1c60b9acSAndroid Build Coastguard Worker 	}
590*1c60b9acSAndroid Build Coastguard Worker 
591*1c60b9acSAndroid Build Coastguard Worker 	ret = 0;
592*1c60b9acSAndroid Build Coastguard Worker 
593*1c60b9acSAndroid Build Coastguard Worker bail:
594*1c60b9acSAndroid Build Coastguard Worker 	if (ecdsasig)
595*1c60b9acSAndroid Build Coastguard Worker 		ECDSA_SIG_free(ecdsasig);
596*1c60b9acSAndroid Build Coastguard Worker 
597*1c60b9acSAndroid Build Coastguard Worker 	return ret;
598*1c60b9acSAndroid Build Coastguard Worker }
599*1c60b9acSAndroid Build Coastguard Worker 
600*1c60b9acSAndroid Build Coastguard Worker /* in is the JWS Signing Input hash */
601*1c60b9acSAndroid Build Coastguard Worker 
602*1c60b9acSAndroid Build Coastguard Worker int
lws_genecdsa_hash_sig_verify_jws(struct lws_genec_ctx * ctx,const uint8_t * in,enum lws_genhash_types hash_type,int keybits,const uint8_t * sig,size_t sig_len)603*1c60b9acSAndroid Build Coastguard Worker lws_genecdsa_hash_sig_verify_jws(struct lws_genec_ctx *ctx, const uint8_t *in,
604*1c60b9acSAndroid Build Coastguard Worker 				 enum lws_genhash_types hash_type, int keybits,
605*1c60b9acSAndroid Build Coastguard Worker 				 const uint8_t *sig, size_t sig_len)
606*1c60b9acSAndroid Build Coastguard Worker {
607*1c60b9acSAndroid Build Coastguard Worker 	int ret = -1, n, hlen = (int)lws_genhash_size(hash_type),
608*1c60b9acSAndroid Build Coastguard Worker 			keybytes = lws_gencrypto_bits_to_bytes(keybits);
609*1c60b9acSAndroid Build Coastguard Worker 	ECDSA_SIG *ecsig = ECDSA_SIG_new();
610*1c60b9acSAndroid Build Coastguard Worker 	BIGNUM *r = NULL, *s = NULL;
611*1c60b9acSAndroid Build Coastguard Worker 	EC_KEY *eckey;
612*1c60b9acSAndroid Build Coastguard Worker 
613*1c60b9acSAndroid Build Coastguard Worker 	if (!ecsig)
614*1c60b9acSAndroid Build Coastguard Worker 		return -1;
615*1c60b9acSAndroid Build Coastguard Worker 
616*1c60b9acSAndroid Build Coastguard Worker 	if (ctx->genec_alg != LEGENEC_ECDSA)
617*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
618*1c60b9acSAndroid Build Coastguard Worker 
619*1c60b9acSAndroid Build Coastguard Worker 	if ((int)sig_len != keybytes * 2) {
620*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: sig buf size %d vs %d\n", __func__,
621*1c60b9acSAndroid Build Coastguard Worker 			 (int)sig_len, keybytes * 2);
622*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
623*1c60b9acSAndroid Build Coastguard Worker 	}
624*1c60b9acSAndroid Build Coastguard Worker 	/*
625*1c60b9acSAndroid Build Coastguard Worker 	 * 1.  The JWS Signature value MUST be a 64-octet sequence.  If it is
626*1c60b9acSAndroid Build Coastguard Worker 	 *     not a 64-octet sequence, the validation has failed.
627*1c60b9acSAndroid Build Coastguard Worker 	 *
628*1c60b9acSAndroid Build Coastguard Worker 	 * 2.  Split the 64-octet sequence into two 32-octet sequences.  The
629*1c60b9acSAndroid Build Coastguard Worker 	 *     first octet sequence represents R and the second S.  The values R
630*1c60b9acSAndroid Build Coastguard Worker 	 *     and S are represented as octet sequences using the Integer-to-
631*1c60b9acSAndroid Build Coastguard Worker 	 *     OctetString Conversion defined in Section 2.3.7 of SEC1 [SEC1]
632*1c60b9acSAndroid Build Coastguard Worker 	 *     (in big-endian octet order).
633*1c60b9acSAndroid Build Coastguard Worker 	 *
634*1c60b9acSAndroid Build Coastguard Worker 	 * 3.  Submit the JWS Signing Input, R, S, and the public key (x, y) to
635*1c60b9acSAndroid Build Coastguard Worker 	 *     the ECDSA P-256 SHA-256 validator.
636*1c60b9acSAndroid Build Coastguard Worker 	 */
637*1c60b9acSAndroid Build Coastguard Worker 
638*1c60b9acSAndroid Build Coastguard Worker 	r = BN_bin2bn(sig, keybytes, NULL);
639*1c60b9acSAndroid Build Coastguard Worker 	if (!r) {
640*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: BN_bin2bn (r) fail\n", __func__);
641*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
642*1c60b9acSAndroid Build Coastguard Worker 	}
643*1c60b9acSAndroid Build Coastguard Worker 
644*1c60b9acSAndroid Build Coastguard Worker 	s = BN_bin2bn(sig + keybytes, keybytes, NULL);
645*1c60b9acSAndroid Build Coastguard Worker 	if (!s) {
646*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: BN_bin2bn (s) fail\n", __func__);
647*1c60b9acSAndroid Build Coastguard Worker 		goto bail1;
648*1c60b9acSAndroid Build Coastguard Worker 	}
649*1c60b9acSAndroid Build Coastguard Worker 
650*1c60b9acSAndroid Build Coastguard Worker 	if (ECDSA_SIG_set0(ecsig, r, s) != 1) {
651*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: ECDSA_SIG_set0 fail\n", __func__);
652*1c60b9acSAndroid Build Coastguard Worker 		goto bail1;
653*1c60b9acSAndroid Build Coastguard Worker 	}
654*1c60b9acSAndroid Build Coastguard Worker 
655*1c60b9acSAndroid Build Coastguard Worker 	eckey = EVP_PKEY_get1_EC_KEY(EVP_PKEY_CTX_get0_pkey(ctx->ctx[0]));
656*1c60b9acSAndroid Build Coastguard Worker 
657*1c60b9acSAndroid Build Coastguard Worker 	n = ECDSA_do_verify(in, hlen, ecsig, eckey);
658*1c60b9acSAndroid Build Coastguard Worker 	EC_KEY_free(eckey);
659*1c60b9acSAndroid Build Coastguard Worker 	if (n != 1) {
660*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: ECDSA_do_verify fail, hlen %d\n", __func__, (int)hlen);
661*1c60b9acSAndroid Build Coastguard Worker 		lws_tls_err_describe_clear();
662*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
663*1c60b9acSAndroid Build Coastguard Worker 	}
664*1c60b9acSAndroid Build Coastguard Worker 
665*1c60b9acSAndroid Build Coastguard Worker 	ret = 0;
666*1c60b9acSAndroid Build Coastguard Worker 	goto bail;
667*1c60b9acSAndroid Build Coastguard Worker 
668*1c60b9acSAndroid Build Coastguard Worker bail1:
669*1c60b9acSAndroid Build Coastguard Worker 	if (r)
670*1c60b9acSAndroid Build Coastguard Worker 		BN_free(r);
671*1c60b9acSAndroid Build Coastguard Worker 	if (s)
672*1c60b9acSAndroid Build Coastguard Worker 		BN_free(s);
673*1c60b9acSAndroid Build Coastguard Worker 
674*1c60b9acSAndroid Build Coastguard Worker bail:
675*1c60b9acSAndroid Build Coastguard Worker 	ECDSA_SIG_free(ecsig);
676*1c60b9acSAndroid Build Coastguard Worker 
677*1c60b9acSAndroid Build Coastguard Worker 	return ret;
678*1c60b9acSAndroid Build Coastguard Worker }
679*1c60b9acSAndroid Build Coastguard Worker 
680*1c60b9acSAndroid Build Coastguard Worker int
lws_genecdh_compute_shared_secret(struct lws_genec_ctx * ctx,uint8_t * ss,int * ss_len)681*1c60b9acSAndroid Build Coastguard Worker lws_genecdh_compute_shared_secret(struct lws_genec_ctx *ctx, uint8_t *ss,
682*1c60b9acSAndroid Build Coastguard Worker 				  int *ss_len)
683*1c60b9acSAndroid Build Coastguard Worker {
684*1c60b9acSAndroid Build Coastguard Worker 	int len, ret = -1;
685*1c60b9acSAndroid Build Coastguard Worker 	EC_KEY *eckey[2];
686*1c60b9acSAndroid Build Coastguard Worker 
687*1c60b9acSAndroid Build Coastguard Worker 	if (!ctx->ctx[LDHS_OURS] || !ctx->ctx[LDHS_THEIRS]) {
688*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: both sides must be set up\n", __func__);
689*1c60b9acSAndroid Build Coastguard Worker 
690*1c60b9acSAndroid Build Coastguard Worker 		return -1;
691*1c60b9acSAndroid Build Coastguard Worker 	}
692*1c60b9acSAndroid Build Coastguard Worker 
693*1c60b9acSAndroid Build Coastguard Worker 	eckey[LDHS_OURS] = EVP_PKEY_get1_EC_KEY(
694*1c60b9acSAndroid Build Coastguard Worker 				EVP_PKEY_CTX_get0_pkey(ctx->ctx[LDHS_OURS]));
695*1c60b9acSAndroid Build Coastguard Worker 	eckey[LDHS_THEIRS] = EVP_PKEY_get1_EC_KEY(
696*1c60b9acSAndroid Build Coastguard Worker 				EVP_PKEY_CTX_get0_pkey(ctx->ctx[LDHS_THEIRS]));
697*1c60b9acSAndroid Build Coastguard Worker 
698*1c60b9acSAndroid Build Coastguard Worker 	len = (EC_GROUP_get_degree(EC_KEY_get0_group(eckey[LDHS_OURS])) + 7) / 8;
699*1c60b9acSAndroid Build Coastguard Worker 	if (len <= *ss_len) {
700*1c60b9acSAndroid Build Coastguard Worker #if defined(USE_WOLFSSL)
701*1c60b9acSAndroid Build Coastguard Worker 		*ss_len = wolfSSL_ECDH_compute_key(
702*1c60b9acSAndroid Build Coastguard Worker #else
703*1c60b9acSAndroid Build Coastguard Worker 		*ss_len = ECDH_compute_key(
704*1c60b9acSAndroid Build Coastguard Worker #endif
705*1c60b9acSAndroid Build Coastguard Worker 				ss, (unsigned int)len,
706*1c60b9acSAndroid Build Coastguard Worker 				EC_KEY_get0_public_key(eckey[LDHS_THEIRS]),
707*1c60b9acSAndroid Build Coastguard Worker 				eckey[LDHS_OURS], NULL);
708*1c60b9acSAndroid Build Coastguard Worker 		ret = -(*ss_len < 0);
709*1c60b9acSAndroid Build Coastguard Worker 	}
710*1c60b9acSAndroid Build Coastguard Worker 
711*1c60b9acSAndroid Build Coastguard Worker 	EC_KEY_free(eckey[LDHS_OURS]);
712*1c60b9acSAndroid Build Coastguard Worker 	EC_KEY_free(eckey[LDHS_THEIRS]);
713*1c60b9acSAndroid Build Coastguard Worker 
714*1c60b9acSAndroid Build Coastguard Worker 	return ret;
715*1c60b9acSAndroid Build Coastguard Worker }
716