1/* 2 * libwebsockets - small server side websockets and web server implementation 3 * 4 * Copyright (C) 2010 - 2021 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 28#if defined(LWS_WITH_TLS_JIT_TRUST) 29 30/* 31 * We get called for each peer certificate that was provided in turn. 32 * 33 * Our job is just to collect the AKID and SKIDs into ssl->kid_chain, and walk 34 * later at verification result time if it failed. 35 * 36 * None of these should be trusted, even if a misconfigured server sends us 37 * his root CA. 38 */ 39 40static int 41lws_mbedtls_client_verify_callback(SSL *ssl, mbedtls_x509_crt *x509) 42{ 43 union lws_tls_cert_info_results ci; 44 45 /* we reached the max we can hold? */ 46 47 if (ssl->kid_chain.count == LWS_ARRAY_SIZE(ssl->kid_chain.akid)) 48 return 0; 49 50 /* if not, stash the SKID and AKID into the next kid slot */ 51 52 if (!lws_tls_mbedtls_cert_info(x509, LWS_TLS_CERT_INFO_SUBJECT_KEY_ID, 53 &ci, 0)) 54 lws_tls_kid_copy(&ci, 55 &ssl->kid_chain.skid[ssl->kid_chain.count]); 56 57 if (!lws_tls_mbedtls_cert_info(x509, LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID, 58 &ci, 0)) 59 lws_tls_kid_copy(&ci, 60 &ssl->kid_chain.akid[ssl->kid_chain.count]); 61 62 ssl->kid_chain.count++; 63 64 // lwsl_notice("%s: %u\n", __func__, ssl->kid_chain.count); 65 66 return 0; 67} 68 69#endif 70 71int 72lws_ssl_client_bio_create(struct lws *wsi) 73{ 74 char hostname[128], *p; 75 const char *alpn_comma = wsi->a.context->tls.alpn_default; 76 struct alpn_ctx protos; 77 int fl = SSL_VERIFY_PEER; 78 79 if (wsi->stash) 80 lws_strncpy(hostname, wsi->stash->cis[CIS_HOST], sizeof(hostname)); 81 else 82 if (lws_hdr_copy(wsi, hostname, sizeof(hostname), 83 _WSI_TOKEN_CLIENT_HOST) <= 0) { 84 lwsl_err("%s: Unable to get hostname\n", __func__); 85 86 return -1; 87 } 88 89 /* 90 * remove any :port part on the hostname... necessary for network 91 * connection but typical certificates do not contain it 92 */ 93 p = hostname; 94 while (*p) { 95 if (*p == ':') { 96 *p = '\0'; 97 break; 98 } 99 p++; 100 } 101 102 wsi->tls.ssl = SSL_new(wsi->a.vhost->tls.ssl_client_ctx); 103 if (!wsi->tls.ssl) { 104 lwsl_info("%s: SSL_new() failed\n", __func__); 105 return -1; 106 } 107 108#if defined(LWS_WITH_TLS_SESSIONS) 109 if (!(wsi->a.vhost->options & LWS_SERVER_OPTION_DISABLE_TLS_SESSION_CACHE)) 110 lws_tls_reuse_session(wsi); 111#endif 112 113 if (wsi->a.vhost->tls.ssl_info_event_mask) 114 SSL_set_info_callback(wsi->tls.ssl, lws_ssl_info_callback); 115 116 if (!(wsi->tls.use_ssl & LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK)) { 117 X509_VERIFY_PARAM *param = SSL_get0_param(wsi->tls.ssl); 118 /* Enable automatic hostname checks */ 119 // X509_VERIFY_PARAM_set_hostflags(param, 120 // X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); 121 lwsl_info("%s: setting hostname %s\n", __func__, hostname); 122 if (X509_VERIFY_PARAM_set1_host(param, hostname, 0) != 1) 123 return -1; 124 } 125 126 if (wsi->a.vhost->tls.alpn) 127 alpn_comma = wsi->a.vhost->tls.alpn; 128 129 if (wsi->stash) { 130 lws_strncpy(hostname, wsi->stash->cis[CIS_HOST], 131 sizeof(hostname)); 132 if (wsi->stash->cis[CIS_ALPN]) 133 alpn_comma = wsi->stash->cis[CIS_ALPN]; 134 } else { 135 if (lws_hdr_copy(wsi, hostname, sizeof(hostname), 136 _WSI_TOKEN_CLIENT_ALPN) > 0) 137 alpn_comma = hostname; 138 } 139 140 protos.len = (uint8_t)lws_alpn_comma_to_openssl(alpn_comma, protos.data, 141 sizeof(protos.data) - 1); 142 143 lwsl_info("%s: %s: client conn sending ALPN list '%s' (protos.len %d)\n", 144 __func__, lws_wsi_tag(wsi), alpn_comma, protos.len); 145 146 /* with mbedtls, protos is not pointed to after exit from this call */ 147 SSL_set_alpn_select_cb(wsi->tls.ssl, &protos); 148 149 if (wsi->flags & LCCSCF_ALLOW_SELFSIGNED) { 150 lwsl_notice("%s: allowing selfsigned\n", __func__); 151 fl = SSL_VERIFY_FAIL_IF_NO_PEER_CERT; 152 } 153 154 if (wsi->flags & LCCSCF_ALLOW_INSECURE) 155 fl = SSL_VERIFY_NONE; 156 157 /* 158 * use server name indication (SNI), if supported, 159 * when establishing connection 160 */ 161#if defined(LWS_WITH_TLS_JIT_TRUST) 162 SSL_set_verify(wsi->tls.ssl, SSL_VERIFY_PEER, 163 lws_mbedtls_client_verify_callback); 164 (void)fl; 165#else 166 SSL_set_verify(wsi->tls.ssl, fl, NULL); 167#endif 168 169 SSL_set_fd(wsi->tls.ssl, (int)wsi->desc.sockfd); 170 171 if (wsi->sys_tls_client_cert) { 172 lws_system_blob_t *b = lws_system_get_blob(wsi->a.context, 173 LWS_SYSBLOB_TYPE_CLIENT_CERT_DER, 174 wsi->sys_tls_client_cert - 1); 175 const uint8_t *pem_data = NULL; 176 uint8_t *data = NULL; 177 lws_filepos_t flen; 178 size_t size; 179 int err = 0; 180 181 if (!b) 182 goto no_client_cert; 183 184 /* 185 * Set up the per-connection client cert 186 */ 187 188 size = lws_system_blob_get_size(b); 189 if (!size) 190 goto no_client_cert; 191 192 if (lws_system_blob_get_single_ptr(b, &pem_data)) 193 goto no_client_cert; 194 195 if (lws_tls_alloc_pem_to_der_file(wsi->a.context, NULL, 196 (const char *)pem_data, size, 197 &data, &flen)) 198 goto no_client_cert; 199 size = (size_t) flen; 200 201 err = SSL_use_certificate_ASN1(wsi->tls.ssl, data, (int)size); 202 lws_free_set_NULL(data); 203 if (err != 1) 204 goto no_client_cert; 205 206 b = lws_system_get_blob(wsi->a.context, 207 LWS_SYSBLOB_TYPE_CLIENT_KEY_DER, 208 wsi->sys_tls_client_cert - 1); 209 if (!b) 210 goto no_client_cert; 211 size = lws_system_blob_get_size(b); 212 if (!size) 213 goto no_client_cert; 214 215 if (lws_system_blob_get_single_ptr(b, &pem_data)) 216 goto no_client_cert; 217 218 if (lws_tls_alloc_pem_to_der_file(wsi->a.context, NULL, 219 (const char *)pem_data, size, 220 &data, &flen)) 221 goto no_client_cert; 222 size = (size_t) flen; 223 224 err = SSL_use_PrivateKey_ASN1(0, wsi->tls.ssl, data, (int)size); 225 lws_free_set_NULL(data); 226 if (err != 1) 227 goto no_client_cert; 228 229 /* no wrapper api for check key */ 230 231 lwsl_notice("%s: set system client cert %u\n", __func__, 232 wsi->sys_tls_client_cert - 1); 233 } 234 235 return 0; 236 237no_client_cert: 238 lwsl_err("%s: unable to set up system client cert %d\n", __func__, 239 wsi->sys_tls_client_cert - 1); 240 241 return 1; 242} 243 244int ERR_get_error(void) 245{ 246 return 0; 247} 248 249enum lws_ssl_capable_status 250lws_tls_client_connect(struct lws *wsi, char *errbuf, size_t elen) 251{ 252 int m, n = SSL_connect(wsi->tls.ssl), en; 253 254 if (n == 1) { 255 lws_tls_server_conn_alpn(wsi); 256#if defined(LWS_WITH_TLS_SESSIONS) 257 lws_tls_session_new_mbedtls(wsi); 258#endif 259 lwsl_info("%s: client connect OK\n", __func__); 260 return LWS_SSL_CAPABLE_DONE; 261 } 262 263 en = (int)LWS_ERRNO; 264 m = SSL_get_error(wsi->tls.ssl, n); 265 266 if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->tls.ssl)) 267 return LWS_SSL_CAPABLE_MORE_SERVICE_READ; 268 269 if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl)) 270 return LWS_SSL_CAPABLE_MORE_SERVICE_WRITE; 271 272 if (!n) /* we don't know what he wants, but he says to retry */ 273 return LWS_SSL_CAPABLE_MORE_SERVICE; 274 275 if (m == SSL_ERROR_SYSCALL && !en && n >= 0) /* otherwise we miss explicit failures and spin 276 * in hs state 17 until timeout... */ 277 return LWS_SSL_CAPABLE_MORE_SERVICE; 278 279 lws_snprintf(errbuf, elen, "mbedtls connect %d %d %d", n, m, en); 280 281 return LWS_SSL_CAPABLE_ERROR; 282} 283 284int 285lws_tls_client_confirm_peer_cert(struct lws *wsi, char *ebuf, size_t ebuf_len) 286{ 287 int n; 288 unsigned int avoid = 0; 289 X509 *peer = SSL_get_peer_certificate(wsi->tls.ssl); 290 struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; 291 const char *type = ""; 292 char *sb = (char *)&pt->serv_buf[0]; 293 294 if (!peer) { 295#if defined(LWS_WITH_SYS_METRICS) 296 lws_metrics_hist_bump_describe_wsi(wsi, lws_metrics_priv_to_pub( 297 wsi->a.context->mth_conn_failures), 298 "tls=\"nocert\""); 299#endif 300 lwsl_info("peer did not provide cert\n"); 301 lws_snprintf(ebuf, ebuf_len, "no peer cert"); 302 303 return -1; 304 } 305 306 n = (int)SSL_get_verify_result(wsi->tls.ssl); 307 lwsl_debug("get_verify says %d\n", n); 308 309 switch (n) { 310 case X509_V_OK: 311 return 0; 312 313 case X509_V_ERR_HOSTNAME_MISMATCH: 314 type = "hostname"; 315 avoid = LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK; 316 break; 317 318 case X509_V_ERR_INVALID_CA: 319 type = "invalidca"; 320 avoid = LCCSCF_ALLOW_SELFSIGNED; 321 break; 322 323 case X509_V_ERR_CERT_NOT_YET_VALID: 324 type = "notyetvalid"; 325 avoid = LCCSCF_ALLOW_EXPIRED; 326 break; 327 328 case X509_V_ERR_CERT_HAS_EXPIRED: 329 type = "expired"; 330 avoid = LCCSCF_ALLOW_EXPIRED; 331 break; 332 } 333 334 lwsl_info("%s: cert problem: %s\n", __func__, type); 335#if defined(LWS_WITH_SYS_METRICS) 336 { 337 char buckname[64]; 338 lws_snprintf(buckname, sizeof(buckname), "tls=\"%s\"", type); 339 lws_metrics_hist_bump_describe_wsi(wsi, 340 lws_metrics_priv_to_pub(wsi->a.context->mth_conn_failures), 341 buckname); 342 } 343#endif 344 if (wsi->tls.use_ssl & avoid) { 345 lwsl_info("%s: allowing anyway\n", __func__); 346 347 return 0; 348 } 349 350#if defined(LWS_WITH_TLS_JIT_TRUST) 351 if (n == X509_V_ERR_INVALID_CA) 352 lws_tls_jit_trust_sort_kids(wsi, &wsi->tls.ssl->kid_chain); 353#endif 354 lws_snprintf(ebuf, ebuf_len, 355 "server's cert didn't look good, %s (use_ssl 0x%x) X509_V_ERR = %d: %s\n", 356 type, (unsigned int)wsi->tls.use_ssl, n, 357 ERR_error_string((unsigned long)n, sb)); 358 359 lwsl_info("%s\n", ebuf); 360 361 lws_tls_err_describe_clear(); 362 363 return -1; 364} 365 366int 367lws_tls_client_create_vhost_context(struct lws_vhost *vh, 368 const struct lws_context_creation_info *info, 369 const char *cipher_list, 370 const char *ca_filepath, 371 const void *ca_mem, 372 unsigned int ca_mem_len, 373 const char *cert_filepath, 374 const void *cert_mem, 375 unsigned int cert_mem_len, 376 const char *private_key_filepath, 377 const void *key_mem, 378 unsigned int key_mem_len 379 ) 380{ 381 X509 *d2i_X509(X509 **cert, const unsigned char *buffer, long len); 382 SSL_METHOD *method = (SSL_METHOD *)TLS_client_method(); 383 unsigned long error; 384 int n; 385 386#if defined(LWS_WITH_TLS_SESSIONS) 387 vh->tls_session_cache_max = info->tls_session_cache_max ? 388 info->tls_session_cache_max : 10; 389 lws_tls_session_cache(vh, info->tls_session_timeout); 390#endif 391 392 if (!method) { 393 error = (unsigned long)ERR_get_error(); 394 lwsl_err("problem creating ssl method %lu: %s\n", 395 error, ERR_error_string(error, 396 (char *)vh->context->pt[0].serv_buf)); 397 return 1; 398 } 399 /* create context */ 400 vh->tls.ssl_client_ctx = SSL_CTX_new(method, &vh->context->mcdc); 401 if (!vh->tls.ssl_client_ctx) { 402 error = (unsigned long)ERR_get_error(); 403 lwsl_err("problem creating ssl context %lu: %s\n", 404 error, ERR_error_string(error, 405 (char *)vh->context->pt[0].serv_buf)); 406 return 1; 407 } 408 409 if (!ca_filepath && (!ca_mem || !ca_mem_len)) 410 return 0; 411 412 if (ca_filepath) { 413#if !defined(LWS_PLAT_OPTEE) 414 uint8_t *buf; 415 lws_filepos_t len; 416 417 if (alloc_file(vh->context, ca_filepath, &buf, &len)) { 418 lwsl_err("Load CA cert file %s failed\n", ca_filepath); 419 return 1; 420 } 421 vh->tls.x509_client_CA = d2i_X509(NULL, buf, (long)len); 422 free(buf); 423 424 lwsl_info("Loading vh %s client CA for verification %s\n", vh->name, ca_filepath); 425#endif 426 } else { 427 vh->tls.x509_client_CA = d2i_X509(NULL, (uint8_t*)ca_mem, (long)ca_mem_len); 428 lwsl_info("%s: using mem client CA cert %d\n", 429 __func__, ca_mem_len); 430 } 431 432 if (!vh->tls.x509_client_CA) { 433 lwsl_err("client CA: x509 parse failed\n"); 434 return 1; 435 } 436 437 if (!vh->tls.ssl_ctx) 438 SSL_CTX_add_client_CA(vh->tls.ssl_client_ctx, vh->tls.x509_client_CA); 439 else 440 SSL_CTX_add_client_CA(vh->tls.ssl_ctx, vh->tls.x509_client_CA); 441 442 /* support for client-side certificate authentication */ 443 if (cert_filepath) { 444#if !defined(LWS_PLAT_OPTEE) 445 uint8_t *buf; 446 lws_filepos_t amount; 447 448 if (lws_tls_use_any_upgrade_check_extant(cert_filepath) != 449 LWS_TLS_EXTANT_YES && 450 (info->options & LWS_SERVER_OPTION_IGNORE_MISSING_CERT)) 451 return 0; 452 453 lwsl_notice("%s: doing cert filepath %s\n", __func__, 454 cert_filepath); 455 456 if (alloc_file(vh->context, cert_filepath, &buf, &amount)) 457 return 1; 458 459 buf[amount++] = '\0'; 460 461 n = SSL_CTX_use_certificate_ASN1(vh->tls.ssl_client_ctx, 462 (int)amount, buf); 463 lws_free(buf); 464 if (n < 1) { 465 lwsl_err("problem %d getting cert '%s'\n", n, 466 cert_filepath); 467 lws_tls_err_describe_clear(); 468 return 1; 469 } 470 471 lwsl_info("Loaded client cert %s\n", cert_filepath); 472#endif 473 } else if (cert_mem && cert_mem_len) { 474 /* lwsl_hexdump_notice(cert_mem, cert_mem_len - 1); */ 475 n = SSL_CTX_use_certificate_ASN1(vh->tls.ssl_client_ctx, 476 (int)cert_mem_len, cert_mem); 477 if (n < 1) { 478 lwsl_err("%s: (mbedtls) problem interpreting client cert\n", 479 __func__); 480 lws_tls_err_describe_clear(); 481 return 1; 482 } 483 lwsl_info("%s: using mem client cert %d\n", 484 __func__, cert_mem_len); 485 } 486 487 if (private_key_filepath) { 488#if !defined(LWS_PLAT_OPTEE) 489 490 uint8_t *buf; 491 lws_filepos_t amount; 492 493 lwsl_notice("%s: doing private key filepath %s\n", __func__, 494 private_key_filepath); 495 if (alloc_file(vh->context, private_key_filepath, &buf, &amount)) 496 return 1; 497 498 buf[amount++] = '\0'; 499 500 n = SSL_CTX_use_PrivateKey_ASN1(0, vh->tls.ssl_client_ctx, 501 buf, (long)amount); 502 503 lws_free(buf); 504 if (n < 1) { 505 lwsl_err("problem %d getting private key '%s'\n", n, 506 private_key_filepath); 507 lws_tls_err_describe_clear(); 508 return 1; 509 } 510 511 lwsl_notice("Loaded private key %s\n", private_key_filepath); 512#endif 513 } else if (key_mem && key_mem_len) { 514 /* lwsl_hexdump_notice(cert_mem, cert_mem_len - 1); */ 515 n = SSL_CTX_use_PrivateKey_ASN1(0, vh->tls.ssl_client_ctx, 516 key_mem, (long)key_mem_len - 1); 517 518 if (n < 1) { 519 lwsl_err("%s: (mbedtls) problem interpreting private key\n", 520 __func__); 521 lws_tls_err_describe_clear(); 522 return 1; 523 } 524 lwsl_info("%s: using mem private key %d\n", 525 __func__, key_mem_len); 526 527 } 528 return 0; 529} 530 531int 532lws_tls_client_vhost_extra_cert_mem(struct lws_vhost *vh, 533 const uint8_t *der, size_t der_len) 534{ 535 if (SSL_CTX_add_client_CA_ASN1(vh->tls.ssl_client_ctx, (int)der_len, der) != 1) { 536 lwsl_err("%s: failed\n", __func__); 537 return 1; 538 } 539 540 return 0; 541} 542 543