1 /*
2 * libwebsockets - small server side websockets and web server implementation
3 *
4 * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 */
24
25 #include "private-lib-core.h"
26 #include "private-lib-tls-mbedtls.h"
27 #include <mbedtls/oid.h>
28
29 #if defined(LWS_PLAT_OPTEE) || defined(OPTEE_DEV_KIT)
30 struct tm {
31 int tm_sec; // seconds [0,61]
32 int tm_min; // minutes [0,59]
33 int tm_hour; // hour [0,23]
34 int tm_mday; // day of month [1,31]
35 int tm_mon; // month of year [0,11]
36 int tm_year; // years since 1900
37 int tm_wday; // day of week [0,6] (Sunday = 0)
38 int tm_yday; // day of year [0,365]
39 int tm_isdst; // daylight savings flag
40 };
mktime(struct tm * t)41 time_t mktime(struct tm *t)
42 {
43 return (time_t)0;
44 }
45 #endif
46
47 static time_t
lws_tls_mbedtls_time_to_unix(mbedtls_x509_time * xtime)48 lws_tls_mbedtls_time_to_unix(mbedtls_x509_time *xtime)
49 {
50 struct tm t;
51
52 if (!xtime || !xtime->year || xtime->year < 0)
53 return (time_t)(long long)-1;
54
55 memset(&t, 0, sizeof(t));
56
57 t.tm_year = xtime->year - 1900;
58 t.tm_mon = xtime->mon - 1; /* mbedtls months are 1+, tm are 0+ */
59 t.tm_mday = xtime->day - 1; /* mbedtls days are 1+, tm are 0+ */
60 t.tm_hour = xtime->hour;
61 t.tm_min = xtime->min;
62 t.tm_sec = xtime->sec;
63 t.tm_isdst = -1;
64
65 return mktime(&t);
66 }
67
68 static int
lws_tls_mbedtls_get_x509_name(mbedtls_x509_name * name,union lws_tls_cert_info_results * buf,size_t len)69 lws_tls_mbedtls_get_x509_name(mbedtls_x509_name *name,
70 union lws_tls_cert_info_results *buf, size_t len)
71 {
72 while (name) {
73 if (MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &name->oid)) {
74 name = name->next;
75 continue;
76 }
77
78 if (len - 1 < name->val.len)
79 return -1;
80
81 memcpy(&buf->ns.name[0], name->val.p, name->val.len);
82 buf->ns.name[name->val.len] = '\0';
83 buf->ns.len = name->val.len;
84
85 return 0;
86 }
87
88 return -1;
89 }
90
91 static int
lws_tls_mbedtls_cert_info(mbedtls_x509_crt * x509,enum lws_tls_cert_info type,union lws_tls_cert_info_results * buf,size_t len)92 lws_tls_mbedtls_cert_info(mbedtls_x509_crt *x509, enum lws_tls_cert_info type,
93 union lws_tls_cert_info_results *buf, size_t len)
94 {
95 if (!x509)
96 return -1;
97
98 switch (type) {
99 case LWS_TLS_CERT_INFO_VALIDITY_FROM:
100 buf->time = lws_tls_mbedtls_time_to_unix(&x509->valid_from);
101 if (buf->time == (time_t)(long long)-1)
102 return -1;
103 break;
104
105 case LWS_TLS_CERT_INFO_VALIDITY_TO:
106 buf->time = lws_tls_mbedtls_time_to_unix(&x509->valid_to);
107 if (buf->time == (time_t)(long long)-1)
108 return -1;
109 break;
110
111 case LWS_TLS_CERT_INFO_COMMON_NAME:
112 return lws_tls_mbedtls_get_x509_name(&x509->subject, buf, len);
113
114 case LWS_TLS_CERT_INFO_ISSUER_NAME:
115 return lws_tls_mbedtls_get_x509_name(&x509->issuer, buf, len);
116
117 case LWS_TLS_CERT_INFO_USAGE:
118 buf->usage = x509->key_usage;
119 break;
120
121 case LWS_TLS_CERT_INFO_OPAQUE_PUBLIC_KEY:
122 {
123 char *p = buf->ns.name;
124 size_t r = len, u;
125
126 switch (mbedtls_pk_get_type(&x509->pk)) {
127 case MBEDTLS_PK_RSA:
128 {
129 mbedtls_rsa_context *rsa = mbedtls_pk_rsa(x509->pk);
130
131 if (mbedtls_mpi_write_string(&rsa->N, 16, p, r, &u))
132 return -1;
133 r -= u;
134 p += u;
135 if (mbedtls_mpi_write_string(&rsa->E, 16, p, r, &u))
136 return -1;
137
138 p += u;
139 buf->ns.len = lws_ptr_diff(p, buf->ns.name);
140 break;
141 }
142 case MBEDTLS_PK_ECKEY:
143 {
144 mbedtls_ecp_keypair *ecp = mbedtls_pk_ec(x509->pk);
145
146 if (mbedtls_mpi_write_string(&ecp->Q.X, 16, p, r, &u))
147 return -1;
148 r -= u;
149 p += u;
150 if (mbedtls_mpi_write_string(&ecp->Q.Y, 16, p, r, &u))
151 return -1;
152 r -= u;
153 p += u;
154 if (mbedtls_mpi_write_string(&ecp->Q.Z, 16, p, r, &u))
155 return -1;
156 p += u;
157 buf->ns.len = lws_ptr_diff(p, buf->ns.name);
158 break;
159 }
160 default:
161 lwsl_notice("%s: x509 has unsupported pubkey type %d\n",
162 __func__,
163 mbedtls_pk_get_type(&x509->pk));
164
165 return -1;
166 }
167 break;
168 }
169
170 default:
171 return -1;
172 }
173
174 return 0;
175 }
176
177 #if defined(LWS_WITH_NETWORK)
178 int
lws_tls_vhost_cert_info(struct lws_vhost * vhost,enum lws_tls_cert_info type,union lws_tls_cert_info_results * buf,size_t len)179 lws_tls_vhost_cert_info(struct lws_vhost *vhost, enum lws_tls_cert_info type,
180 union lws_tls_cert_info_results *buf, size_t len)
181 {
182 mbedtls_x509_crt *x509;
183
184 x509 = ssl_ctx_get_mbedtls_x509_crt(vhost->tls.ssl_ctx);
185
186 return lws_tls_mbedtls_cert_info(x509, type, buf, len);
187 }
188
189 int
lws_tls_peer_cert_info(struct lws * wsi,enum lws_tls_cert_info type,union lws_tls_cert_info_results * buf,size_t len)190 lws_tls_peer_cert_info(struct lws *wsi, enum lws_tls_cert_info type,
191 union lws_tls_cert_info_results *buf, size_t len)
192 {
193 mbedtls_x509_crt *x509;
194
195 wsi = lws_get_network_wsi(wsi);
196
197 x509 = ssl_get_peer_mbedtls_x509_crt(wsi->tls.ssl);
198
199 if (!x509)
200 return -1;
201
202 switch (type) {
203 case LWS_TLS_CERT_INFO_VERIFIED:
204 buf->verified = SSL_get_verify_result(wsi->tls.ssl) == X509_V_OK;
205 return 0;
206 default:
207 return lws_tls_mbedtls_cert_info(x509, type, buf, len);
208 }
209
210 return -1;
211 }
212 #endif
213
214 int
lws_x509_info(struct lws_x509_cert * x509,enum lws_tls_cert_info type,union lws_tls_cert_info_results * buf,size_t len)215 lws_x509_info(struct lws_x509_cert *x509, enum lws_tls_cert_info type,
216 union lws_tls_cert_info_results *buf, size_t len)
217 {
218 return lws_tls_mbedtls_cert_info(&x509->cert, type, buf, len);
219 }
220
221 int
lws_x509_create(struct lws_x509_cert ** x509)222 lws_x509_create(struct lws_x509_cert **x509)
223 {
224 *x509 = lws_malloc(sizeof(**x509), __func__);
225
226 return !(*x509);
227 }
228
229 /*
230 * Parse one DER-encoded or one or more concatenated PEM-encoded certificates
231 * and add them to the chained list.
232 */
233
234 int
lws_x509_parse_from_pem(struct lws_x509_cert * x509,const void * pem,size_t len)235 lws_x509_parse_from_pem(struct lws_x509_cert *x509, const void *pem, size_t len)
236 {
237 int ret;
238
239 mbedtls_x509_crt_init(&x509->cert);
240
241 ret = mbedtls_x509_crt_parse(&x509->cert, pem, len);
242 if (ret) {
243 mbedtls_x509_crt_free(&x509->cert);
244 lwsl_err("%s: unable to parse PEM cert: -0x%x\n",
245 __func__, -ret);
246
247 return -1;
248 }
249
250 return 0;
251 }
252
253 int
lws_x509_verify(struct lws_x509_cert * x509,struct lws_x509_cert * trusted,const char * common_name)254 lws_x509_verify(struct lws_x509_cert *x509, struct lws_x509_cert *trusted,
255 const char *common_name)
256 {
257 uint32_t flags = 0;
258 int ret;
259
260 ret = mbedtls_x509_crt_verify_with_profile(&x509->cert, &trusted->cert,
261 NULL,
262 &mbedtls_x509_crt_profile_next,
263 common_name, &flags, NULL,
264 NULL);
265
266 if (ret) {
267 lwsl_err("%s: unable to parse PEM cert: -0x%x\n",
268 __func__, -ret);
269
270 return -1;
271 }
272
273 return 0;
274 }
275
276 #if defined(LWS_WITH_JOSE)
277
278 int
lws_x509_public_to_jwk(struct lws_jwk * jwk,struct lws_x509_cert * x509,const char * curves,int rsa_min_bits)279 lws_x509_public_to_jwk(struct lws_jwk *jwk, struct lws_x509_cert *x509,
280 const char *curves, int rsa_min_bits)
281 {
282 int kt = mbedtls_pk_get_type(&x509->cert.pk), n, count = 0, ret = -1;
283 mbedtls_rsa_context *rsactx;
284 mbedtls_ecp_keypair *ecpctx;
285 mbedtls_mpi *mpi[LWS_GENCRYPTO_RSA_KEYEL_COUNT];
286
287 memset(jwk, 0, sizeof(*jwk));
288
289 switch (kt) {
290 case MBEDTLS_PK_RSA:
291 lwsl_notice("%s: RSA key\n", __func__);
292 jwk->kty = LWS_GENCRYPTO_KTY_RSA;
293 rsactx = mbedtls_pk_rsa(x509->cert.pk);
294
295 mpi[LWS_GENCRYPTO_RSA_KEYEL_E] = &rsactx->E;
296 mpi[LWS_GENCRYPTO_RSA_KEYEL_N] = &rsactx->N;
297 mpi[LWS_GENCRYPTO_RSA_KEYEL_D] = &rsactx->D;
298 mpi[LWS_GENCRYPTO_RSA_KEYEL_P] = &rsactx->P;
299 mpi[LWS_GENCRYPTO_RSA_KEYEL_Q] = &rsactx->Q;
300 mpi[LWS_GENCRYPTO_RSA_KEYEL_DP] = &rsactx->DP;
301 mpi[LWS_GENCRYPTO_RSA_KEYEL_DQ] = &rsactx->DQ;
302 mpi[LWS_GENCRYPTO_RSA_KEYEL_QI] = &rsactx->QP;
303
304 count = LWS_GENCRYPTO_RSA_KEYEL_COUNT;
305 n = LWS_GENCRYPTO_RSA_KEYEL_E;
306 break;
307
308 case MBEDTLS_PK_ECKEY:
309 lwsl_notice("%s: EC key\n", __func__);
310 jwk->kty = LWS_GENCRYPTO_KTY_EC;
311 ecpctx = mbedtls_pk_ec(x509->cert.pk);
312 mpi[LWS_GENCRYPTO_EC_KEYEL_X] = &ecpctx->Q.X;
313 mpi[LWS_GENCRYPTO_EC_KEYEL_D] = &ecpctx->d;
314 mpi[LWS_GENCRYPTO_EC_KEYEL_Y] = &ecpctx->Q.Y;
315
316 if (lws_genec_confirm_curve_allowed_by_tls_id(curves,
317 ecpctx->grp.id, jwk))
318 /* already logged */
319 goto bail;
320
321 count = LWS_GENCRYPTO_EC_KEYEL_COUNT;
322 n = LWS_GENCRYPTO_EC_KEYEL_X;
323 break;
324 default:
325 lwsl_err("%s: key type %d not supported\n", __func__, kt);
326
327 return -1;
328 }
329
330 for (; n < count; n++) {
331 if (!mbedtls_mpi_size(mpi[n]))
332 continue;
333
334 jwk->e[n].buf = lws_malloc(mbedtls_mpi_size(mpi[n]), "certjwk");
335 if (!jwk->e[n].buf)
336 goto bail;
337 jwk->e[n].len = mbedtls_mpi_size(mpi[n]);
338 mbedtls_mpi_write_binary(mpi[n], jwk->e[n].buf, jwk->e[n].len);
339 }
340
341 ret = 0;
342
343 bail:
344 /* jwk destroy will clean up partials */
345 if (ret)
346 lws_jwk_destroy(jwk);
347
348 return ret;
349 }
350
351 int
lws_x509_jwk_privkey_pem(struct lws_jwk * jwk,void * pem,size_t len,const char * passphrase)352 lws_x509_jwk_privkey_pem(struct lws_jwk *jwk, void *pem, size_t len,
353 const char *passphrase)
354 {
355 mbedtls_rsa_context *rsactx;
356 mbedtls_ecp_keypair *ecpctx;
357 mbedtls_pk_context pk;
358 mbedtls_mpi *mpi[LWS_GENCRYPTO_RSA_KEYEL_COUNT];
359 int n, ret = -1, count = 0;
360
361 mbedtls_pk_init(&pk);
362
363 n = 0;
364 if (passphrase)
365 n = strlen(passphrase);
366 n = mbedtls_pk_parse_key(&pk, pem, len, (uint8_t *)passphrase, n);
367 if (n) {
368 lwsl_err("%s: parse PEM key failed: -0x%x\n", __func__, -n);
369
370 return -1;
371 }
372
373 /* the incoming private key type */
374 switch (mbedtls_pk_get_type(&pk)) {
375 case MBEDTLS_PK_RSA:
376 if (jwk->kty != LWS_GENCRYPTO_KTY_RSA) {
377 lwsl_err("%s: RSA privkey, non-RSA jwk\n", __func__);
378 goto bail;
379 }
380 rsactx = mbedtls_pk_rsa(pk);
381 mpi[LWS_GENCRYPTO_RSA_KEYEL_D] = &rsactx->D;
382 mpi[LWS_GENCRYPTO_RSA_KEYEL_P] = &rsactx->P;
383 mpi[LWS_GENCRYPTO_RSA_KEYEL_Q] = &rsactx->Q;
384 n = LWS_GENCRYPTO_RSA_KEYEL_D;
385 count = LWS_GENCRYPTO_RSA_KEYEL_Q + 1;
386 break;
387 case MBEDTLS_PK_ECKEY:
388 if (jwk->kty != LWS_GENCRYPTO_KTY_EC) {
389 lwsl_err("%s: EC privkey, non-EC jwk\n", __func__);
390 goto bail;
391 }
392 ecpctx = mbedtls_pk_ec(pk);
393 mpi[LWS_GENCRYPTO_EC_KEYEL_D] = &ecpctx->d;
394 n = LWS_GENCRYPTO_EC_KEYEL_D;
395 count = n + 1;
396 break;
397 default:
398 lwsl_err("%s: unusable key type %d\n", __func__,
399 mbedtls_pk_get_type(&pk));
400 goto bail;
401 }
402
403 for (; n < count; n++) {
404 if (!mbedtls_mpi_size(mpi[n])) {
405 lwsl_err("%s: empty privkey\n", __func__);
406 goto bail;
407 }
408
409 jwk->e[n].buf = lws_malloc(mbedtls_mpi_size(mpi[n]), "certjwk");
410 if (!jwk->e[n].buf)
411 goto bail;
412 jwk->e[n].len = mbedtls_mpi_size(mpi[n]);
413 mbedtls_mpi_write_binary(mpi[n], jwk->e[n].buf, jwk->e[n].len);
414 }
415
416 ret = 0;
417
418 bail:
419 mbedtls_pk_free(&pk);
420
421 return ret;
422 }
423 #endif
424
425 void
lws_x509_destroy(struct lws_x509_cert ** x509)426 lws_x509_destroy(struct lws_x509_cert **x509)
427 {
428 if (!*x509)
429 return;
430
431 mbedtls_x509_crt_free(&(*x509)->cert);
432
433 lws_free_set_NULL(*x509);
434 }
435