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-mbedtls.h"
29d4afb5ceSopenharmony_ci#include <mbedtls/rsa.h>
30d4afb5ceSopenharmony_ci
31d4afb5ceSopenharmony_civoid
32d4afb5ceSopenharmony_cilws_genrsa_destroy_elements(struct lws_gencrypto_keyelem *el)
33d4afb5ceSopenharmony_ci{
34d4afb5ceSopenharmony_ci	int n;
35d4afb5ceSopenharmony_ci
36d4afb5ceSopenharmony_ci	for (n = 0; n < LWS_GENCRYPTO_RSA_KEYEL_COUNT; n++)
37d4afb5ceSopenharmony_ci		if (el[n].buf)
38d4afb5ceSopenharmony_ci			lws_free_set_NULL(el[n].buf);
39d4afb5ceSopenharmony_ci}
40d4afb5ceSopenharmony_ci
41d4afb5ceSopenharmony_cistatic int mode_map[] = { MBEDTLS_RSA_PKCS_V15, MBEDTLS_RSA_PKCS_V21 };
42d4afb5ceSopenharmony_ci
43d4afb5ceSopenharmony_ciint
44d4afb5ceSopenharmony_cilws_genrsa_create(struct lws_genrsa_ctx *ctx,
45d4afb5ceSopenharmony_ci		  const struct lws_gencrypto_keyelem *el,
46d4afb5ceSopenharmony_ci		  struct lws_context *context, enum enum_genrsa_mode mode,
47d4afb5ceSopenharmony_ci		  enum lws_genhash_types oaep_hashid)
48d4afb5ceSopenharmony_ci{
49d4afb5ceSopenharmony_ci	memset(ctx, 0, sizeof(*ctx));
50d4afb5ceSopenharmony_ci	ctx->ctx = lws_zalloc(sizeof(*ctx->ctx), "genrsa");
51d4afb5ceSopenharmony_ci	if (!ctx->ctx)
52d4afb5ceSopenharmony_ci		return 1;
53d4afb5ceSopenharmony_ci
54d4afb5ceSopenharmony_ci	ctx->context = context;
55d4afb5ceSopenharmony_ci	ctx->mode = mode;
56d4afb5ceSopenharmony_ci
57d4afb5ceSopenharmony_ci	if (mode >= LGRSAM_COUNT)
58d4afb5ceSopenharmony_ci		return -1;
59d4afb5ceSopenharmony_ci
60d4afb5ceSopenharmony_ci#if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000
61d4afb5ceSopenharmony_ci	mbedtls_rsa_init(ctx->ctx, mode_map[mode], 0);
62d4afb5ceSopenharmony_ci#else
63d4afb5ceSopenharmony_ci	mbedtls_rsa_init(ctx->ctx);
64d4afb5ceSopenharmony_ci	mbedtls_rsa_set_padding(ctx->ctx, mode_map[mode], 0);
65d4afb5ceSopenharmony_ci#endif
66d4afb5ceSopenharmony_ci
67d4afb5ceSopenharmony_ci	ctx->ctx->MBEDTLS_PRIVATE(padding) = mode_map[mode];
68d4afb5ceSopenharmony_ci	ctx->ctx->MBEDTLS_PRIVATE(hash_id) =
69d4afb5ceSopenharmony_ci			(int)lws_gencrypto_mbedtls_hash_to_MD_TYPE(oaep_hashid);
70d4afb5ceSopenharmony_ci
71d4afb5ceSopenharmony_ci	{
72d4afb5ceSopenharmony_ci		int n;
73d4afb5ceSopenharmony_ci
74d4afb5ceSopenharmony_ci		mbedtls_mpi *mpi[LWS_GENCRYPTO_RSA_KEYEL_COUNT] = {
75d4afb5ceSopenharmony_ci			&ctx->ctx->MBEDTLS_PRIVATE(E),
76d4afb5ceSopenharmony_ci			&ctx->ctx->MBEDTLS_PRIVATE(N),
77d4afb5ceSopenharmony_ci			&ctx->ctx->MBEDTLS_PRIVATE(D),
78d4afb5ceSopenharmony_ci			&ctx->ctx->MBEDTLS_PRIVATE(P),
79d4afb5ceSopenharmony_ci			&ctx->ctx->MBEDTLS_PRIVATE(Q),
80d4afb5ceSopenharmony_ci			&ctx->ctx->MBEDTLS_PRIVATE(DP),
81d4afb5ceSopenharmony_ci			&ctx->ctx->MBEDTLS_PRIVATE(DQ),
82d4afb5ceSopenharmony_ci			&ctx->ctx->MBEDTLS_PRIVATE(QP),
83d4afb5ceSopenharmony_ci		};
84d4afb5ceSopenharmony_ci
85d4afb5ceSopenharmony_ci		for (n = 0; n < LWS_GENCRYPTO_RSA_KEYEL_COUNT; n++)
86d4afb5ceSopenharmony_ci			if (el[n].buf &&
87d4afb5ceSopenharmony_ci			    mbedtls_mpi_read_binary(mpi[n], el[n].buf,
88d4afb5ceSopenharmony_ci					    	    el[n].len)) {
89d4afb5ceSopenharmony_ci				lwsl_notice("mpi load failed\n");
90d4afb5ceSopenharmony_ci				lws_free_set_NULL(ctx->ctx);
91d4afb5ceSopenharmony_ci
92d4afb5ceSopenharmony_ci				return -1;
93d4afb5ceSopenharmony_ci			}
94d4afb5ceSopenharmony_ci
95d4afb5ceSopenharmony_ci		/* mbedtls... compute missing P & Q */
96d4afb5ceSopenharmony_ci
97d4afb5ceSopenharmony_ci		if ( el[LWS_GENCRYPTO_RSA_KEYEL_D].len &&
98d4afb5ceSopenharmony_ci		    !el[LWS_GENCRYPTO_RSA_KEYEL_P].len &&
99d4afb5ceSopenharmony_ci		    !el[LWS_GENCRYPTO_RSA_KEYEL_Q].len) {
100d4afb5ceSopenharmony_ci#if defined(LWS_HAVE_mbedtls_rsa_complete)
101d4afb5ceSopenharmony_ci			if (mbedtls_rsa_complete(ctx->ctx)) {
102d4afb5ceSopenharmony_ci				lwsl_notice("mbedtls_rsa_complete failed\n");
103d4afb5ceSopenharmony_ci#else
104d4afb5ceSopenharmony_ci			{
105d4afb5ceSopenharmony_ci				lwsl_notice("%s: you have to provide P and Q\n", __func__);
106d4afb5ceSopenharmony_ci#endif
107d4afb5ceSopenharmony_ci				lws_free_set_NULL(ctx->ctx);
108d4afb5ceSopenharmony_ci
109d4afb5ceSopenharmony_ci				return -1;
110d4afb5ceSopenharmony_ci			}
111d4afb5ceSopenharmony_ci
112d4afb5ceSopenharmony_ci		}
113d4afb5ceSopenharmony_ci	}
114d4afb5ceSopenharmony_ci
115d4afb5ceSopenharmony_ci	ctx->ctx->MBEDTLS_PRIVATE(len) = el[LWS_GENCRYPTO_RSA_KEYEL_N].len;
116d4afb5ceSopenharmony_ci
117d4afb5ceSopenharmony_ci	return 0;
118d4afb5ceSopenharmony_ci}
119d4afb5ceSopenharmony_ci
120d4afb5ceSopenharmony_cistatic int
121d4afb5ceSopenharmony_ci_rngf(void *context, unsigned char *buf, size_t len)
122d4afb5ceSopenharmony_ci{
123d4afb5ceSopenharmony_ci	if ((size_t)lws_get_random(context, buf, len) == len)
124d4afb5ceSopenharmony_ci		return 0;
125d4afb5ceSopenharmony_ci
126d4afb5ceSopenharmony_ci	return -1;
127d4afb5ceSopenharmony_ci}
128d4afb5ceSopenharmony_ci
129d4afb5ceSopenharmony_ciint
130d4afb5ceSopenharmony_cilws_genrsa_new_keypair(struct lws_context *context, struct lws_genrsa_ctx *ctx,
131d4afb5ceSopenharmony_ci		       enum enum_genrsa_mode mode, struct lws_gencrypto_keyelem *el,
132d4afb5ceSopenharmony_ci		       int bits)
133d4afb5ceSopenharmony_ci{
134d4afb5ceSopenharmony_ci	int n;
135d4afb5ceSopenharmony_ci
136d4afb5ceSopenharmony_ci	memset(ctx, 0, sizeof(*ctx));
137d4afb5ceSopenharmony_ci	ctx->ctx = lws_zalloc(sizeof(*ctx->ctx), "genrsa");
138d4afb5ceSopenharmony_ci	if (!ctx->ctx)
139d4afb5ceSopenharmony_ci		return -1;
140d4afb5ceSopenharmony_ci
141d4afb5ceSopenharmony_ci	ctx->context = context;
142d4afb5ceSopenharmony_ci	ctx->mode = mode;
143d4afb5ceSopenharmony_ci
144d4afb5ceSopenharmony_ci	if (mode >= LGRSAM_COUNT)
145d4afb5ceSopenharmony_ci		return -1;
146d4afb5ceSopenharmony_ci
147d4afb5ceSopenharmony_ci#if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000
148d4afb5ceSopenharmony_ci	mbedtls_rsa_init(ctx->ctx, mode_map[mode], 0);
149d4afb5ceSopenharmony_ci#else
150d4afb5ceSopenharmony_ci	mbedtls_rsa_init(ctx->ctx);
151d4afb5ceSopenharmony_ci	mbedtls_rsa_set_padding(ctx->ctx, mode_map[mode], 0);
152d4afb5ceSopenharmony_ci#endif
153d4afb5ceSopenharmony_ci
154d4afb5ceSopenharmony_ci	n = mbedtls_rsa_gen_key(ctx->ctx, _rngf, context, (unsigned int)bits, 65537);
155d4afb5ceSopenharmony_ci	if (n) {
156d4afb5ceSopenharmony_ci		lwsl_err("mbedtls_rsa_gen_key failed 0x%x\n", -n);
157d4afb5ceSopenharmony_ci		goto cleanup_1;
158d4afb5ceSopenharmony_ci	}
159d4afb5ceSopenharmony_ci
160d4afb5ceSopenharmony_ci	{
161d4afb5ceSopenharmony_ci		mbedtls_mpi *mpi[LWS_GENCRYPTO_RSA_KEYEL_COUNT] = {
162d4afb5ceSopenharmony_ci			&ctx->ctx->MBEDTLS_PRIVATE(E),
163d4afb5ceSopenharmony_ci			&ctx->ctx->MBEDTLS_PRIVATE(N),
164d4afb5ceSopenharmony_ci			&ctx->ctx->MBEDTLS_PRIVATE(D),
165d4afb5ceSopenharmony_ci			&ctx->ctx->MBEDTLS_PRIVATE(P),
166d4afb5ceSopenharmony_ci			&ctx->ctx->MBEDTLS_PRIVATE(Q),
167d4afb5ceSopenharmony_ci			&ctx->ctx->MBEDTLS_PRIVATE(DP),
168d4afb5ceSopenharmony_ci			&ctx->ctx->MBEDTLS_PRIVATE(DQ),
169d4afb5ceSopenharmony_ci			&ctx->ctx->MBEDTLS_PRIVATE(QP),
170d4afb5ceSopenharmony_ci		};
171d4afb5ceSopenharmony_ci
172d4afb5ceSopenharmony_ci		for (n = 0; n < LWS_GENCRYPTO_RSA_KEYEL_COUNT; n++)
173d4afb5ceSopenharmony_ci			if (mpi[n] && mbedtls_mpi_size(mpi[n])) {
174d4afb5ceSopenharmony_ci				el[n].buf = lws_malloc(
175d4afb5ceSopenharmony_ci					mbedtls_mpi_size(mpi[n]), "genrsakey");
176d4afb5ceSopenharmony_ci				if (!el[n].buf)
177d4afb5ceSopenharmony_ci					goto cleanup;
178d4afb5ceSopenharmony_ci				el[n].len = (uint32_t)mbedtls_mpi_size(mpi[n]);
179d4afb5ceSopenharmony_ci				if (mbedtls_mpi_write_binary(mpi[n], el[n].buf,
180d4afb5ceSopenharmony_ci							 el[n].len))
181d4afb5ceSopenharmony_ci					goto cleanup;
182d4afb5ceSopenharmony_ci			}
183d4afb5ceSopenharmony_ci	}
184d4afb5ceSopenharmony_ci
185d4afb5ceSopenharmony_ci	return 0;
186d4afb5ceSopenharmony_ci
187d4afb5ceSopenharmony_cicleanup:
188d4afb5ceSopenharmony_ci	for (n = 0; n < LWS_GENCRYPTO_RSA_KEYEL_COUNT; n++)
189d4afb5ceSopenharmony_ci		if (el[n].buf)
190d4afb5ceSopenharmony_ci			lws_free_set_NULL(el[n].buf);
191d4afb5ceSopenharmony_cicleanup_1:
192d4afb5ceSopenharmony_ci	lws_free(ctx->ctx);
193d4afb5ceSopenharmony_ci
194d4afb5ceSopenharmony_ci	return -1;
195d4afb5ceSopenharmony_ci}
196d4afb5ceSopenharmony_ci
197d4afb5ceSopenharmony_ciint
198d4afb5ceSopenharmony_cilws_genrsa_public_decrypt(struct lws_genrsa_ctx *ctx, const uint8_t *in,
199d4afb5ceSopenharmony_ci			  size_t in_len, uint8_t *out, size_t out_max)
200d4afb5ceSopenharmony_ci{
201d4afb5ceSopenharmony_ci	size_t olen = 0;
202d4afb5ceSopenharmony_ci	int n;
203d4afb5ceSopenharmony_ci
204d4afb5ceSopenharmony_ci	ctx->ctx->MBEDTLS_PRIVATE(len) = in_len;
205d4afb5ceSopenharmony_ci
206d4afb5ceSopenharmony_ci#if defined(LWS_HAVE_mbedtls_rsa_complete)
207d4afb5ceSopenharmony_ci	mbedtls_rsa_complete(ctx->ctx);
208d4afb5ceSopenharmony_ci#endif
209d4afb5ceSopenharmony_ci
210d4afb5ceSopenharmony_ci	switch(ctx->mode) {
211d4afb5ceSopenharmony_ci	case LGRSAM_PKCS1_1_5:
212d4afb5ceSopenharmony_ci		n = mbedtls_rsa_rsaes_pkcs1_v15_decrypt(ctx->ctx, _rngf,
213d4afb5ceSopenharmony_ci							ctx->context,
214d4afb5ceSopenharmony_ci#if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000
215d4afb5ceSopenharmony_ci							MBEDTLS_RSA_PUBLIC,
216d4afb5ceSopenharmony_ci#endif
217d4afb5ceSopenharmony_ci							&olen, in, out,
218d4afb5ceSopenharmony_ci							out_max);
219d4afb5ceSopenharmony_ci		break;
220d4afb5ceSopenharmony_ci	case LGRSAM_PKCS1_OAEP_PSS:
221d4afb5ceSopenharmony_ci		n = mbedtls_rsa_rsaes_oaep_decrypt(ctx->ctx, _rngf,
222d4afb5ceSopenharmony_ci						   ctx->context,
223d4afb5ceSopenharmony_ci#if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000
224d4afb5ceSopenharmony_ci							MBEDTLS_RSA_PUBLIC,
225d4afb5ceSopenharmony_ci#endif
226d4afb5ceSopenharmony_ci						   NULL, 0,
227d4afb5ceSopenharmony_ci						   &olen, in, out, out_max);
228d4afb5ceSopenharmony_ci		break;
229d4afb5ceSopenharmony_ci	default:
230d4afb5ceSopenharmony_ci		return -1;
231d4afb5ceSopenharmony_ci	}
232d4afb5ceSopenharmony_ci	if (n) {
233d4afb5ceSopenharmony_ci		lwsl_notice("%s: -0x%x\n", __func__, -n);
234d4afb5ceSopenharmony_ci
235d4afb5ceSopenharmony_ci		return -1;
236d4afb5ceSopenharmony_ci	}
237d4afb5ceSopenharmony_ci
238d4afb5ceSopenharmony_ci	return (int)olen;
239d4afb5ceSopenharmony_ci}
240d4afb5ceSopenharmony_ci
241d4afb5ceSopenharmony_ciint
242d4afb5ceSopenharmony_cilws_genrsa_private_decrypt(struct lws_genrsa_ctx *ctx, const uint8_t *in,
243d4afb5ceSopenharmony_ci			   size_t in_len, uint8_t *out, size_t out_max)
244d4afb5ceSopenharmony_ci{
245d4afb5ceSopenharmony_ci	size_t olen = 0;
246d4afb5ceSopenharmony_ci	int n;
247d4afb5ceSopenharmony_ci
248d4afb5ceSopenharmony_ci	ctx->ctx->MBEDTLS_PRIVATE(len) = in_len;
249d4afb5ceSopenharmony_ci
250d4afb5ceSopenharmony_ci#if defined(LWS_HAVE_mbedtls_rsa_complete)
251d4afb5ceSopenharmony_ci	mbedtls_rsa_complete(ctx->ctx);
252d4afb5ceSopenharmony_ci#endif
253d4afb5ceSopenharmony_ci
254d4afb5ceSopenharmony_ci	switch(ctx->mode) {
255d4afb5ceSopenharmony_ci	case LGRSAM_PKCS1_1_5:
256d4afb5ceSopenharmony_ci		n = mbedtls_rsa_rsaes_pkcs1_v15_decrypt(ctx->ctx, _rngf,
257d4afb5ceSopenharmony_ci							ctx->context,
258d4afb5ceSopenharmony_ci#if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000
259d4afb5ceSopenharmony_ci							MBEDTLS_RSA_PRIVATE,
260d4afb5ceSopenharmony_ci#endif
261d4afb5ceSopenharmony_ci							&olen, in, out,
262d4afb5ceSopenharmony_ci							out_max);
263d4afb5ceSopenharmony_ci		break;
264d4afb5ceSopenharmony_ci	case LGRSAM_PKCS1_OAEP_PSS:
265d4afb5ceSopenharmony_ci		n = mbedtls_rsa_rsaes_oaep_decrypt(ctx->ctx, _rngf,
266d4afb5ceSopenharmony_ci						   ctx->context,
267d4afb5ceSopenharmony_ci#if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000
268d4afb5ceSopenharmony_ci						   MBEDTLS_RSA_PRIVATE,
269d4afb5ceSopenharmony_ci#endif
270d4afb5ceSopenharmony_ci						   NULL, 0,
271d4afb5ceSopenharmony_ci						   &olen, in, out, out_max);
272d4afb5ceSopenharmony_ci		break;
273d4afb5ceSopenharmony_ci	default:
274d4afb5ceSopenharmony_ci		return -1;
275d4afb5ceSopenharmony_ci	}
276d4afb5ceSopenharmony_ci	if (n) {
277d4afb5ceSopenharmony_ci		lwsl_notice("%s: -0x%x\n", __func__, -n);
278d4afb5ceSopenharmony_ci
279d4afb5ceSopenharmony_ci		return -1;
280d4afb5ceSopenharmony_ci	}
281d4afb5ceSopenharmony_ci
282d4afb5ceSopenharmony_ci	return (int)olen;
283d4afb5ceSopenharmony_ci}
284d4afb5ceSopenharmony_ci
285d4afb5ceSopenharmony_ciint
286d4afb5ceSopenharmony_cilws_genrsa_public_encrypt(struct lws_genrsa_ctx *ctx, const uint8_t *in,
287d4afb5ceSopenharmony_ci			  size_t in_len, uint8_t *out)
288d4afb5ceSopenharmony_ci{
289d4afb5ceSopenharmony_ci	int n;
290d4afb5ceSopenharmony_ci
291d4afb5ceSopenharmony_ci#if defined(LWS_HAVE_mbedtls_rsa_complete)
292d4afb5ceSopenharmony_ci	mbedtls_rsa_complete(ctx->ctx);
293d4afb5ceSopenharmony_ci#endif
294d4afb5ceSopenharmony_ci
295d4afb5ceSopenharmony_ci	switch(ctx->mode) {
296d4afb5ceSopenharmony_ci	case LGRSAM_PKCS1_1_5:
297d4afb5ceSopenharmony_ci		n = mbedtls_rsa_rsaes_pkcs1_v15_encrypt(ctx->ctx, _rngf,
298d4afb5ceSopenharmony_ci							ctx->context,
299d4afb5ceSopenharmony_ci#if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000
300d4afb5ceSopenharmony_ci							MBEDTLS_RSA_PUBLIC,
301d4afb5ceSopenharmony_ci#endif
302d4afb5ceSopenharmony_ci							in_len, in, out);
303d4afb5ceSopenharmony_ci		break;
304d4afb5ceSopenharmony_ci	case LGRSAM_PKCS1_OAEP_PSS:
305d4afb5ceSopenharmony_ci		n = mbedtls_rsa_rsaes_oaep_encrypt(ctx->ctx, _rngf,
306d4afb5ceSopenharmony_ci						   ctx->context,
307d4afb5ceSopenharmony_ci#if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000
308d4afb5ceSopenharmony_ci						   MBEDTLS_RSA_PUBLIC,
309d4afb5ceSopenharmony_ci#endif
310d4afb5ceSopenharmony_ci						   NULL, 0,
311d4afb5ceSopenharmony_ci						   in_len, in, out);
312d4afb5ceSopenharmony_ci		break;
313d4afb5ceSopenharmony_ci	default:
314d4afb5ceSopenharmony_ci		return -1;
315d4afb5ceSopenharmony_ci	}
316d4afb5ceSopenharmony_ci	if (n < 0) {
317d4afb5ceSopenharmony_ci		lwsl_notice("%s: -0x%x: in_len: %d\n", __func__, -n,
318d4afb5ceSopenharmony_ci				(int)in_len);
319d4afb5ceSopenharmony_ci
320d4afb5ceSopenharmony_ci		return -1;
321d4afb5ceSopenharmony_ci	}
322d4afb5ceSopenharmony_ci
323d4afb5ceSopenharmony_ci	return (int)mbedtls_mpi_size(&ctx->ctx->MBEDTLS_PRIVATE(N));
324d4afb5ceSopenharmony_ci}
325d4afb5ceSopenharmony_ci
326d4afb5ceSopenharmony_ciint
327d4afb5ceSopenharmony_cilws_genrsa_private_encrypt(struct lws_genrsa_ctx *ctx, const uint8_t *in,
328d4afb5ceSopenharmony_ci			   size_t in_len, uint8_t *out)
329d4afb5ceSopenharmony_ci{
330d4afb5ceSopenharmony_ci	int n;
331d4afb5ceSopenharmony_ci
332d4afb5ceSopenharmony_ci#if defined(LWS_HAVE_mbedtls_rsa_complete)
333d4afb5ceSopenharmony_ci	mbedtls_rsa_complete(ctx->ctx);
334d4afb5ceSopenharmony_ci#endif
335d4afb5ceSopenharmony_ci
336d4afb5ceSopenharmony_ci	switch(ctx->mode) {
337d4afb5ceSopenharmony_ci	case LGRSAM_PKCS1_1_5:
338d4afb5ceSopenharmony_ci		n = mbedtls_rsa_rsaes_pkcs1_v15_encrypt(ctx->ctx, _rngf,
339d4afb5ceSopenharmony_ci							ctx->context,
340d4afb5ceSopenharmony_ci#if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000
341d4afb5ceSopenharmony_ci							MBEDTLS_RSA_PRIVATE,
342d4afb5ceSopenharmony_ci#endif
343d4afb5ceSopenharmony_ci							in_len, in, out);
344d4afb5ceSopenharmony_ci		break;
345d4afb5ceSopenharmony_ci	case LGRSAM_PKCS1_OAEP_PSS:
346d4afb5ceSopenharmony_ci		n = mbedtls_rsa_rsaes_oaep_encrypt(ctx->ctx, _rngf,
347d4afb5ceSopenharmony_ci						   ctx->context,
348d4afb5ceSopenharmony_ci#if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000
349d4afb5ceSopenharmony_ci						   MBEDTLS_RSA_PRIVATE,
350d4afb5ceSopenharmony_ci#endif
351d4afb5ceSopenharmony_ci						   NULL, 0,
352d4afb5ceSopenharmony_ci						   in_len, in, out);
353d4afb5ceSopenharmony_ci		break;
354d4afb5ceSopenharmony_ci	default:
355d4afb5ceSopenharmony_ci		return -1;
356d4afb5ceSopenharmony_ci	}
357d4afb5ceSopenharmony_ci	if (n) {
358d4afb5ceSopenharmony_ci		lwsl_notice("%s: -0x%x: in_len: %d\n", __func__, -n,
359d4afb5ceSopenharmony_ci				(int)in_len);
360d4afb5ceSopenharmony_ci
361d4afb5ceSopenharmony_ci		return -1;
362d4afb5ceSopenharmony_ci	}
363d4afb5ceSopenharmony_ci
364d4afb5ceSopenharmony_ci	return (int)mbedtls_mpi_size(&ctx->ctx->MBEDTLS_PRIVATE(N));
365d4afb5ceSopenharmony_ci}
366d4afb5ceSopenharmony_ci
367d4afb5ceSopenharmony_ciint
368d4afb5ceSopenharmony_cilws_genrsa_hash_sig_verify(struct lws_genrsa_ctx *ctx, const uint8_t *in,
369d4afb5ceSopenharmony_ci			 enum lws_genhash_types hash_type, const uint8_t *sig,
370d4afb5ceSopenharmony_ci			 size_t sig_len)
371d4afb5ceSopenharmony_ci{
372d4afb5ceSopenharmony_ci	int n, h = (int)lws_gencrypto_mbedtls_hash_to_MD_TYPE(hash_type);
373d4afb5ceSopenharmony_ci
374d4afb5ceSopenharmony_ci	if (h < 0)
375d4afb5ceSopenharmony_ci		return -1;
376d4afb5ceSopenharmony_ci
377d4afb5ceSopenharmony_ci#if defined(LWS_HAVE_mbedtls_rsa_complete)
378d4afb5ceSopenharmony_ci	mbedtls_rsa_complete(ctx->ctx);
379d4afb5ceSopenharmony_ci#endif
380d4afb5ceSopenharmony_ci
381d4afb5ceSopenharmony_ci	switch(ctx->mode) {
382d4afb5ceSopenharmony_ci	case LGRSAM_PKCS1_1_5:
383d4afb5ceSopenharmony_ci		n = mbedtls_rsa_rsassa_pkcs1_v15_verify(ctx->ctx,
384d4afb5ceSopenharmony_ci#if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000
385d4afb5ceSopenharmony_ci							NULL, NULL,
386d4afb5ceSopenharmony_ci							MBEDTLS_RSA_PUBLIC,
387d4afb5ceSopenharmony_ci#endif
388d4afb5ceSopenharmony_ci							(mbedtls_md_type_t)h,
389d4afb5ceSopenharmony_ci							(unsigned int)lws_genhash_size(hash_type),
390d4afb5ceSopenharmony_ci							in, sig);
391d4afb5ceSopenharmony_ci		break;
392d4afb5ceSopenharmony_ci	case LGRSAM_PKCS1_OAEP_PSS:
393d4afb5ceSopenharmony_ci		n = mbedtls_rsa_rsassa_pss_verify(ctx->ctx,
394d4afb5ceSopenharmony_ci#if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000
395d4afb5ceSopenharmony_ci						  NULL, NULL,
396d4afb5ceSopenharmony_ci						  MBEDTLS_RSA_PUBLIC,
397d4afb5ceSopenharmony_ci#endif
398d4afb5ceSopenharmony_ci						  (mbedtls_md_type_t)h,
399d4afb5ceSopenharmony_ci						  (unsigned int)lws_genhash_size(hash_type),
400d4afb5ceSopenharmony_ci						  in, sig);
401d4afb5ceSopenharmony_ci		break;
402d4afb5ceSopenharmony_ci	default:
403d4afb5ceSopenharmony_ci		return -1;
404d4afb5ceSopenharmony_ci	}
405d4afb5ceSopenharmony_ci	if (n < 0) {
406d4afb5ceSopenharmony_ci		lwsl_notice("%s: (mode %d) -0x%x\n", __func__, ctx->mode, -n);
407d4afb5ceSopenharmony_ci
408d4afb5ceSopenharmony_ci		return -1;
409d4afb5ceSopenharmony_ci	}
410d4afb5ceSopenharmony_ci
411d4afb5ceSopenharmony_ci	return n;
412d4afb5ceSopenharmony_ci}
413d4afb5ceSopenharmony_ci
414d4afb5ceSopenharmony_ciint
415d4afb5ceSopenharmony_cilws_genrsa_hash_sign(struct lws_genrsa_ctx *ctx, const uint8_t *in,
416d4afb5ceSopenharmony_ci		       enum lws_genhash_types hash_type, uint8_t *sig,
417d4afb5ceSopenharmony_ci		       size_t sig_len)
418d4afb5ceSopenharmony_ci{
419d4afb5ceSopenharmony_ci	int n, h = (int)lws_gencrypto_mbedtls_hash_to_MD_TYPE(hash_type);
420d4afb5ceSopenharmony_ci
421d4afb5ceSopenharmony_ci	if (h < 0)
422d4afb5ceSopenharmony_ci		return -1;
423d4afb5ceSopenharmony_ci
424d4afb5ceSopenharmony_ci#if defined(LWS_HAVE_mbedtls_rsa_complete)
425d4afb5ceSopenharmony_ci	mbedtls_rsa_complete(ctx->ctx);
426d4afb5ceSopenharmony_ci#endif
427d4afb5ceSopenharmony_ci
428d4afb5ceSopenharmony_ci	/*
429d4afb5ceSopenharmony_ci	 * The "sig" buffer must be as large as the size of ctx->N
430d4afb5ceSopenharmony_ci	 * (eg. 128 bytes if RSA-1024 is used).
431d4afb5ceSopenharmony_ci	 */
432d4afb5ceSopenharmony_ci	if (sig_len < ctx->ctx->MBEDTLS_PRIVATE(len))
433d4afb5ceSopenharmony_ci		return -1;
434d4afb5ceSopenharmony_ci
435d4afb5ceSopenharmony_ci	switch(ctx->mode) {
436d4afb5ceSopenharmony_ci	case LGRSAM_PKCS1_1_5:
437d4afb5ceSopenharmony_ci		n = mbedtls_rsa_rsassa_pkcs1_v15_sign(ctx->ctx,
438d4afb5ceSopenharmony_ci						      mbedtls_ctr_drbg_random,
439d4afb5ceSopenharmony_ci						      &ctx->context->mcdc,
440d4afb5ceSopenharmony_ci#if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000
441d4afb5ceSopenharmony_ci						      MBEDTLS_RSA_PRIVATE,
442d4afb5ceSopenharmony_ci#endif
443d4afb5ceSopenharmony_ci						      (mbedtls_md_type_t)h,
444d4afb5ceSopenharmony_ci						      (unsigned int)lws_genhash_size(hash_type),
445d4afb5ceSopenharmony_ci						      in, sig);
446d4afb5ceSopenharmony_ci		break;
447d4afb5ceSopenharmony_ci	case LGRSAM_PKCS1_OAEP_PSS:
448d4afb5ceSopenharmony_ci		n = mbedtls_rsa_rsassa_pss_sign(ctx->ctx,
449d4afb5ceSopenharmony_ci						mbedtls_ctr_drbg_random,
450d4afb5ceSopenharmony_ci						&ctx->context->mcdc,
451d4afb5ceSopenharmony_ci#if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000
452d4afb5ceSopenharmony_ci						MBEDTLS_RSA_PRIVATE,
453d4afb5ceSopenharmony_ci#endif
454d4afb5ceSopenharmony_ci						(mbedtls_md_type_t)h,
455d4afb5ceSopenharmony_ci						(unsigned int)lws_genhash_size(hash_type),
456d4afb5ceSopenharmony_ci						in, sig);
457d4afb5ceSopenharmony_ci		break;
458d4afb5ceSopenharmony_ci	default:
459d4afb5ceSopenharmony_ci		return -1;
460d4afb5ceSopenharmony_ci	}
461d4afb5ceSopenharmony_ci
462d4afb5ceSopenharmony_ci	if (n < 0) {
463d4afb5ceSopenharmony_ci		lwsl_notice("%s: -0x%x\n", __func__, -n);
464d4afb5ceSopenharmony_ci
465d4afb5ceSopenharmony_ci		return -1;
466d4afb5ceSopenharmony_ci	}
467d4afb5ceSopenharmony_ci
468d4afb5ceSopenharmony_ci	return (int)ctx->ctx->MBEDTLS_PRIVATE(len);
469d4afb5ceSopenharmony_ci}
470d4afb5ceSopenharmony_ci
471d4afb5ceSopenharmony_ciint
472d4afb5ceSopenharmony_cilws_genrsa_render_pkey_asn1(struct lws_genrsa_ctx *ctx, int _private,
473d4afb5ceSopenharmony_ci			    uint8_t *pkey_asn1, size_t pkey_asn1_len)
474d4afb5ceSopenharmony_ci{
475d4afb5ceSopenharmony_ci	uint8_t *p = pkey_asn1, *totlen, *end = pkey_asn1 + pkey_asn1_len - 1;
476d4afb5ceSopenharmony_ci	mbedtls_mpi *mpi[LWS_GENCRYPTO_RSA_KEYEL_COUNT] = {
477d4afb5ceSopenharmony_ci		&ctx->ctx->MBEDTLS_PRIVATE(N),
478d4afb5ceSopenharmony_ci		&ctx->ctx->MBEDTLS_PRIVATE(E),
479d4afb5ceSopenharmony_ci		&ctx->ctx->MBEDTLS_PRIVATE(D),
480d4afb5ceSopenharmony_ci		&ctx->ctx->MBEDTLS_PRIVATE(P),
481d4afb5ceSopenharmony_ci		&ctx->ctx->MBEDTLS_PRIVATE(Q),
482d4afb5ceSopenharmony_ci		&ctx->ctx->MBEDTLS_PRIVATE(DP),
483d4afb5ceSopenharmony_ci		&ctx->ctx->MBEDTLS_PRIVATE(DQ),
484d4afb5ceSopenharmony_ci		&ctx->ctx->MBEDTLS_PRIVATE(QP),
485d4afb5ceSopenharmony_ci	};
486d4afb5ceSopenharmony_ci	int n;
487d4afb5ceSopenharmony_ci
488d4afb5ceSopenharmony_ci	/* 30 82  - sequence
489d4afb5ceSopenharmony_ci	 *   09 29  <-- length(0x0929) less 4 bytes
490d4afb5ceSopenharmony_ci	 * 02 01 <- length (1)
491d4afb5ceSopenharmony_ci	 *  00
492d4afb5ceSopenharmony_ci	 * 02 82
493d4afb5ceSopenharmony_ci	 *  02 01 <- length (513)  N
494d4afb5ceSopenharmony_ci	 *  ...
495d4afb5ceSopenharmony_ci	 *
496d4afb5ceSopenharmony_ci	 *  02 03 <- length (3) E
497d4afb5ceSopenharmony_ci	 *    01 00 01
498d4afb5ceSopenharmony_ci	 *
499d4afb5ceSopenharmony_ci	 * 02 82
500d4afb5ceSopenharmony_ci	 *   02 00 <- length (512) D P Q EXP1 EXP2 COEFF
501d4afb5ceSopenharmony_ci	 *
502d4afb5ceSopenharmony_ci	 *  */
503d4afb5ceSopenharmony_ci
504d4afb5ceSopenharmony_ci	*p++ = 0x30;
505d4afb5ceSopenharmony_ci	*p++ = 0x82;
506d4afb5ceSopenharmony_ci	totlen = p;
507d4afb5ceSopenharmony_ci	p += 2;
508d4afb5ceSopenharmony_ci
509d4afb5ceSopenharmony_ci	*p++ = 0x02;
510d4afb5ceSopenharmony_ci	*p++ = 0x01;
511d4afb5ceSopenharmony_ci	*p++ = 0x00;
512d4afb5ceSopenharmony_ci
513d4afb5ceSopenharmony_ci	for (n = 0; n < LWS_GENCRYPTO_RSA_KEYEL_COUNT; n++) {
514d4afb5ceSopenharmony_ci		int m = (int)mbedtls_mpi_size(mpi[n]);
515d4afb5ceSopenharmony_ci		uint8_t *elen;
516d4afb5ceSopenharmony_ci
517d4afb5ceSopenharmony_ci		*p++ = 0x02;
518d4afb5ceSopenharmony_ci		elen = p;
519d4afb5ceSopenharmony_ci		if (m < 0x7f)
520d4afb5ceSopenharmony_ci			*p++ = (uint8_t)m;
521d4afb5ceSopenharmony_ci		else {
522d4afb5ceSopenharmony_ci			*p++ = 0x82;
523d4afb5ceSopenharmony_ci			*p++ = (uint8_t)(m >> 8);
524d4afb5ceSopenharmony_ci			*p++ = (uint8_t)(m & 0xff);
525d4afb5ceSopenharmony_ci		}
526d4afb5ceSopenharmony_ci
527d4afb5ceSopenharmony_ci		if (p + m > end)
528d4afb5ceSopenharmony_ci			return -1;
529d4afb5ceSopenharmony_ci
530d4afb5ceSopenharmony_ci		if (mbedtls_mpi_write_binary(mpi[n], p, (unsigned int)m))
531d4afb5ceSopenharmony_ci			return -1;
532d4afb5ceSopenharmony_ci		if (p[0] & 0x80) {
533d4afb5ceSopenharmony_ci			p[0] = 0x00;
534d4afb5ceSopenharmony_ci			if (mbedtls_mpi_write_binary(mpi[n], &p[1], (unsigned int)m))
535d4afb5ceSopenharmony_ci				return -1;
536d4afb5ceSopenharmony_ci			m++;
537d4afb5ceSopenharmony_ci		}
538d4afb5ceSopenharmony_ci		if (m < 0x7f)
539d4afb5ceSopenharmony_ci			*elen = (uint8_t)m;
540d4afb5ceSopenharmony_ci		else {
541d4afb5ceSopenharmony_ci			*elen++ = 0x82;
542d4afb5ceSopenharmony_ci			*elen++ = (uint8_t)(m >> 8);
543d4afb5ceSopenharmony_ci			*elen = (uint8_t)(m & 0xff);
544d4afb5ceSopenharmony_ci		}
545d4afb5ceSopenharmony_ci		p += m;
546d4afb5ceSopenharmony_ci	}
547d4afb5ceSopenharmony_ci
548d4afb5ceSopenharmony_ci	n = lws_ptr_diff(p, pkey_asn1);
549d4afb5ceSopenharmony_ci
550d4afb5ceSopenharmony_ci	*totlen++ = (uint8_t)((n - 4) >> 8);
551d4afb5ceSopenharmony_ci	*totlen = (uint8_t)((n - 4) & 0xff);
552d4afb5ceSopenharmony_ci
553d4afb5ceSopenharmony_ci	return n;
554d4afb5ceSopenharmony_ci}
555d4afb5ceSopenharmony_ci
556d4afb5ceSopenharmony_civoid
557d4afb5ceSopenharmony_cilws_genrsa_destroy(struct lws_genrsa_ctx *ctx)
558d4afb5ceSopenharmony_ci{
559d4afb5ceSopenharmony_ci	if (!ctx->ctx)
560d4afb5ceSopenharmony_ci		return;
561d4afb5ceSopenharmony_ci	mbedtls_rsa_free(ctx->ctx);
562d4afb5ceSopenharmony_ci	lws_free(ctx->ctx);
563d4afb5ceSopenharmony_ci	ctx->ctx = NULL;
564d4afb5ceSopenharmony_ci}
565