1d4afb5ceSopenharmony_ci /*
2d4afb5ceSopenharmony_ci * libwebsockets - small server side websockets and web server implementation
3d4afb5ceSopenharmony_ci *
4d4afb5ceSopenharmony_ci * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
5d4afb5ceSopenharmony_ci *
6d4afb5ceSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
7d4afb5ceSopenharmony_ci * of this software and associated documentation files (the "Software"), to
8d4afb5ceSopenharmony_ci * deal in the Software without restriction, including without limitation the
9d4afb5ceSopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10d4afb5ceSopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is
11d4afb5ceSopenharmony_ci * furnished to do so, subject to the following conditions:
12d4afb5ceSopenharmony_ci *
13d4afb5ceSopenharmony_ci * The above copyright notice and this permission notice shall be included in
14d4afb5ceSopenharmony_ci * all copies or substantial portions of the Software.
15d4afb5ceSopenharmony_ci *
16d4afb5ceSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17d4afb5ceSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18d4afb5ceSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19d4afb5ceSopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20d4afb5ceSopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21d4afb5ceSopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22d4afb5ceSopenharmony_ci * IN THE SOFTWARE.
23d4afb5ceSopenharmony_ci *
24d4afb5ceSopenharmony_ci *  lws_genrsa provides an RSA abstraction api in lws that works the
25d4afb5ceSopenharmony_ci *  same whether you are using openssl or mbedtls crypto functions underneath.
26d4afb5ceSopenharmony_ci */
27d4afb5ceSopenharmony_ci#include "private-lib-core.h"
28d4afb5ceSopenharmony_ci#include "private-lib-tls-openssl.h"
29d4afb5ceSopenharmony_ci
30d4afb5ceSopenharmony_ci/*
31d4afb5ceSopenharmony_ci * Care: many openssl apis return 1 for success.  These are translated to the
32d4afb5ceSopenharmony_ci * lws convention of 0 for success.
33d4afb5ceSopenharmony_ci */
34d4afb5ceSopenharmony_ci
35d4afb5ceSopenharmony_civoid
36d4afb5ceSopenharmony_cilws_genrsa_destroy_elements(struct lws_gencrypto_keyelem *el)
37d4afb5ceSopenharmony_ci{
38d4afb5ceSopenharmony_ci	lws_gencrypto_destroy_elements(el, LWS_GENCRYPTO_RSA_KEYEL_COUNT);
39d4afb5ceSopenharmony_ci}
40d4afb5ceSopenharmony_ci
41d4afb5ceSopenharmony_cistatic int mode_map_crypt[] = { RSA_PKCS1_PADDING, RSA_PKCS1_OAEP_PADDING },
42d4afb5ceSopenharmony_ci	   mode_map_sig[]   = { RSA_PKCS1_PADDING, RSA_PKCS1_PSS_PADDING };
43d4afb5ceSopenharmony_ci
44d4afb5ceSopenharmony_cistatic int
45d4afb5ceSopenharmony_cirsa_pkey_wrap(struct lws_genrsa_ctx *ctx, RSA *rsa)
46d4afb5ceSopenharmony_ci{
47d4afb5ceSopenharmony_ci	EVP_PKEY *pkey;
48d4afb5ceSopenharmony_ci
49d4afb5ceSopenharmony_ci	/* we have the RSA object filled up... wrap in a PKEY */
50d4afb5ceSopenharmony_ci
51d4afb5ceSopenharmony_ci	pkey = EVP_PKEY_new();
52d4afb5ceSopenharmony_ci	if (!pkey)
53d4afb5ceSopenharmony_ci		return 1;
54d4afb5ceSopenharmony_ci
55d4afb5ceSopenharmony_ci	/* bind the PKEY to the RSA key we just prepared */
56d4afb5ceSopenharmony_ci
57d4afb5ceSopenharmony_ci	if (EVP_PKEY_assign_RSA(pkey, rsa) != 1) {
58d4afb5ceSopenharmony_ci		lwsl_err("%s: EVP_PKEY_assign_RSA_KEY failed\n", __func__);
59d4afb5ceSopenharmony_ci		goto bail;
60d4afb5ceSopenharmony_ci	}
61d4afb5ceSopenharmony_ci
62d4afb5ceSopenharmony_ci	/* pepare our PKEY_CTX with the PKEY */
63d4afb5ceSopenharmony_ci
64d4afb5ceSopenharmony_ci	ctx->ctx = EVP_PKEY_CTX_new(pkey, NULL);
65d4afb5ceSopenharmony_ci	EVP_PKEY_free(pkey);
66d4afb5ceSopenharmony_ci	pkey = NULL;
67d4afb5ceSopenharmony_ci	if (!ctx->ctx)
68d4afb5ceSopenharmony_ci		goto bail;
69d4afb5ceSopenharmony_ci
70d4afb5ceSopenharmony_ci	return 0;
71d4afb5ceSopenharmony_ci
72d4afb5ceSopenharmony_cibail:
73d4afb5ceSopenharmony_ci	if (pkey)
74d4afb5ceSopenharmony_ci		EVP_PKEY_free(pkey);
75d4afb5ceSopenharmony_ci
76d4afb5ceSopenharmony_ci	return 1;
77d4afb5ceSopenharmony_ci}
78d4afb5ceSopenharmony_ci
79d4afb5ceSopenharmony_ciint
80d4afb5ceSopenharmony_cilws_genrsa_create(struct lws_genrsa_ctx *ctx,
81d4afb5ceSopenharmony_ci		  const struct lws_gencrypto_keyelem *el,
82d4afb5ceSopenharmony_ci		  struct lws_context *context, enum enum_genrsa_mode mode,
83d4afb5ceSopenharmony_ci		  enum lws_genhash_types oaep_hashid)
84d4afb5ceSopenharmony_ci{
85d4afb5ceSopenharmony_ci	int n;
86d4afb5ceSopenharmony_ci
87d4afb5ceSopenharmony_ci	memset(ctx, 0, sizeof(*ctx));
88d4afb5ceSopenharmony_ci	ctx->context = context;
89d4afb5ceSopenharmony_ci	ctx->mode = mode;
90d4afb5ceSopenharmony_ci
91d4afb5ceSopenharmony_ci	/* Step 1:
92d4afb5ceSopenharmony_ci	 *
93d4afb5ceSopenharmony_ci	 * convert the MPI for e and n to OpenSSL BIGNUMs
94d4afb5ceSopenharmony_ci	 */
95d4afb5ceSopenharmony_ci
96d4afb5ceSopenharmony_ci	for (n = 0; n < 5; n++) {
97d4afb5ceSopenharmony_ci		ctx->bn[n] = BN_bin2bn(el[n].buf, (int)el[n].len, NULL);
98d4afb5ceSopenharmony_ci		if (!ctx->bn[n]) {
99d4afb5ceSopenharmony_ci			lwsl_notice("mpi load failed\n");
100d4afb5ceSopenharmony_ci			goto bail;
101d4afb5ceSopenharmony_ci		}
102d4afb5ceSopenharmony_ci	}
103d4afb5ceSopenharmony_ci
104d4afb5ceSopenharmony_ci	/* Step 2:
105d4afb5ceSopenharmony_ci	 *
106d4afb5ceSopenharmony_ci	 * assemble the OpenSSL RSA from the BIGNUMs
107d4afb5ceSopenharmony_ci	 */
108d4afb5ceSopenharmony_ci
109d4afb5ceSopenharmony_ci	ctx->rsa = RSA_new();
110d4afb5ceSopenharmony_ci	if (!ctx->rsa) {
111d4afb5ceSopenharmony_ci		lwsl_notice("Failed to create RSA\n");
112d4afb5ceSopenharmony_ci		goto bail;
113d4afb5ceSopenharmony_ci	}
114d4afb5ceSopenharmony_ci
115d4afb5ceSopenharmony_ci#if defined(LWS_HAVE_RSA_SET0_KEY) && !defined(USE_WOLFSSL)
116d4afb5ceSopenharmony_ci	if (RSA_set0_key(ctx->rsa, ctx->bn[LWS_GENCRYPTO_RSA_KEYEL_N],
117d4afb5ceSopenharmony_ci			 ctx->bn[LWS_GENCRYPTO_RSA_KEYEL_E],
118d4afb5ceSopenharmony_ci			 ctx->bn[LWS_GENCRYPTO_RSA_KEYEL_D]) != 1) {
119d4afb5ceSopenharmony_ci		lwsl_notice("RSA_set0_key failed\n");
120d4afb5ceSopenharmony_ci		goto bail;
121d4afb5ceSopenharmony_ci	}
122d4afb5ceSopenharmony_ci	RSA_set0_factors(ctx->rsa, ctx->bn[LWS_GENCRYPTO_RSA_KEYEL_P],
123d4afb5ceSopenharmony_ci				   ctx->bn[LWS_GENCRYPTO_RSA_KEYEL_Q]);
124d4afb5ceSopenharmony_ci#else
125d4afb5ceSopenharmony_ci	ctx->rsa->e = ctx->bn[LWS_GENCRYPTO_RSA_KEYEL_E];
126d4afb5ceSopenharmony_ci	ctx->rsa->n = ctx->bn[LWS_GENCRYPTO_RSA_KEYEL_N];
127d4afb5ceSopenharmony_ci	ctx->rsa->d = ctx->bn[LWS_GENCRYPTO_RSA_KEYEL_D];
128d4afb5ceSopenharmony_ci	ctx->rsa->p = ctx->bn[LWS_GENCRYPTO_RSA_KEYEL_P];
129d4afb5ceSopenharmony_ci	ctx->rsa->q = ctx->bn[LWS_GENCRYPTO_RSA_KEYEL_Q];
130d4afb5ceSopenharmony_ci#endif
131d4afb5ceSopenharmony_ci
132d4afb5ceSopenharmony_ci	if (!rsa_pkey_wrap(ctx, ctx->rsa))
133d4afb5ceSopenharmony_ci		return 0;
134d4afb5ceSopenharmony_ci
135d4afb5ceSopenharmony_cibail:
136d4afb5ceSopenharmony_ci	for (n = 0; n < 5; n++)
137d4afb5ceSopenharmony_ci		if (ctx->bn[n]) {
138d4afb5ceSopenharmony_ci			BN_clear_free(ctx->bn[n]);
139d4afb5ceSopenharmony_ci			ctx->bn[n] = NULL;
140d4afb5ceSopenharmony_ci		}
141d4afb5ceSopenharmony_ci
142d4afb5ceSopenharmony_ci	if (ctx->rsa) {
143d4afb5ceSopenharmony_ci		RSA_free(ctx->rsa);
144d4afb5ceSopenharmony_ci		ctx->rsa = NULL;
145d4afb5ceSopenharmony_ci	}
146d4afb5ceSopenharmony_ci
147d4afb5ceSopenharmony_ci	return 1;
148d4afb5ceSopenharmony_ci}
149d4afb5ceSopenharmony_ci
150d4afb5ceSopenharmony_ciint
151d4afb5ceSopenharmony_cilws_genrsa_new_keypair(struct lws_context *context, struct lws_genrsa_ctx *ctx,
152d4afb5ceSopenharmony_ci		       enum enum_genrsa_mode mode, struct lws_gencrypto_keyelem *el,
153d4afb5ceSopenharmony_ci		       int bits)
154d4afb5ceSopenharmony_ci{
155d4afb5ceSopenharmony_ci	BIGNUM *bn;
156d4afb5ceSopenharmony_ci	int n;
157d4afb5ceSopenharmony_ci
158d4afb5ceSopenharmony_ci	memset(ctx, 0, sizeof(*ctx));
159d4afb5ceSopenharmony_ci	ctx->context = context;
160d4afb5ceSopenharmony_ci	ctx->mode = mode;
161d4afb5ceSopenharmony_ci
162d4afb5ceSopenharmony_ci	ctx->rsa = RSA_new();
163d4afb5ceSopenharmony_ci	if (!ctx->rsa) {
164d4afb5ceSopenharmony_ci		lwsl_notice("Failed to create RSA\n");
165d4afb5ceSopenharmony_ci		return -1;
166d4afb5ceSopenharmony_ci	}
167d4afb5ceSopenharmony_ci
168d4afb5ceSopenharmony_ci	bn = BN_new();
169d4afb5ceSopenharmony_ci	if (!bn)
170d4afb5ceSopenharmony_ci		goto cleanup_1;
171d4afb5ceSopenharmony_ci	if (BN_set_word(bn, RSA_F4) != 1) {
172d4afb5ceSopenharmony_ci		BN_free(bn);
173d4afb5ceSopenharmony_ci		goto cleanup_1;
174d4afb5ceSopenharmony_ci	}
175d4afb5ceSopenharmony_ci
176d4afb5ceSopenharmony_ci	n = RSA_generate_key_ex(ctx->rsa, bits, bn, NULL);
177d4afb5ceSopenharmony_ci	BN_clear_free(bn);
178d4afb5ceSopenharmony_ci	if (n != 1)
179d4afb5ceSopenharmony_ci		goto cleanup_1;
180d4afb5ceSopenharmony_ci
181d4afb5ceSopenharmony_ci#if defined(LWS_HAVE_RSA_SET0_KEY) && !defined(USE_WOLFSSL)
182d4afb5ceSopenharmony_ci	{
183d4afb5ceSopenharmony_ci		const BIGNUM *mpi[5];
184d4afb5ceSopenharmony_ci
185d4afb5ceSopenharmony_ci		RSA_get0_key(ctx->rsa, &mpi[LWS_GENCRYPTO_RSA_KEYEL_N],
186d4afb5ceSopenharmony_ci			     &mpi[LWS_GENCRYPTO_RSA_KEYEL_E], &mpi[LWS_GENCRYPTO_RSA_KEYEL_D]);
187d4afb5ceSopenharmony_ci		RSA_get0_factors(ctx->rsa, &mpi[LWS_GENCRYPTO_RSA_KEYEL_P],
188d4afb5ceSopenharmony_ci				 &mpi[LWS_GENCRYPTO_RSA_KEYEL_Q]);
189d4afb5ceSopenharmony_ci#else
190d4afb5ceSopenharmony_ci	{
191d4afb5ceSopenharmony_ci		BIGNUM *mpi[5] = { ctx->rsa->e, ctx->rsa->n, ctx->rsa->d,
192d4afb5ceSopenharmony_ci				   ctx->rsa->p, ctx->rsa->q, };
193d4afb5ceSopenharmony_ci#endif
194d4afb5ceSopenharmony_ci		for (n = 0; n < 5; n++)
195d4afb5ceSopenharmony_ci			if (BN_num_bytes(mpi[n])) {
196d4afb5ceSopenharmony_ci				el[n].buf = lws_malloc(
197d4afb5ceSopenharmony_ci					(unsigned int)BN_num_bytes(mpi[n]), "genrsakey");
198d4afb5ceSopenharmony_ci				if (!el[n].buf)
199d4afb5ceSopenharmony_ci					goto cleanup;
200d4afb5ceSopenharmony_ci				el[n].len = (unsigned int)BN_num_bytes(mpi[n]);
201d4afb5ceSopenharmony_ci				BN_bn2bin(mpi[n], el[n].buf);
202d4afb5ceSopenharmony_ci			}
203d4afb5ceSopenharmony_ci	}
204d4afb5ceSopenharmony_ci
205d4afb5ceSopenharmony_ci	if (!rsa_pkey_wrap(ctx, ctx->rsa))
206d4afb5ceSopenharmony_ci		return 0;
207d4afb5ceSopenharmony_ci
208d4afb5ceSopenharmony_cicleanup:
209d4afb5ceSopenharmony_ci	for (n = 0; n < LWS_GENCRYPTO_RSA_KEYEL_COUNT; n++)
210d4afb5ceSopenharmony_ci		if (el[n].buf)
211d4afb5ceSopenharmony_ci			lws_free_set_NULL(el[n].buf);
212d4afb5ceSopenharmony_cicleanup_1:
213d4afb5ceSopenharmony_ci	RSA_free(ctx->rsa);
214d4afb5ceSopenharmony_ci	ctx->rsa = NULL;
215d4afb5ceSopenharmony_ci
216d4afb5ceSopenharmony_ci	return -1;
217d4afb5ceSopenharmony_ci}
218d4afb5ceSopenharmony_ci
219d4afb5ceSopenharmony_ci/*
220d4afb5ceSopenharmony_ci * in_len must be less than RSA_size(rsa) - 11 for the PKCS #1 v1.5
221d4afb5ceSopenharmony_ci * based padding modes
222d4afb5ceSopenharmony_ci */
223d4afb5ceSopenharmony_ci
224d4afb5ceSopenharmony_ciint
225d4afb5ceSopenharmony_cilws_genrsa_public_encrypt(struct lws_genrsa_ctx *ctx, const uint8_t *in,
226d4afb5ceSopenharmony_ci			  size_t in_len, uint8_t *out)
227d4afb5ceSopenharmony_ci{
228d4afb5ceSopenharmony_ci	int n = RSA_public_encrypt((int)in_len, in, out, ctx->rsa,
229d4afb5ceSopenharmony_ci				   mode_map_crypt[ctx->mode]);
230d4afb5ceSopenharmony_ci	if (n < 0) {
231d4afb5ceSopenharmony_ci		lwsl_err("%s: RSA_public_encrypt failed\n", __func__);
232d4afb5ceSopenharmony_ci		lws_tls_err_describe_clear();
233d4afb5ceSopenharmony_ci		return -1;
234d4afb5ceSopenharmony_ci	}
235d4afb5ceSopenharmony_ci
236d4afb5ceSopenharmony_ci	return n;
237d4afb5ceSopenharmony_ci}
238d4afb5ceSopenharmony_ci
239d4afb5ceSopenharmony_ciint
240d4afb5ceSopenharmony_cilws_genrsa_private_encrypt(struct lws_genrsa_ctx *ctx, const uint8_t *in,
241d4afb5ceSopenharmony_ci			   size_t in_len, uint8_t *out)
242d4afb5ceSopenharmony_ci{
243d4afb5ceSopenharmony_ci	int n = RSA_private_encrypt((int)in_len, in, out, ctx->rsa,
244d4afb5ceSopenharmony_ci			        mode_map_crypt[ctx->mode]);
245d4afb5ceSopenharmony_ci	if (n < 0) {
246d4afb5ceSopenharmony_ci		lwsl_err("%s: RSA_private_encrypt failed\n", __func__);
247d4afb5ceSopenharmony_ci		lws_tls_err_describe_clear();
248d4afb5ceSopenharmony_ci		return -1;
249d4afb5ceSopenharmony_ci	}
250d4afb5ceSopenharmony_ci
251d4afb5ceSopenharmony_ci	return n;
252d4afb5ceSopenharmony_ci}
253d4afb5ceSopenharmony_ci
254d4afb5ceSopenharmony_ciint
255d4afb5ceSopenharmony_cilws_genrsa_public_decrypt(struct lws_genrsa_ctx *ctx, const uint8_t *in,
256d4afb5ceSopenharmony_ci			  size_t in_len, uint8_t *out, size_t out_max)
257d4afb5ceSopenharmony_ci{
258d4afb5ceSopenharmony_ci	int n = RSA_public_decrypt((int)in_len, in, out, ctx->rsa,
259d4afb5ceSopenharmony_ci			       mode_map_crypt[ctx->mode]);
260d4afb5ceSopenharmony_ci	if (n < 0) {
261d4afb5ceSopenharmony_ci		lwsl_err("%s: RSA_public_decrypt failed\n", __func__);
262d4afb5ceSopenharmony_ci		return -1;
263d4afb5ceSopenharmony_ci	}
264d4afb5ceSopenharmony_ci
265d4afb5ceSopenharmony_ci	return n;
266d4afb5ceSopenharmony_ci}
267d4afb5ceSopenharmony_ci
268d4afb5ceSopenharmony_ciint
269d4afb5ceSopenharmony_cilws_genrsa_private_decrypt(struct lws_genrsa_ctx *ctx, const uint8_t *in,
270d4afb5ceSopenharmony_ci			   size_t in_len, uint8_t *out, size_t out_max)
271d4afb5ceSopenharmony_ci{
272d4afb5ceSopenharmony_ci	int n = RSA_private_decrypt((int)in_len, in, out, ctx->rsa,
273d4afb5ceSopenharmony_ci			        mode_map_crypt[ctx->mode]);
274d4afb5ceSopenharmony_ci	if (n < 0) {
275d4afb5ceSopenharmony_ci		lwsl_err("%s: RSA_private_decrypt failed\n", __func__);
276d4afb5ceSopenharmony_ci		lws_tls_err_describe_clear();
277d4afb5ceSopenharmony_ci		return -1;
278d4afb5ceSopenharmony_ci	}
279d4afb5ceSopenharmony_ci
280d4afb5ceSopenharmony_ci	return n;
281d4afb5ceSopenharmony_ci}
282d4afb5ceSopenharmony_ci
283d4afb5ceSopenharmony_ciint
284d4afb5ceSopenharmony_cilws_genrsa_hash_sig_verify(struct lws_genrsa_ctx *ctx, const uint8_t *in,
285d4afb5ceSopenharmony_ci			 enum lws_genhash_types hash_type, const uint8_t *sig,
286d4afb5ceSopenharmony_ci			 size_t sig_len)
287d4afb5ceSopenharmony_ci{
288d4afb5ceSopenharmony_ci	int n = lws_gencrypto_openssl_hash_to_NID(hash_type),
289d4afb5ceSopenharmony_ci	    h = (int)lws_genhash_size(hash_type);
290d4afb5ceSopenharmony_ci	const EVP_MD *md = NULL;
291d4afb5ceSopenharmony_ci
292d4afb5ceSopenharmony_ci	if (n < 0)
293d4afb5ceSopenharmony_ci		return -1;
294d4afb5ceSopenharmony_ci
295d4afb5ceSopenharmony_ci	switch(ctx->mode) {
296d4afb5ceSopenharmony_ci	case LGRSAM_PKCS1_1_5:
297d4afb5ceSopenharmony_ci		n = RSA_verify(n, in, (unsigned int)h, (uint8_t *)sig,
298d4afb5ceSopenharmony_ci			       (unsigned int)sig_len, ctx->rsa);
299d4afb5ceSopenharmony_ci		break;
300d4afb5ceSopenharmony_ci	case LGRSAM_PKCS1_OAEP_PSS:
301d4afb5ceSopenharmony_ci		md = lws_gencrypto_openssl_hash_to_EVP_MD(hash_type);
302d4afb5ceSopenharmony_ci		if (!md)
303d4afb5ceSopenharmony_ci			return -1;
304d4afb5ceSopenharmony_ci
305d4afb5ceSopenharmony_ci#if defined(LWS_HAVE_RSA_verify_pss_mgf1)
306d4afb5ceSopenharmony_ci		n = RSA_verify_pss_mgf1(ctx->rsa, in, h, md, NULL, -1,
307d4afb5ceSopenharmony_ci					(uint8_t *)sig,
308d4afb5ceSopenharmony_ci#else
309d4afb5ceSopenharmony_ci		n = RSA_verify_PKCS1_PSS(ctx->rsa, in, md, (uint8_t *)sig,
310d4afb5ceSopenharmony_ci#endif
311d4afb5ceSopenharmony_ci					 (int)sig_len);
312d4afb5ceSopenharmony_ci		break;
313d4afb5ceSopenharmony_ci	default:
314d4afb5ceSopenharmony_ci		return -1;
315d4afb5ceSopenharmony_ci	}
316d4afb5ceSopenharmony_ci
317d4afb5ceSopenharmony_ci	if (n != 1) {
318d4afb5ceSopenharmony_ci		lwsl_notice("%s: fail\n", __func__);
319d4afb5ceSopenharmony_ci		lws_tls_err_describe_clear();
320d4afb5ceSopenharmony_ci
321d4afb5ceSopenharmony_ci		return -1;
322d4afb5ceSopenharmony_ci	}
323d4afb5ceSopenharmony_ci
324d4afb5ceSopenharmony_ci	return 0;
325d4afb5ceSopenharmony_ci}
326d4afb5ceSopenharmony_ci
327d4afb5ceSopenharmony_ciint
328d4afb5ceSopenharmony_cilws_genrsa_hash_sign(struct lws_genrsa_ctx *ctx, const uint8_t *in,
329d4afb5ceSopenharmony_ci		       enum lws_genhash_types hash_type, uint8_t *sig,
330d4afb5ceSopenharmony_ci		       size_t sig_len)
331d4afb5ceSopenharmony_ci{
332d4afb5ceSopenharmony_ci	int n = lws_gencrypto_openssl_hash_to_NID(hash_type),
333d4afb5ceSopenharmony_ci	    h = (int)lws_genhash_size(hash_type);
334d4afb5ceSopenharmony_ci	unsigned int used = 0;
335d4afb5ceSopenharmony_ci	EVP_MD_CTX *mdctx = NULL;
336d4afb5ceSopenharmony_ci	const EVP_MD *md = NULL;
337d4afb5ceSopenharmony_ci
338d4afb5ceSopenharmony_ci	if (n < 0)
339d4afb5ceSopenharmony_ci		return -1;
340d4afb5ceSopenharmony_ci
341d4afb5ceSopenharmony_ci	switch(ctx->mode) {
342d4afb5ceSopenharmony_ci	case LGRSAM_PKCS1_1_5:
343d4afb5ceSopenharmony_ci		if (RSA_sign(n, in, (unsigned int)h, sig, &used, ctx->rsa) != 1) {
344d4afb5ceSopenharmony_ci			lwsl_err("%s: RSA_sign failed\n", __func__);
345d4afb5ceSopenharmony_ci
346d4afb5ceSopenharmony_ci			goto bail;
347d4afb5ceSopenharmony_ci		}
348d4afb5ceSopenharmony_ci		break;
349d4afb5ceSopenharmony_ci
350d4afb5ceSopenharmony_ci	case LGRSAM_PKCS1_OAEP_PSS:
351d4afb5ceSopenharmony_ci
352d4afb5ceSopenharmony_ci		md = lws_gencrypto_openssl_hash_to_EVP_MD(hash_type);
353d4afb5ceSopenharmony_ci		if (!md)
354d4afb5ceSopenharmony_ci			return -1;
355d4afb5ceSopenharmony_ci
356d4afb5ceSopenharmony_ci		if (EVP_PKEY_CTX_set_rsa_padding(ctx->ctx,
357d4afb5ceSopenharmony_ci						 mode_map_sig[ctx->mode]) != 1) {
358d4afb5ceSopenharmony_ci			lwsl_err("%s: set_rsa_padding failed\n", __func__);
359d4afb5ceSopenharmony_ci
360d4afb5ceSopenharmony_ci			goto bail;
361d4afb5ceSopenharmony_ci		}
362d4afb5ceSopenharmony_ci
363d4afb5ceSopenharmony_ci		mdctx = EVP_MD_CTX_create();
364d4afb5ceSopenharmony_ci		if (!mdctx)
365d4afb5ceSopenharmony_ci			goto bail;
366d4afb5ceSopenharmony_ci
367d4afb5ceSopenharmony_ci		if (EVP_DigestSignInit(mdctx, NULL, md, NULL,
368d4afb5ceSopenharmony_ci#if defined(USE_WOLFSSL)
369d4afb5ceSopenharmony_ci					ctx->ctx->pkey)) {
370d4afb5ceSopenharmony_ci#else
371d4afb5ceSopenharmony_ci				       EVP_PKEY_CTX_get0_pkey(ctx->ctx))) {
372d4afb5ceSopenharmony_ci#endif
373d4afb5ceSopenharmony_ci			lwsl_err("%s: EVP_DigestSignInit failed\n", __func__);
374d4afb5ceSopenharmony_ci
375d4afb5ceSopenharmony_ci			goto bail;
376d4afb5ceSopenharmony_ci		}
377d4afb5ceSopenharmony_ci		if (EVP_DigestSignUpdate(mdctx, in, (unsigned int)EVP_MD_size(md))) {
378d4afb5ceSopenharmony_ci			lwsl_err("%s: EVP_DigestSignUpdate failed\n", __func__);
379d4afb5ceSopenharmony_ci
380d4afb5ceSopenharmony_ci			goto bail;
381d4afb5ceSopenharmony_ci		}
382d4afb5ceSopenharmony_ci		if (EVP_DigestSignFinal(mdctx, sig, &sig_len)) {
383d4afb5ceSopenharmony_ci			lwsl_err("%s: EVP_DigestSignFinal failed\n", __func__);
384d4afb5ceSopenharmony_ci
385d4afb5ceSopenharmony_ci			goto bail;
386d4afb5ceSopenharmony_ci		}
387d4afb5ceSopenharmony_ci		EVP_MD_CTX_free(mdctx);
388d4afb5ceSopenharmony_ci		used = (unsigned int)sig_len;
389d4afb5ceSopenharmony_ci		break;
390d4afb5ceSopenharmony_ci
391d4afb5ceSopenharmony_ci	default:
392d4afb5ceSopenharmony_ci		return -1;
393d4afb5ceSopenharmony_ci	}
394d4afb5ceSopenharmony_ci
395d4afb5ceSopenharmony_ci	return (int)used;
396d4afb5ceSopenharmony_ci
397d4afb5ceSopenharmony_cibail:
398d4afb5ceSopenharmony_ci	if (mdctx)
399d4afb5ceSopenharmony_ci		EVP_MD_CTX_free(mdctx);
400d4afb5ceSopenharmony_ci
401d4afb5ceSopenharmony_ci	return -1;
402d4afb5ceSopenharmony_ci}
403d4afb5ceSopenharmony_ci
404d4afb5ceSopenharmony_civoid
405d4afb5ceSopenharmony_cilws_genrsa_destroy(struct lws_genrsa_ctx *ctx)
406d4afb5ceSopenharmony_ci{
407d4afb5ceSopenharmony_ci	if (!ctx->ctx)
408d4afb5ceSopenharmony_ci		return;
409d4afb5ceSopenharmony_ci
410d4afb5ceSopenharmony_ci	EVP_PKEY_CTX_free(ctx->ctx);
411d4afb5ceSopenharmony_ci	ctx->ctx = NULL;
412d4afb5ceSopenharmony_ci	ctx->rsa = NULL;
413d4afb5ceSopenharmony_ci}
414