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 <mbedtls/x509_csr.h> 27#include <errno.h> 28 29int 30lws_tls_server_client_cert_verify_config(struct lws_vhost *vh) 31{ 32 int verify_options = SSL_VERIFY_PEER; 33 34 /* as a server, are we requiring clients to identify themselves? */ 35 if (!lws_check_opt(vh->options, 36 LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT)) { 37 lwsl_notice("no client cert required\n"); 38 return 0; 39 } 40 41 if (!lws_check_opt(vh->options, LWS_SERVER_OPTION_PEER_CERT_NOT_REQUIRED)) 42 verify_options = SSL_VERIFY_FAIL_IF_NO_PEER_CERT; 43 44 lwsl_notice("%s: vh %s requires client cert %d\n", __func__, vh->name, 45 verify_options); 46 47 SSL_CTX_set_verify(vh->tls.ssl_ctx, verify_options, NULL); 48 49 return 0; 50} 51 52static int 53lws_mbedtls_sni_cb(void *arg, mbedtls_ssl_context *mbedtls_ctx, 54 const unsigned char *servername, size_t len) 55{ 56 SSL *ssl = SSL_SSL_from_mbedtls_ssl_context(mbedtls_ctx); 57 struct lws_context *context = (struct lws_context *)arg; 58 struct lws_vhost *vhost, *vh; 59 60 lwsl_notice("%s: %s\n", __func__, servername); 61 62 /* 63 * We can only get ssl accepted connections by using a vhost's ssl_ctx 64 * find out which listening one took us and only match vhosts on the 65 * same port. 66 */ 67 vh = context->vhost_list; 68 while (vh) { 69 if (!vh->being_destroyed && 70 vh->tls.ssl_ctx == SSL_get_SSL_CTX(ssl)) 71 break; 72 vh = vh->vhost_next; 73 } 74 75 if (!vh) { 76 assert(vh); /* can't match the incoming vh? */ 77 return 0; 78 } 79 80 vhost = lws_select_vhost(context, vh->listen_port, 81 (const char *)servername); 82 if (!vhost) { 83 lwsl_info("SNI: none: %s:%d\n", servername, vh->listen_port); 84 85 return 0; 86 } 87 88 lwsl_info("SNI: Found: %s:%d at vhost '%s'\n", servername, 89 vh->listen_port, vhost->name); 90 91 if (!vhost->tls.ssl_ctx) { 92 lwsl_err("%s: vhost %s matches SNI but no valid cert\n", 93 __func__, vh->name); 94 95 return 1; 96 } 97 98 /* select the ssl ctx from the selected vhost for this conn */ 99 SSL_set_SSL_CTX(ssl, vhost->tls.ssl_ctx); 100 101 return 0; 102} 103 104int 105lws_tls_server_certs_load(struct lws_vhost *vhost, struct lws *wsi, 106 const char *cert, const char *private_key, 107 const char *mem_cert, size_t mem_cert_len, 108 const char *mem_privkey, size_t mem_privkey_len) 109{ 110 lws_filepos_t flen; 111 uint8_t *p = NULL; 112 long err; 113 int n; 114 115 if ((!cert || !private_key) && (!mem_cert || !mem_privkey)) { 116 lwsl_notice("%s: no usable input\n", __func__); 117 return 0; 118 } 119 120 n = (int)lws_tls_generic_cert_checks(vhost, cert, private_key); 121 122 if (n == LWS_TLS_EXTANT_NO && (!mem_cert || !mem_privkey)) 123 return 0; 124 125 /* 126 * we can't read the root-privs files. But if mem_cert is provided, 127 * we should use that. 128 */ 129 if (n == LWS_TLS_EXTANT_NO) 130 n = LWS_TLS_EXTANT_ALTERNATIVE; 131 132 if (n == LWS_TLS_EXTANT_ALTERNATIVE && (!mem_cert || !mem_privkey)) 133 return 1; /* no alternative */ 134 135 if (n == LWS_TLS_EXTANT_ALTERNATIVE) { 136 /* 137 * Although we have prepared update certs, we no longer have 138 * the rights to read our own cert + key we saved. 139 * 140 * If we were passed copies in memory buffers, use those 141 * instead. 142 * 143 * The passed memory-buffer cert image is in DER, and the 144 * memory-buffer private key image is PEM. 145 */ 146 cert = NULL; 147 private_key = NULL; 148 } 149 if (lws_tls_alloc_pem_to_der_file(vhost->context, cert, mem_cert, 150 mem_cert_len, &p, &flen)) { 151 lwsl_err("couldn't find cert file %s\n", cert); 152 153 return 1; 154 } 155 156 err = SSL_CTX_use_certificate_ASN1(vhost->tls.ssl_ctx, (int)flen, p); 157 lws_free_set_NULL(p); 158 if (!err) { 159 lwsl_err("Problem loading cert\n"); 160 return 1; 161 } 162 163 if (lws_tls_alloc_pem_to_der_file(vhost->context, private_key, 164 (char *)mem_privkey, mem_privkey_len, 165 &p, &flen)) { 166 lwsl_err("couldn't find private key\n"); 167 168 return 1; 169 } 170 171 err = SSL_CTX_use_PrivateKey_ASN1(0, vhost->tls.ssl_ctx, p, (long)flen); 172 lws_free_set_NULL(p); 173 if (!err) { 174 lwsl_err("Problem loading key\n"); 175 176 return 1; 177 } 178 179 vhost->tls.skipped_certs = 0; 180 181 return 0; 182} 183 184int 185lws_tls_server_vhost_backend_init(const struct lws_context_creation_info *info, 186 struct lws_vhost *vhost, struct lws *wsi) 187{ 188 const SSL_METHOD *method = TLS_server_method(); 189 uint8_t *p; 190 lws_filepos_t flen; 191 int n; 192 193 vhost->tls.ssl_ctx = SSL_CTX_new(method, &vhost->context->mcdc); /* create context */ 194 if (!vhost->tls.ssl_ctx) { 195 lwsl_err("problem creating ssl context\n"); 196 return 1; 197 } 198 199 if (!vhost->tls.use_ssl || 200 (!info->ssl_cert_filepath && !info->server_ssl_cert_mem)) 201 return 0; 202 203 if (info->ssl_ca_filepath) { 204 lwsl_notice("%s: vh %s: loading CA filepath %s\n", __func__, 205 vhost->name, info->ssl_ca_filepath); 206 if (lws_tls_alloc_pem_to_der_file(vhost->context, 207 info->ssl_ca_filepath, NULL, 0, &p, &flen)) { 208 lwsl_err("couldn't find client CA file %s\n", 209 info->ssl_ca_filepath); 210 211 return 1; 212 } 213 214 if (SSL_CTX_add_client_CA_ASN1(vhost->tls.ssl_ctx, (int)flen, p) != 1) { 215 lwsl_err("%s: SSL_CTX_add_client_CA_ASN1 unhappy\n", 216 __func__); 217 free(p); 218 return 1; 219 } 220 free(p); 221 } else { 222 if (info->server_ssl_ca_mem && info->server_ssl_ca_mem_len && 223 SSL_CTX_add_client_CA_ASN1(vhost->tls.ssl_ctx, 224 (int)info->server_ssl_ca_mem_len, 225 info->server_ssl_ca_mem) != 1) { 226 lwsl_err("%s: mem SSL_CTX_add_client_CA_ASN1 unhappy\n", 227 __func__); 228 return 1; 229 } 230 lwsl_notice("%s: vh %s: mem CA OK\n", __func__, vhost->name); 231 } 232 233 n = lws_tls_server_certs_load(vhost, wsi, info->ssl_cert_filepath, 234 info->ssl_private_key_filepath, 235 info->server_ssl_cert_mem, 236 info->server_ssl_cert_mem_len, 237 info->server_ssl_private_key_mem, 238 info->server_ssl_private_key_mem_len); 239 if (n) 240 return n; 241 242 return 0; 243} 244 245int 246lws_tls_server_new_nonblocking(struct lws *wsi, lws_sockfd_type accept_fd) 247{ 248 errno = 0; 249 wsi->tls.ssl = SSL_new(wsi->a.vhost->tls.ssl_ctx); 250 if (wsi->tls.ssl == NULL) { 251 lwsl_err("SSL_new failed: errno %d\n", errno); 252 253 lws_tls_err_describe_clear(); 254 return 1; 255 } 256 257 SSL_set_fd(wsi->tls.ssl, (int)accept_fd); 258 259 if (wsi->a.vhost->tls.ssl_info_event_mask) 260 SSL_set_info_callback(wsi->tls.ssl, lws_ssl_info_callback); 261 262 SSL_set_sni_callback(wsi->tls.ssl, lws_mbedtls_sni_cb, wsi->a.context); 263 264 return 0; 265} 266 267enum lws_ssl_capable_status 268lws_tls_server_abort_connection(struct lws *wsi) 269{ 270 if (wsi->tls.use_ssl) 271 __lws_tls_shutdown(wsi); 272 273 SSL_free(wsi->tls.ssl); 274 275 return 0; 276} 277 278enum lws_ssl_capable_status 279lws_tls_server_accept(struct lws *wsi) 280{ 281 union lws_tls_cert_info_results ir; 282 int m, n; 283 284 n = SSL_accept(wsi->tls.ssl); 285 286 wsi->skip_fallback = 1; 287 if (n == 1) { 288 289 if (strstr(wsi->a.vhost->name, ".invalid")) { 290 lwsl_notice("%s: vhost has .invalid, " 291 "rejecting accept\n", __func__); 292 293 return LWS_SSL_CAPABLE_ERROR; 294 } 295 296 n = lws_tls_peer_cert_info(wsi, LWS_TLS_CERT_INFO_COMMON_NAME, 297 &ir, sizeof(ir.ns.name)); 298 if (!n) 299 lwsl_notice("%s: client cert CN '%s'\n", 300 __func__, ir.ns.name); 301 else 302 lwsl_info("%s: couldn't get client cert CN\n", 303 __func__); 304 return LWS_SSL_CAPABLE_DONE; 305 } 306 307 m = SSL_get_error(wsi->tls.ssl, n); 308 lwsl_debug("%s: %s: accept SSL_get_error %d errno %d\n", __func__, 309 lws_wsi_tag(wsi), m, errno); 310 311 // mbedtls wrapper only 312 if (m == SSL_ERROR_SYSCALL && errno == 11) 313 return LWS_SSL_CAPABLE_MORE_SERVICE_READ; 314 315#if defined(__APPLE__) 316 if (m == SSL_ERROR_SYSCALL && errno == 35) 317 return LWS_SSL_CAPABLE_MORE_SERVICE_READ; 318#endif 319 320#if defined(WIN32) 321 if (m == SSL_ERROR_SYSCALL && errno == 0) 322 return LWS_SSL_CAPABLE_MORE_SERVICE_READ; 323#endif 324 325 if (m == SSL_ERROR_SYSCALL || m == SSL_ERROR_SSL) 326 return LWS_SSL_CAPABLE_ERROR; 327 328 if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->tls.ssl)) { 329 if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) { 330 lwsl_info("%s: WANT_READ change_pollfd failed\n", 331 __func__); 332 return LWS_SSL_CAPABLE_ERROR; 333 } 334 335 lwsl_info("SSL_ERROR_WANT_READ\n"); 336 return LWS_SSL_CAPABLE_MORE_SERVICE_READ; 337 } 338 if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl)) { 339 lwsl_debug("%s: WANT_WRITE\n", __func__); 340 341 if (lws_change_pollfd(wsi, 0, LWS_POLLOUT)) { 342 lwsl_info("%s: WANT_WRITE change_pollfd failed\n", 343 __func__); 344 return LWS_SSL_CAPABLE_ERROR; 345 } 346 return LWS_SSL_CAPABLE_MORE_SERVICE_WRITE; 347 } 348 349 return LWS_SSL_CAPABLE_ERROR; 350} 351 352#if defined(LWS_WITH_ACME) 353/* 354 * mbedtls doesn't support SAN for cert creation. So we use a known-good 355 * tls-sni-01 cert from OpenSSL that worked on Let's Encrypt, and just replace 356 * the pubkey n part and the signature part. 357 * 358 * This will need redoing for tls-sni-02... 359 */ 360 361static uint8_t ss_cert_leadin[] = { 362 0x30, 0x82, 363 0x05, 0x56, /* total length: LEN1 (+2 / +3) (correct for 513 + 512)*/ 364 365 0x30, 0x82, /* length: LEN2 (+6 / +7) (correct for 513) */ 366 0x03, 0x3e, 367 368 /* addition: v3 cert (+5 bytes)*/ 369 0xa0, 0x03, 370 0x02, 0x01, 0x02, 371 372 0x02, 0x01, 0x01, 373 0x30, 0x0d, 0x06, 0x09, 0x2a, 374 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x3f, 375 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 376 0x42, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 377 0x73, 0x6f, 0x6d, 0x65, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x31, 378 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 0x74, 0x65, 379 0x6d, 0x70, 0x2e, 0x61, 0x63, 0x6d, 0x65, 0x2e, 0x69, 0x6e, 0x76, 0x61, 380 0x6c, 0x69, 0x64, 0x30, 0x1e, 0x17, 0x0d, 381 382 /* from 2017-10-29 ... */ 383 0x31, 0x37, 0x31, 0x30, 0x32, 0x39, 0x31, 0x31, 0x34, 0x39, 0x34, 0x35, 384 0x5a, 0x17, 0x0d, 385 386 /* thru 2049-10-29 we immediately discard the private key, no worries */ 387 0x34, 0x39, 0x31, 0x30, 0x32, 0x39, 0x31, 0x32, 0x34, 0x39, 0x34, 0x35, 388 0x5a, 389 390 0x30, 0x3f, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 391 0x02, 0x47, 0x42, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 392 0x0c, 0x0b, 0x73, 0x6f, 0x6d, 0x65, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 393 0x79, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 394 0x74, 0x65, 0x6d, 0x70, 0x2e, 0x61, 0x63, 0x6d, 0x65, 0x2e, 0x69, 0x6e, 395 0x76, 0x61, 0x6c, 0x69, 0x64, 0x30, 396 397 0x82, 398 0x02, 0x22, /* LEN3 (+C3 / C4) */ 399 0x30, 0x0d, 0x06, 400 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 401 0x03, 402 403 0x82, 404 0x02, 0x0f, /* LEN4 (+D6 / D7) */ 405 406 0x00, 0x30, 0x82, 407 408 0x02, 0x0a, /* LEN5 (+ DB / DC) */ 409 410 0x02, 0x82, 411 412 //0x02, 0x01, /* length of n in bytes (including leading 00 if any) */ 413 }, 414 415 /* 1 + (keybits / 8) bytes N */ 416 417 ss_cert_san_leadin[] = { 418 /* e - fixed */ 419 0x02, 0x03, 0x01, 0x00, 0x01, 420 421 0xa3, 0x5d, 0x30, 0x5b, 0x30, 0x59, 0x06, 0x03, 0x55, 0x1d, 422 0x11, 0x04, 0x52, 0x30, 0x50, /* <-- SAN length + 2 */ 423 424 0x82, 0x4e, /* <-- SAN length */ 425 }, 426 427 /* 78 bytes of SAN (tls-sni-01) 428 0x61, 0x64, 0x34, 0x31, 0x61, 0x66, 0x62, 0x65, 0x30, 0x63, 0x61, 0x34, 429 0x36, 0x34, 0x32, 0x66, 0x30, 0x61, 0x34, 0x34, 0x39, 0x64, 0x39, 0x63, 430 0x61, 0x37, 0x36, 0x65, 0x62, 0x61, 0x61, 0x62, 0x2e, 0x32, 0x38, 0x39, 431 0x34, 0x64, 0x34, 0x31, 0x36, 0x63, 0x39, 0x38, 0x33, 0x66, 0x31, 0x32, 432 0x65, 0x64, 0x37, 0x33, 0x31, 0x61, 0x33, 0x30, 0x66, 0x35, 0x63, 0x34, 433 0x34, 0x37, 0x37, 0x66, 0x65, 0x2e, 0x61, 0x63, 0x6d, 0x65, 0x2e, 0x69, 434 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, */ 435 436 /* end of LEN2 area */ 437 438 ss_cert_sig_leadin[] = { 439 /* it's saying that the signature is SHA256 + RSA */ 440 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 441 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 442 443 0x82, 444 0x02, 0x01, 445 0x00, 446 }; 447 448 /* (keybits / 8) bytes signature to end of LEN1 area */ 449 450#define SAN_A_LENGTH 78 451 452int 453lws_tls_acme_sni_cert_create(struct lws_vhost *vhost, const char *san_a, 454 const char *san_b) 455{ 456 int buflen = 0x560; 457 uint8_t *buf = lws_malloc((unsigned int)buflen, "tmp cert buf"), *p = buf, *pkey_asn1; 458 struct lws_genrsa_ctx ctx; 459 struct lws_gencrypto_keyelem el[LWS_GENCRYPTO_RSA_KEYEL_COUNT]; 460 uint8_t digest[32]; 461 struct lws_genhash_ctx hash_ctx; 462 int pkey_asn1_len = 3 * 1024; 463 int n, m, keybits = lws_plat_recommended_rsa_bits(), adj; 464 465 if (!buf) 466 return 1; 467 468 n = lws_genrsa_new_keypair(vhost->context, &ctx, LGRSAM_PKCS1_1_5, 469 &el[0], keybits); 470 if (n < 0) { 471 lws_genrsa_destroy_elements(&el[0]); 472 goto bail1; 473 } 474 475 n = sizeof(ss_cert_leadin); 476 memcpy(p, ss_cert_leadin, (unsigned int)n); 477 p += n; 478 479 adj = (0x0556 - 0x401) + (keybits / 4) + 1; 480 buf[2] = (uint8_t)(adj >> 8); 481 buf[3] = (uint8_t)(adj & 0xff); 482 483 adj = (0x033e - 0x201) + (keybits / 8) + 1; 484 buf[6] = (uint8_t)(adj >> 8); 485 buf[7] = (uint8_t)(adj & 0xff); 486 487 adj = (0x0222 - 0x201) + (keybits / 8) + 1; 488 buf[0xc3] = (uint8_t)(adj >> 8); 489 buf[0xc4] = (uint8_t)(adj & 0xff); 490 491 adj = (0x020f - 0x201) + (keybits / 8) + 1; 492 buf[0xd6] = (uint8_t)(adj >> 8); 493 buf[0xd7] = (uint8_t)(adj & 0xff); 494 495 adj = (0x020a - 0x201) + (keybits / 8) + 1; 496 buf[0xdb] = (uint8_t)(adj >> 8); 497 buf[0xdc] = (uint8_t)(adj & 0xff); 498 499 *p++ = (uint8_t)(((keybits / 8) + 1) >> 8); 500 *p++ = (uint8_t)(((keybits / 8) + 1) & 0xff); 501 502 /* we need to drop 1 + (keybits / 8) bytes of n in here, 00 + key */ 503 504 *p++ = 0x00; 505 memcpy(p, el[LWS_GENCRYPTO_RSA_KEYEL_N].buf, el[LWS_GENCRYPTO_RSA_KEYEL_N].len); 506 p += el[LWS_GENCRYPTO_RSA_KEYEL_N].len; 507 508 memcpy(p, ss_cert_san_leadin, sizeof(ss_cert_san_leadin)); 509 p += sizeof(ss_cert_san_leadin); 510 511 /* drop in 78 bytes of san_a */ 512 513 memcpy(p, san_a, SAN_A_LENGTH); 514 p += SAN_A_LENGTH; 515 memcpy(p, ss_cert_sig_leadin, sizeof(ss_cert_sig_leadin)); 516 517 p[17] = (uint8_t)(((keybits / 8) + 1) >> 8); 518 p[18] = (uint8_t)(((keybits / 8) + 1) & 0xff); 519 520 p += sizeof(ss_cert_sig_leadin); 521 522 /* hash the cert plaintext */ 523 524 if (lws_genhash_init(&hash_ctx, LWS_GENHASH_TYPE_SHA256)) 525 goto bail2; 526 527 if (lws_genhash_update(&hash_ctx, buf, lws_ptr_diff_size_t(p, buf))) { 528 lws_genhash_destroy(&hash_ctx, NULL); 529 530 goto bail2; 531 } 532 if (lws_genhash_destroy(&hash_ctx, digest)) 533 goto bail2; 534 535 /* sign the hash */ 536 537 n = lws_genrsa_hash_sign(&ctx, digest, LWS_GENHASH_TYPE_SHA256, p, 538 (size_t)((size_t)buflen - lws_ptr_diff_size_t(p, buf))); 539 if (n < 0) 540 goto bail2; 541 p += n; 542 543 pkey_asn1 = lws_malloc((unsigned int)pkey_asn1_len, "mbed crt tmp"); 544 if (!pkey_asn1) 545 goto bail2; 546 547 m = lws_genrsa_render_pkey_asn1(&ctx, 1, pkey_asn1, (size_t)pkey_asn1_len); 548 if (m < 0) { 549 lws_free(pkey_asn1); 550 goto bail2; 551 } 552 553// lwsl_hexdump_level(LLL_DEBUG, buf, lws_ptr_diff(p, buf)); 554 n = SSL_CTX_use_certificate_ASN1(vhost->tls.ssl_ctx, 555 lws_ptr_diff(p, buf), buf); 556 if (n != 1) { 557 lws_free(pkey_asn1); 558 lwsl_err("%s: generated cert failed to load 0x%x\n", 559 __func__, -n); 560 } else { 561 //lwsl_debug("private key\n"); 562 //lwsl_hexdump_level(LLL_DEBUG, pkey_asn1, n); 563 564 /* and to use our generated private key */ 565 n = SSL_CTX_use_PrivateKey_ASN1(0, vhost->tls.ssl_ctx, 566 pkey_asn1, m); 567 lws_free(pkey_asn1); 568 if (n != 1) { 569 lwsl_err("%s: SSL_CTX_use_PrivateKey_ASN1 failed\n", 570 __func__); 571 } 572 } 573 574 lws_genrsa_destroy(&ctx); 575 lws_genrsa_destroy_elements(&el[0]); 576 577 lws_free(buf); 578 579 return n != 1; 580 581bail2: 582 lws_genrsa_destroy(&ctx); 583 lws_genrsa_destroy_elements(&el[0]); 584bail1: 585 lws_free(buf); 586 587 return -1; 588} 589 590void 591lws_tls_acme_sni_cert_destroy(struct lws_vhost *vhost) 592{ 593} 594 595#if defined(LWS_WITH_JOSE) 596static int 597_rngf(void *context, unsigned char *buf, size_t len) 598{ 599 if ((size_t)lws_get_random(context, buf, len) == len) 600 return 0; 601 602 return -1; 603} 604 605static const char *x5[] = { "C", "ST", "L", "O", "CN" }; 606 607/* 608 * CSR is output formatted as b64url(DER) 609 * Private key is output as a PEM in memory 610 */ 611int 612lws_tls_acme_sni_csr_create(struct lws_context *context, const char *elements[], 613 uint8_t *dcsr, size_t csr_len, char **privkey_pem, 614 size_t *privkey_len) 615{ 616 mbedtls_x509write_csr csr; 617 mbedtls_pk_context mpk; 618 int buf_size = 4096, n; 619 char subject[200], *p = subject, *end = p + sizeof(subject) - 1; 620 uint8_t *buf = malloc((unsigned int)buf_size); /* malloc because given to user code */ 621 622 if (!buf) 623 return -1; 624 625 mbedtls_x509write_csr_init(&csr); 626 627 mbedtls_pk_init(&mpk); 628 if (mbedtls_pk_setup(&mpk, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA))) { 629 lwsl_notice("%s: pk_setup failed\n", __func__); 630 goto fail; 631 } 632 633 n = mbedtls_rsa_gen_key(mbedtls_pk_rsa(mpk), _rngf, context, 634 (unsigned int)lws_plat_recommended_rsa_bits(), 65537); 635 if (n) { 636 lwsl_notice("%s: failed to generate keys\n", __func__); 637 638 goto fail1; 639 } 640 641 /* subject must be formatted like "C=TW,O=warmcat,CN=myserver" */ 642 643 for (n = 0; n < (int)LWS_ARRAY_SIZE(x5); n++) { 644 if (p != subject) 645 *p++ = ','; 646 if (elements[n]) 647 p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "%s=%s", x5[n], 648 elements[n]); 649 } 650 651 if (mbedtls_x509write_csr_set_subject_name(&csr, subject)) 652 goto fail1; 653 654 mbedtls_x509write_csr_set_key(&csr, &mpk); 655 mbedtls_x509write_csr_set_md_alg(&csr, MBEDTLS_MD_SHA256); 656 657 /* 658 * data is written at the end of the buffer! Use the 659 * return value to determine where you should start 660 * using the buffer 661 */ 662 n = mbedtls_x509write_csr_der(&csr, buf, (size_t)buf_size, _rngf, context); 663 if (n < 0) { 664 lwsl_notice("%s: write csr der failed\n", __func__); 665 goto fail1; 666 } 667 668 /* we have it in DER, we need it in b64URL */ 669 670 n = lws_jws_base64_enc((char *)(buf + buf_size) - n, (size_t)n, 671 (char *)dcsr, csr_len); 672 if (n < 0) 673 goto fail1; 674 675 /* 676 * okay, the CSR is done, last we need the private key in PEM 677 * re-use the DER CSR buf as the result buffer since we cn do it in 678 * one step 679 */ 680 681 if (mbedtls_pk_write_key_pem(&mpk, buf, (size_t)buf_size)) { 682 lwsl_notice("write key pem failed\n"); 683 goto fail1; 684 } 685 686 *privkey_pem = (char *)buf; 687 *privkey_len = strlen((const char *)buf); 688 689 mbedtls_pk_free(&mpk); 690 mbedtls_x509write_csr_free(&csr); 691 692 return n; 693 694fail1: 695 mbedtls_pk_free(&mpk); 696fail: 697 mbedtls_x509write_csr_free(&csr); 698 free(buf); 699 700 return -1; 701} 702#endif 703#endif 704