xref: /aosp_15_r20/external/libwebsockets/lib/tls/openssl/lws-genrsa.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_genrsa provides an RSA 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 /*
31*1c60b9acSAndroid Build Coastguard Worker  * Care: many openssl apis return 1 for success.  These are translated to the
32*1c60b9acSAndroid Build Coastguard Worker  * lws convention of 0 for success.
33*1c60b9acSAndroid Build Coastguard Worker  */
34*1c60b9acSAndroid Build Coastguard Worker 
35*1c60b9acSAndroid Build Coastguard Worker void
lws_genrsa_destroy_elements(struct lws_gencrypto_keyelem * el)36*1c60b9acSAndroid Build Coastguard Worker lws_genrsa_destroy_elements(struct lws_gencrypto_keyelem *el)
37*1c60b9acSAndroid Build Coastguard Worker {
38*1c60b9acSAndroid Build Coastguard Worker 	lws_gencrypto_destroy_elements(el, LWS_GENCRYPTO_RSA_KEYEL_COUNT);
39*1c60b9acSAndroid Build Coastguard Worker }
40*1c60b9acSAndroid Build Coastguard Worker 
41*1c60b9acSAndroid Build Coastguard Worker static int mode_map_crypt[] = { RSA_PKCS1_PADDING, RSA_PKCS1_OAEP_PADDING },
42*1c60b9acSAndroid Build Coastguard Worker 	   mode_map_sig[]   = { RSA_PKCS1_PADDING, RSA_PKCS1_PSS_PADDING };
43*1c60b9acSAndroid Build Coastguard Worker 
44*1c60b9acSAndroid Build Coastguard Worker static int
rsa_pkey_wrap(struct lws_genrsa_ctx * ctx,RSA * rsa)45*1c60b9acSAndroid Build Coastguard Worker rsa_pkey_wrap(struct lws_genrsa_ctx *ctx, RSA *rsa)
46*1c60b9acSAndroid Build Coastguard Worker {
47*1c60b9acSAndroid Build Coastguard Worker 	EVP_PKEY *pkey;
48*1c60b9acSAndroid Build Coastguard Worker 
49*1c60b9acSAndroid Build Coastguard Worker 	/* we have the RSA object filled up... wrap in a PKEY */
50*1c60b9acSAndroid Build Coastguard Worker 
51*1c60b9acSAndroid Build Coastguard Worker 	pkey = EVP_PKEY_new();
52*1c60b9acSAndroid Build Coastguard Worker 	if (!pkey)
53*1c60b9acSAndroid Build Coastguard Worker 		return 1;
54*1c60b9acSAndroid Build Coastguard Worker 
55*1c60b9acSAndroid Build Coastguard Worker 	/* bind the PKEY to the RSA key we just prepared */
56*1c60b9acSAndroid Build Coastguard Worker 
57*1c60b9acSAndroid Build Coastguard Worker 	if (EVP_PKEY_assign_RSA(pkey, rsa) != 1) {
58*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: EVP_PKEY_assign_RSA_KEY failed\n", __func__);
59*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
60*1c60b9acSAndroid Build Coastguard Worker 	}
61*1c60b9acSAndroid Build Coastguard Worker 
62*1c60b9acSAndroid Build Coastguard Worker 	/* pepare our PKEY_CTX with the PKEY */
63*1c60b9acSAndroid Build Coastguard Worker 
64*1c60b9acSAndroid Build Coastguard Worker 	ctx->ctx = EVP_PKEY_CTX_new(pkey, NULL);
65*1c60b9acSAndroid Build Coastguard Worker 	EVP_PKEY_free(pkey);
66*1c60b9acSAndroid Build Coastguard Worker 	pkey = NULL;
67*1c60b9acSAndroid Build Coastguard Worker 	if (!ctx->ctx)
68*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
69*1c60b9acSAndroid Build Coastguard Worker 
70*1c60b9acSAndroid Build Coastguard Worker 	return 0;
71*1c60b9acSAndroid Build Coastguard Worker 
72*1c60b9acSAndroid Build Coastguard Worker bail:
73*1c60b9acSAndroid Build Coastguard Worker 	if (pkey)
74*1c60b9acSAndroid Build Coastguard Worker 		EVP_PKEY_free(pkey);
75*1c60b9acSAndroid Build Coastguard Worker 
76*1c60b9acSAndroid Build Coastguard Worker 	return 1;
77*1c60b9acSAndroid Build Coastguard Worker }
78*1c60b9acSAndroid Build Coastguard Worker 
79*1c60b9acSAndroid Build Coastguard Worker int
lws_genrsa_create(struct lws_genrsa_ctx * ctx,const struct lws_gencrypto_keyelem * el,struct lws_context * context,enum enum_genrsa_mode mode,enum lws_genhash_types oaep_hashid)80*1c60b9acSAndroid Build Coastguard Worker lws_genrsa_create(struct lws_genrsa_ctx *ctx,
81*1c60b9acSAndroid Build Coastguard Worker 		  const struct lws_gencrypto_keyelem *el,
82*1c60b9acSAndroid Build Coastguard Worker 		  struct lws_context *context, enum enum_genrsa_mode mode,
83*1c60b9acSAndroid Build Coastguard Worker 		  enum lws_genhash_types oaep_hashid)
84*1c60b9acSAndroid Build Coastguard Worker {
85*1c60b9acSAndroid Build Coastguard Worker 	int n;
86*1c60b9acSAndroid Build Coastguard Worker 
87*1c60b9acSAndroid Build Coastguard Worker 	memset(ctx, 0, sizeof(*ctx));
88*1c60b9acSAndroid Build Coastguard Worker 	ctx->context = context;
89*1c60b9acSAndroid Build Coastguard Worker 	ctx->mode = mode;
90*1c60b9acSAndroid Build Coastguard Worker 
91*1c60b9acSAndroid Build Coastguard Worker 	/* Step 1:
92*1c60b9acSAndroid Build Coastguard Worker 	 *
93*1c60b9acSAndroid Build Coastguard Worker 	 * convert the MPI for e and n to OpenSSL BIGNUMs
94*1c60b9acSAndroid Build Coastguard Worker 	 */
95*1c60b9acSAndroid Build Coastguard Worker 
96*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < 5; n++) {
97*1c60b9acSAndroid Build Coastguard Worker 		ctx->bn[n] = BN_bin2bn(el[n].buf, (int)el[n].len, NULL);
98*1c60b9acSAndroid Build Coastguard Worker 		if (!ctx->bn[n]) {
99*1c60b9acSAndroid Build Coastguard Worker 			lwsl_notice("mpi load failed\n");
100*1c60b9acSAndroid Build Coastguard Worker 			goto bail;
101*1c60b9acSAndroid Build Coastguard Worker 		}
102*1c60b9acSAndroid Build Coastguard Worker 	}
103*1c60b9acSAndroid Build Coastguard Worker 
104*1c60b9acSAndroid Build Coastguard Worker 	/* Step 2:
105*1c60b9acSAndroid Build Coastguard Worker 	 *
106*1c60b9acSAndroid Build Coastguard Worker 	 * assemble the OpenSSL RSA from the BIGNUMs
107*1c60b9acSAndroid Build Coastguard Worker 	 */
108*1c60b9acSAndroid Build Coastguard Worker 
109*1c60b9acSAndroid Build Coastguard Worker 	ctx->rsa = RSA_new();
110*1c60b9acSAndroid Build Coastguard Worker 	if (!ctx->rsa) {
111*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("Failed to create RSA\n");
112*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
113*1c60b9acSAndroid Build Coastguard Worker 	}
114*1c60b9acSAndroid Build Coastguard Worker 
115*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAVE_RSA_SET0_KEY) && !defined(USE_WOLFSSL)
116*1c60b9acSAndroid Build Coastguard Worker 	if (RSA_set0_key(ctx->rsa, ctx->bn[LWS_GENCRYPTO_RSA_KEYEL_N],
117*1c60b9acSAndroid Build Coastguard Worker 			 ctx->bn[LWS_GENCRYPTO_RSA_KEYEL_E],
118*1c60b9acSAndroid Build Coastguard Worker 			 ctx->bn[LWS_GENCRYPTO_RSA_KEYEL_D]) != 1) {
119*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("RSA_set0_key failed\n");
120*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
121*1c60b9acSAndroid Build Coastguard Worker 	}
122*1c60b9acSAndroid Build Coastguard Worker 	RSA_set0_factors(ctx->rsa, ctx->bn[LWS_GENCRYPTO_RSA_KEYEL_P],
123*1c60b9acSAndroid Build Coastguard Worker 				   ctx->bn[LWS_GENCRYPTO_RSA_KEYEL_Q]);
124*1c60b9acSAndroid Build Coastguard Worker #else
125*1c60b9acSAndroid Build Coastguard Worker 	ctx->rsa->e = ctx->bn[LWS_GENCRYPTO_RSA_KEYEL_E];
126*1c60b9acSAndroid Build Coastguard Worker 	ctx->rsa->n = ctx->bn[LWS_GENCRYPTO_RSA_KEYEL_N];
127*1c60b9acSAndroid Build Coastguard Worker 	ctx->rsa->d = ctx->bn[LWS_GENCRYPTO_RSA_KEYEL_D];
128*1c60b9acSAndroid Build Coastguard Worker 	ctx->rsa->p = ctx->bn[LWS_GENCRYPTO_RSA_KEYEL_P];
129*1c60b9acSAndroid Build Coastguard Worker 	ctx->rsa->q = ctx->bn[LWS_GENCRYPTO_RSA_KEYEL_Q];
130*1c60b9acSAndroid Build Coastguard Worker #endif
131*1c60b9acSAndroid Build Coastguard Worker 
132*1c60b9acSAndroid Build Coastguard Worker 	if (!rsa_pkey_wrap(ctx, ctx->rsa))
133*1c60b9acSAndroid Build Coastguard Worker 		return 0;
134*1c60b9acSAndroid Build Coastguard Worker 
135*1c60b9acSAndroid Build Coastguard Worker bail:
136*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < 5; n++)
137*1c60b9acSAndroid Build Coastguard Worker 		if (ctx->bn[n]) {
138*1c60b9acSAndroid Build Coastguard Worker 			BN_clear_free(ctx->bn[n]);
139*1c60b9acSAndroid Build Coastguard Worker 			ctx->bn[n] = NULL;
140*1c60b9acSAndroid Build Coastguard Worker 		}
141*1c60b9acSAndroid Build Coastguard Worker 
142*1c60b9acSAndroid Build Coastguard Worker 	if (ctx->rsa) {
143*1c60b9acSAndroid Build Coastguard Worker 		RSA_free(ctx->rsa);
144*1c60b9acSAndroid Build Coastguard Worker 		ctx->rsa = NULL;
145*1c60b9acSAndroid Build Coastguard Worker 	}
146*1c60b9acSAndroid Build Coastguard Worker 
147*1c60b9acSAndroid Build Coastguard Worker 	return 1;
148*1c60b9acSAndroid Build Coastguard Worker }
149*1c60b9acSAndroid Build Coastguard Worker 
150*1c60b9acSAndroid Build Coastguard Worker int
lws_genrsa_new_keypair(struct lws_context * context,struct lws_genrsa_ctx * ctx,enum enum_genrsa_mode mode,struct lws_gencrypto_keyelem * el,int bits)151*1c60b9acSAndroid Build Coastguard Worker lws_genrsa_new_keypair(struct lws_context *context, struct lws_genrsa_ctx *ctx,
152*1c60b9acSAndroid Build Coastguard Worker 		       enum enum_genrsa_mode mode, struct lws_gencrypto_keyelem *el,
153*1c60b9acSAndroid Build Coastguard Worker 		       int bits)
154*1c60b9acSAndroid Build Coastguard Worker {
155*1c60b9acSAndroid Build Coastguard Worker 	BIGNUM *bn;
156*1c60b9acSAndroid Build Coastguard Worker 	int n;
157*1c60b9acSAndroid Build Coastguard Worker 
158*1c60b9acSAndroid Build Coastguard Worker 	memset(ctx, 0, sizeof(*ctx));
159*1c60b9acSAndroid Build Coastguard Worker 	ctx->context = context;
160*1c60b9acSAndroid Build Coastguard Worker 	ctx->mode = mode;
161*1c60b9acSAndroid Build Coastguard Worker 
162*1c60b9acSAndroid Build Coastguard Worker 	ctx->rsa = RSA_new();
163*1c60b9acSAndroid Build Coastguard Worker 	if (!ctx->rsa) {
164*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("Failed to create RSA\n");
165*1c60b9acSAndroid Build Coastguard Worker 		return -1;
166*1c60b9acSAndroid Build Coastguard Worker 	}
167*1c60b9acSAndroid Build Coastguard Worker 
168*1c60b9acSAndroid Build Coastguard Worker 	bn = BN_new();
169*1c60b9acSAndroid Build Coastguard Worker 	if (!bn)
170*1c60b9acSAndroid Build Coastguard Worker 		goto cleanup_1;
171*1c60b9acSAndroid Build Coastguard Worker 	if (BN_set_word(bn, RSA_F4) != 1) {
172*1c60b9acSAndroid Build Coastguard Worker 		BN_free(bn);
173*1c60b9acSAndroid Build Coastguard Worker 		goto cleanup_1;
174*1c60b9acSAndroid Build Coastguard Worker 	}
175*1c60b9acSAndroid Build Coastguard Worker 
176*1c60b9acSAndroid Build Coastguard Worker 	n = RSA_generate_key_ex(ctx->rsa, bits, bn, NULL);
177*1c60b9acSAndroid Build Coastguard Worker 	BN_clear_free(bn);
178*1c60b9acSAndroid Build Coastguard Worker 	if (n != 1)
179*1c60b9acSAndroid Build Coastguard Worker 		goto cleanup_1;
180*1c60b9acSAndroid Build Coastguard Worker 
181*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAVE_RSA_SET0_KEY) && !defined(USE_WOLFSSL)
182*1c60b9acSAndroid Build Coastguard Worker 	{
183*1c60b9acSAndroid Build Coastguard Worker 		const BIGNUM *mpi[5];
184*1c60b9acSAndroid Build Coastguard Worker 
185*1c60b9acSAndroid Build Coastguard Worker 		RSA_get0_key(ctx->rsa, &mpi[LWS_GENCRYPTO_RSA_KEYEL_N],
186*1c60b9acSAndroid Build Coastguard Worker 			     &mpi[LWS_GENCRYPTO_RSA_KEYEL_E], &mpi[LWS_GENCRYPTO_RSA_KEYEL_D]);
187*1c60b9acSAndroid Build Coastguard Worker 		RSA_get0_factors(ctx->rsa, &mpi[LWS_GENCRYPTO_RSA_KEYEL_P],
188*1c60b9acSAndroid Build Coastguard Worker 				 &mpi[LWS_GENCRYPTO_RSA_KEYEL_Q]);
189*1c60b9acSAndroid Build Coastguard Worker #else
190*1c60b9acSAndroid Build Coastguard Worker 	{
191*1c60b9acSAndroid Build Coastguard Worker 		BIGNUM *mpi[5] = { ctx->rsa->e, ctx->rsa->n, ctx->rsa->d,
192*1c60b9acSAndroid Build Coastguard Worker 				   ctx->rsa->p, ctx->rsa->q, };
193*1c60b9acSAndroid Build Coastguard Worker #endif
194*1c60b9acSAndroid Build Coastguard Worker 		for (n = 0; n < 5; n++)
195*1c60b9acSAndroid Build Coastguard Worker 			if (BN_num_bytes(mpi[n])) {
196*1c60b9acSAndroid Build Coastguard Worker 				el[n].buf = lws_malloc(
197*1c60b9acSAndroid Build Coastguard Worker 					(unsigned int)BN_num_bytes(mpi[n]), "genrsakey");
198*1c60b9acSAndroid Build Coastguard Worker 				if (!el[n].buf)
199*1c60b9acSAndroid Build Coastguard Worker 					goto cleanup;
200*1c60b9acSAndroid Build Coastguard Worker 				el[n].len = (unsigned int)BN_num_bytes(mpi[n]);
201*1c60b9acSAndroid Build Coastguard Worker 				BN_bn2bin(mpi[n], el[n].buf);
202*1c60b9acSAndroid Build Coastguard Worker 			}
203*1c60b9acSAndroid Build Coastguard Worker 	}
204*1c60b9acSAndroid Build Coastguard Worker 
205*1c60b9acSAndroid Build Coastguard Worker 	if (!rsa_pkey_wrap(ctx, ctx->rsa))
206*1c60b9acSAndroid Build Coastguard Worker 		return 0;
207*1c60b9acSAndroid Build Coastguard Worker 
208*1c60b9acSAndroid Build Coastguard Worker cleanup:
209*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < LWS_GENCRYPTO_RSA_KEYEL_COUNT; n++)
210*1c60b9acSAndroid Build Coastguard Worker 		if (el[n].buf)
211*1c60b9acSAndroid Build Coastguard Worker 			lws_free_set_NULL(el[n].buf);
212*1c60b9acSAndroid Build Coastguard Worker cleanup_1:
213*1c60b9acSAndroid Build Coastguard Worker 	RSA_free(ctx->rsa);
214*1c60b9acSAndroid Build Coastguard Worker 	ctx->rsa = NULL;
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 /*
220*1c60b9acSAndroid Build Coastguard Worker  * in_len must be less than RSA_size(rsa) - 11 for the PKCS #1 v1.5
221*1c60b9acSAndroid Build Coastguard Worker  * based padding modes
222*1c60b9acSAndroid Build Coastguard Worker  */
223*1c60b9acSAndroid Build Coastguard Worker 
224*1c60b9acSAndroid Build Coastguard Worker int
225*1c60b9acSAndroid Build Coastguard Worker lws_genrsa_public_encrypt(struct lws_genrsa_ctx *ctx, const uint8_t *in,
226*1c60b9acSAndroid Build Coastguard Worker 			  size_t in_len, uint8_t *out)
227*1c60b9acSAndroid Build Coastguard Worker {
228*1c60b9acSAndroid Build Coastguard Worker 	int n = RSA_public_encrypt((int)in_len, in, out, ctx->rsa,
229*1c60b9acSAndroid Build Coastguard Worker 				   mode_map_crypt[ctx->mode]);
230*1c60b9acSAndroid Build Coastguard Worker 	if (n < 0) {
231*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: RSA_public_encrypt failed\n", __func__);
232*1c60b9acSAndroid Build Coastguard Worker 		lws_tls_err_describe_clear();
233*1c60b9acSAndroid Build Coastguard Worker 		return -1;
234*1c60b9acSAndroid Build Coastguard Worker 	}
235*1c60b9acSAndroid Build Coastguard Worker 
236*1c60b9acSAndroid Build Coastguard Worker 	return n;
237*1c60b9acSAndroid Build Coastguard Worker }
238*1c60b9acSAndroid Build Coastguard Worker 
239*1c60b9acSAndroid Build Coastguard Worker int
240*1c60b9acSAndroid Build Coastguard Worker lws_genrsa_private_encrypt(struct lws_genrsa_ctx *ctx, const uint8_t *in,
241*1c60b9acSAndroid Build Coastguard Worker 			   size_t in_len, uint8_t *out)
242*1c60b9acSAndroid Build Coastguard Worker {
243*1c60b9acSAndroid Build Coastguard Worker 	int n = RSA_private_encrypt((int)in_len, in, out, ctx->rsa,
244*1c60b9acSAndroid Build Coastguard Worker 			        mode_map_crypt[ctx->mode]);
245*1c60b9acSAndroid Build Coastguard Worker 	if (n < 0) {
246*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: RSA_private_encrypt failed\n", __func__);
247*1c60b9acSAndroid Build Coastguard Worker 		lws_tls_err_describe_clear();
248*1c60b9acSAndroid Build Coastguard Worker 		return -1;
249*1c60b9acSAndroid Build Coastguard Worker 	}
250*1c60b9acSAndroid Build Coastguard Worker 
251*1c60b9acSAndroid Build Coastguard Worker 	return n;
252*1c60b9acSAndroid Build Coastguard Worker }
253*1c60b9acSAndroid Build Coastguard Worker 
254*1c60b9acSAndroid Build Coastguard Worker int
255*1c60b9acSAndroid Build Coastguard Worker lws_genrsa_public_decrypt(struct lws_genrsa_ctx *ctx, const uint8_t *in,
256*1c60b9acSAndroid Build Coastguard Worker 			  size_t in_len, uint8_t *out, size_t out_max)
257*1c60b9acSAndroid Build Coastguard Worker {
258*1c60b9acSAndroid Build Coastguard Worker 	int n = RSA_public_decrypt((int)in_len, in, out, ctx->rsa,
259*1c60b9acSAndroid Build Coastguard Worker 			       mode_map_crypt[ctx->mode]);
260*1c60b9acSAndroid Build Coastguard Worker 	if (n < 0) {
261*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: RSA_public_decrypt failed\n", __func__);
262*1c60b9acSAndroid Build Coastguard Worker 		return -1;
263*1c60b9acSAndroid Build Coastguard Worker 	}
264*1c60b9acSAndroid Build Coastguard Worker 
265*1c60b9acSAndroid Build Coastguard Worker 	return n;
266*1c60b9acSAndroid Build Coastguard Worker }
267*1c60b9acSAndroid Build Coastguard Worker 
268*1c60b9acSAndroid Build Coastguard Worker int
269*1c60b9acSAndroid Build Coastguard Worker lws_genrsa_private_decrypt(struct lws_genrsa_ctx *ctx, const uint8_t *in,
270*1c60b9acSAndroid Build Coastguard Worker 			   size_t in_len, uint8_t *out, size_t out_max)
271*1c60b9acSAndroid Build Coastguard Worker {
272*1c60b9acSAndroid Build Coastguard Worker 	int n = RSA_private_decrypt((int)in_len, in, out, ctx->rsa,
273*1c60b9acSAndroid Build Coastguard Worker 			        mode_map_crypt[ctx->mode]);
274*1c60b9acSAndroid Build Coastguard Worker 	if (n < 0) {
275*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: RSA_private_decrypt failed\n", __func__);
276*1c60b9acSAndroid Build Coastguard Worker 		lws_tls_err_describe_clear();
277*1c60b9acSAndroid Build Coastguard Worker 		return -1;
278*1c60b9acSAndroid Build Coastguard Worker 	}
279*1c60b9acSAndroid Build Coastguard Worker 
280*1c60b9acSAndroid Build Coastguard Worker 	return n;
281*1c60b9acSAndroid Build Coastguard Worker }
282*1c60b9acSAndroid Build Coastguard Worker 
283*1c60b9acSAndroid Build Coastguard Worker int
284*1c60b9acSAndroid Build Coastguard Worker lws_genrsa_hash_sig_verify(struct lws_genrsa_ctx *ctx, const uint8_t *in,
285*1c60b9acSAndroid Build Coastguard Worker 			 enum lws_genhash_types hash_type, const uint8_t *sig,
286*1c60b9acSAndroid Build Coastguard Worker 			 size_t sig_len)
287*1c60b9acSAndroid Build Coastguard Worker {
288*1c60b9acSAndroid Build Coastguard Worker 	int n = lws_gencrypto_openssl_hash_to_NID(hash_type),
289*1c60b9acSAndroid Build Coastguard Worker 	    h = (int)lws_genhash_size(hash_type);
290*1c60b9acSAndroid Build Coastguard Worker 	const EVP_MD *md = NULL;
291*1c60b9acSAndroid Build Coastguard Worker 
292*1c60b9acSAndroid Build Coastguard Worker 	if (n < 0)
293*1c60b9acSAndroid Build Coastguard Worker 		return -1;
294*1c60b9acSAndroid Build Coastguard Worker 
295*1c60b9acSAndroid Build Coastguard Worker 	switch(ctx->mode) {
296*1c60b9acSAndroid Build Coastguard Worker 	case LGRSAM_PKCS1_1_5:
297*1c60b9acSAndroid Build Coastguard Worker 		n = RSA_verify(n, in, (unsigned int)h, (uint8_t *)sig,
298*1c60b9acSAndroid Build Coastguard Worker 			       (unsigned int)sig_len, ctx->rsa);
299*1c60b9acSAndroid Build Coastguard Worker 		break;
300*1c60b9acSAndroid Build Coastguard Worker 	case LGRSAM_PKCS1_OAEP_PSS:
301*1c60b9acSAndroid Build Coastguard Worker 		md = lws_gencrypto_openssl_hash_to_EVP_MD(hash_type);
302*1c60b9acSAndroid Build Coastguard Worker 		if (!md)
303*1c60b9acSAndroid Build Coastguard Worker 			return -1;
304*1c60b9acSAndroid Build Coastguard Worker 
305*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAVE_RSA_verify_pss_mgf1)
306*1c60b9acSAndroid Build Coastguard Worker 		n = RSA_verify_pss_mgf1(ctx->rsa, in, h, md, NULL, -1,
307*1c60b9acSAndroid Build Coastguard Worker 					(uint8_t *)sig,
308*1c60b9acSAndroid Build Coastguard Worker #else
309*1c60b9acSAndroid Build Coastguard Worker 		n = RSA_verify_PKCS1_PSS(ctx->rsa, in, md, (uint8_t *)sig,
310*1c60b9acSAndroid Build Coastguard Worker #endif
311*1c60b9acSAndroid Build Coastguard Worker 					 (int)sig_len);
312*1c60b9acSAndroid Build Coastguard Worker 		break;
313*1c60b9acSAndroid Build Coastguard Worker 	default:
314*1c60b9acSAndroid Build Coastguard Worker 		return -1;
315*1c60b9acSAndroid Build Coastguard Worker 	}
316*1c60b9acSAndroid Build Coastguard Worker 
317*1c60b9acSAndroid Build Coastguard Worker 	if (n != 1) {
318*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: fail\n", __func__);
319*1c60b9acSAndroid Build Coastguard Worker 		lws_tls_err_describe_clear();
320*1c60b9acSAndroid Build Coastguard Worker 
321*1c60b9acSAndroid Build Coastguard Worker 		return -1;
322*1c60b9acSAndroid Build Coastguard Worker 	}
323*1c60b9acSAndroid Build Coastguard Worker 
324*1c60b9acSAndroid Build Coastguard Worker 	return 0;
325*1c60b9acSAndroid Build Coastguard Worker }
326*1c60b9acSAndroid Build Coastguard Worker 
327*1c60b9acSAndroid Build Coastguard Worker int
328*1c60b9acSAndroid Build Coastguard Worker lws_genrsa_hash_sign(struct lws_genrsa_ctx *ctx, const uint8_t *in,
329*1c60b9acSAndroid Build Coastguard Worker 		       enum lws_genhash_types hash_type, uint8_t *sig,
330*1c60b9acSAndroid Build Coastguard Worker 		       size_t sig_len)
331*1c60b9acSAndroid Build Coastguard Worker {
332*1c60b9acSAndroid Build Coastguard Worker 	int n = lws_gencrypto_openssl_hash_to_NID(hash_type),
333*1c60b9acSAndroid Build Coastguard Worker 	    h = (int)lws_genhash_size(hash_type);
334*1c60b9acSAndroid Build Coastguard Worker 	unsigned int used = 0;
335*1c60b9acSAndroid Build Coastguard Worker 	EVP_MD_CTX *mdctx = NULL;
336*1c60b9acSAndroid Build Coastguard Worker 	const EVP_MD *md = NULL;
337*1c60b9acSAndroid Build Coastguard Worker 
338*1c60b9acSAndroid Build Coastguard Worker 	if (n < 0)
339*1c60b9acSAndroid Build Coastguard Worker 		return -1;
340*1c60b9acSAndroid Build Coastguard Worker 
341*1c60b9acSAndroid Build Coastguard Worker 	switch(ctx->mode) {
342*1c60b9acSAndroid Build Coastguard Worker 	case LGRSAM_PKCS1_1_5:
343*1c60b9acSAndroid Build Coastguard Worker 		if (RSA_sign(n, in, (unsigned int)h, sig, &used, ctx->rsa) != 1) {
344*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: RSA_sign failed\n", __func__);
345*1c60b9acSAndroid Build Coastguard Worker 
346*1c60b9acSAndroid Build Coastguard Worker 			goto bail;
347*1c60b9acSAndroid Build Coastguard Worker 		}
348*1c60b9acSAndroid Build Coastguard Worker 		break;
349*1c60b9acSAndroid Build Coastguard Worker 
350*1c60b9acSAndroid Build Coastguard Worker 	case LGRSAM_PKCS1_OAEP_PSS:
351*1c60b9acSAndroid Build Coastguard Worker 
352*1c60b9acSAndroid Build Coastguard Worker 		md = lws_gencrypto_openssl_hash_to_EVP_MD(hash_type);
353*1c60b9acSAndroid Build Coastguard Worker 		if (!md)
354*1c60b9acSAndroid Build Coastguard Worker 			return -1;
355*1c60b9acSAndroid Build Coastguard Worker 
356*1c60b9acSAndroid Build Coastguard Worker 		if (EVP_PKEY_CTX_set_rsa_padding(ctx->ctx,
357*1c60b9acSAndroid Build Coastguard Worker 						 mode_map_sig[ctx->mode]) != 1) {
358*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: set_rsa_padding failed\n", __func__);
359*1c60b9acSAndroid Build Coastguard Worker 
360*1c60b9acSAndroid Build Coastguard Worker 			goto bail;
361*1c60b9acSAndroid Build Coastguard Worker 		}
362*1c60b9acSAndroid Build Coastguard Worker 
363*1c60b9acSAndroid Build Coastguard Worker 		mdctx = EVP_MD_CTX_create();
364*1c60b9acSAndroid Build Coastguard Worker 		if (!mdctx)
365*1c60b9acSAndroid Build Coastguard Worker 			goto bail;
366*1c60b9acSAndroid Build Coastguard Worker 
367*1c60b9acSAndroid Build Coastguard Worker 		if (EVP_DigestSignInit(mdctx, NULL, md, NULL,
368*1c60b9acSAndroid Build Coastguard Worker #if defined(USE_WOLFSSL)
369*1c60b9acSAndroid Build Coastguard Worker 					ctx->ctx->pkey)) {
370*1c60b9acSAndroid Build Coastguard Worker #else
371*1c60b9acSAndroid Build Coastguard Worker 				       EVP_PKEY_CTX_get0_pkey(ctx->ctx))) {
372*1c60b9acSAndroid Build Coastguard Worker #endif
373*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: EVP_DigestSignInit failed\n", __func__);
374*1c60b9acSAndroid Build Coastguard Worker 
375*1c60b9acSAndroid Build Coastguard Worker 			goto bail;
376*1c60b9acSAndroid Build Coastguard Worker 		}
377*1c60b9acSAndroid Build Coastguard Worker 		if (EVP_DigestSignUpdate(mdctx, in, (unsigned int)EVP_MD_size(md))) {
378*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: EVP_DigestSignUpdate failed\n", __func__);
379*1c60b9acSAndroid Build Coastguard Worker 
380*1c60b9acSAndroid Build Coastguard Worker 			goto bail;
381*1c60b9acSAndroid Build Coastguard Worker 		}
382*1c60b9acSAndroid Build Coastguard Worker 		if (EVP_DigestSignFinal(mdctx, sig, &sig_len)) {
383*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: EVP_DigestSignFinal failed\n", __func__);
384*1c60b9acSAndroid Build Coastguard Worker 
385*1c60b9acSAndroid Build Coastguard Worker 			goto bail;
386*1c60b9acSAndroid Build Coastguard Worker 		}
387*1c60b9acSAndroid Build Coastguard Worker 		EVP_MD_CTX_free(mdctx);
388*1c60b9acSAndroid Build Coastguard Worker 		used = (unsigned int)sig_len;
389*1c60b9acSAndroid Build Coastguard Worker 		break;
390*1c60b9acSAndroid Build Coastguard Worker 
391*1c60b9acSAndroid Build Coastguard Worker 	default:
392*1c60b9acSAndroid Build Coastguard Worker 		return -1;
393*1c60b9acSAndroid Build Coastguard Worker 	}
394*1c60b9acSAndroid Build Coastguard Worker 
395*1c60b9acSAndroid Build Coastguard Worker 	return (int)used;
396*1c60b9acSAndroid Build Coastguard Worker 
397*1c60b9acSAndroid Build Coastguard Worker bail:
398*1c60b9acSAndroid Build Coastguard Worker 	if (mdctx)
399*1c60b9acSAndroid Build Coastguard Worker 		EVP_MD_CTX_free(mdctx);
400*1c60b9acSAndroid Build Coastguard Worker 
401*1c60b9acSAndroid Build Coastguard Worker 	return -1;
402*1c60b9acSAndroid Build Coastguard Worker }
403*1c60b9acSAndroid Build Coastguard Worker 
404*1c60b9acSAndroid Build Coastguard Worker void
405*1c60b9acSAndroid Build Coastguard Worker lws_genrsa_destroy(struct lws_genrsa_ctx *ctx)
406*1c60b9acSAndroid Build Coastguard Worker {
407*1c60b9acSAndroid Build Coastguard Worker 	if (!ctx->ctx)
408*1c60b9acSAndroid Build Coastguard Worker 		return;
409*1c60b9acSAndroid Build Coastguard Worker 
410*1c60b9acSAndroid Build Coastguard Worker 	EVP_PKEY_CTX_free(ctx->ctx);
411*1c60b9acSAndroid Build Coastguard Worker 	ctx->ctx = NULL;
412*1c60b9acSAndroid Build Coastguard Worker 	ctx->rsa = NULL;
413*1c60b9acSAndroid Build Coastguard Worker }
414