2 * libwebsockets - OpenSSL-specific server functions
4 * Copyright (C) 2010-2018 Andy Green <andy@warmcat.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation:
9 * version 2.1 of the License.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22 #include "private-lib-core.h"
25 * Care: many openssl apis return 1 for success. These are translated to the
26 * lws convention of 0 for success.
29 extern int openssl_websocket_private_data_index,
30 openssl_SSL_CTX_private_data_index;
32 int lws_openssl_describe_cipher(struct lws *wsi);
35 OpenSSL_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
40 union lws_tls_cert_info_results ir;
41 X509 *topcert = X509_STORE_CTX_get_current_cert(x509_ctx);
43 ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
44 SSL_get_ex_data_X509_STORE_CTX_idx());
47 * !!! nasty openssl requires the index to come as a library-scope
50 wsi = SSL_get_ex_data(ssl, openssl_websocket_private_data_index);
52 n = lws_tls_openssl_cert_info(topcert, LWS_TLS_CERT_INFO_COMMON_NAME,
53 &ir, sizeof(ir.ns.name));
55 lwsl_info("%s: client cert CN '%s'\n", __func__, ir.ns.name);
57 lwsl_info("%s: couldn't get client cert CN\n", __func__);
59 n = wsi->vhost->protocols[0].callback(wsi,
60 LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION,
61 x509_ctx, ssl, preverify_ok);
63 /* convert return code from 0 = OK to 1 = OK */
68 lws_tls_server_client_cert_verify_config(struct lws_vhost *vh)
70 int verify_options = SSL_VERIFY_PEER;
72 /* as a server, are we requiring clients to identify themselves? */
74 if (!lws_check_opt(vh->options,
75 LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT))
78 if (!lws_check_opt(vh->options,
79 LWS_SERVER_OPTION_PEER_CERT_NOT_REQUIRED))
80 verify_options |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
82 SSL_CTX_set_session_id_context(vh->tls.ssl_ctx, (uint8_t *)vh->context,
85 /* absolutely require the client cert */
86 SSL_CTX_set_verify(vh->tls.ssl_ctx, verify_options,
87 OpenSSL_verify_callback);
92 #if defined(SSL_TLSEXT_ERR_NOACK) && !defined(OPENSSL_NO_TLSEXT)
94 lws_ssl_server_name_cb(SSL *ssl, int *ad, void *arg)
96 struct lws_context *context = (struct lws_context *)arg;
97 struct lws_vhost *vhost, *vh;
98 const char *servername;
101 return SSL_TLSEXT_ERR_NOACK;
104 * We can only get ssl accepted connections by using a vhost's ssl_ctx
105 * find out which listening one took us and only match vhosts on the
108 vh = context->vhost_list;
110 if (!vh->being_destroyed &&
111 vh->tls.ssl_ctx == SSL_get_SSL_CTX(ssl))
117 assert(vh); /* can't match the incoming vh? */
118 return SSL_TLSEXT_ERR_OK;
121 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
123 /* the client doesn't know what hostname it wants */
124 lwsl_info("SNI: Unknown ServerName\n");
126 return SSL_TLSEXT_ERR_OK;
129 vhost = lws_select_vhost(context, vh->listen_port, servername);
131 lwsl_info("SNI: none: %s:%d\n", servername, vh->listen_port);
133 return SSL_TLSEXT_ERR_OK;
136 lwsl_info("SNI: Found: %s:%d\n", servername, vh->listen_port);
138 /* select the ssl ctx from the selected vhost for this conn */
139 SSL_set_SSL_CTX(ssl, vhost->tls.ssl_ctx);
141 return SSL_TLSEXT_ERR_OK;
146 * this may now get called after the vhost creation, when certs become
150 lws_tls_server_certs_load(struct lws_vhost *vhost, struct lws *wsi,
151 const char *cert, const char *private_key,
152 const char *mem_cert, size_t mem_cert_len,
153 const char *mem_privkey, size_t mem_privkey_len)
155 #if !defined(OPENSSL_NO_EC)
156 const char *ecdh_curve = "prime256v1";
157 #if !defined(LWS_WITH_BORINGSSL) && defined(LWS_HAVE_SSL_EXTRA_CHAIN_CERTS)
158 STACK_OF(X509) *extra_certs = NULL;
160 EC_KEY *ecdh, *EC_key = NULL;
171 int n = lws_tls_generic_cert_checks(vhost, cert, private_key), m;
175 if (!cert && !private_key)
176 n = LWS_TLS_EXTANT_ALTERNATIVE;
178 if (n == LWS_TLS_EXTANT_NO && (!mem_cert || !mem_privkey))
180 if (n == LWS_TLS_EXTANT_NO)
181 n = LWS_TLS_EXTANT_ALTERNATIVE;
183 if (n == LWS_TLS_EXTANT_ALTERNATIVE && (!mem_cert || !mem_privkey))
184 return 1; /* no alternative */
186 if (n == LWS_TLS_EXTANT_ALTERNATIVE) {
188 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
191 * Although we have prepared update certs, we no longer have
192 * the rights to read our own cert + key we saved.
194 * If we were passed copies in memory buffers, use those
195 * in favour of the filepaths we normally want.
202 * use the multi-cert interface for backwards compatibility in the
203 * both simple files case
206 if (n != LWS_TLS_EXTANT_ALTERNATIVE && cert) {
208 /* set the local certificate from CertFile */
209 m = SSL_CTX_use_certificate_chain_file(vhost->tls.ssl_ctx, cert);
211 error = ERR_get_error();
212 lwsl_err("problem getting cert '%s' %lu: %s\n",
213 cert, error, ERR_error_string(error,
214 (char *)vhost->context->pt[0].serv_buf));
220 /* set the private key from KeyFile */
221 if (SSL_CTX_use_PrivateKey_file(vhost->tls.ssl_ctx, private_key,
222 SSL_FILETYPE_PEM) != 1) {
223 error = ERR_get_error();
224 lwsl_err("ssl problem getting key '%s' %lu: %s\n",
226 ERR_error_string(error,
227 (char *)vhost->context->pt[0].serv_buf));
231 if (vhost->protocols[0].callback(wsi,
232 LWS_CALLBACK_OPENSSL_CONTEXT_REQUIRES_PRIVATE_KEY,
233 vhost->tls.ssl_ctx, NULL, 0)) {
234 lwsl_err("ssl private key not set\n");
243 /* otherwise allow for DER or PEM, file or memory image */
245 if (lws_tls_alloc_pem_to_der_file(vhost->context, cert, mem_cert,
246 mem_cert_len, &p, &flen)) {
247 lwsl_err("%s: couldn't read cert file\n", __func__);
252 #if !defined(USE_WOLFSSL)
253 ret = SSL_CTX_use_certificate_ASN1(vhost->tls.ssl_ctx, (int)flen, p);
255 ret = wolfSSL_CTX_use_certificate_buffer(vhost->tls.ssl_ctx,
256 (uint8_t *)p, (int)flen,
257 WOLFSSL_FILETYPE_ASN1);
259 lws_free_set_NULL(p);
261 lwsl_err("%s: Problem loading cert\n", __func__);
266 if (lws_tls_alloc_pem_to_der_file(vhost->context, private_key,
267 mem_privkey, mem_privkey_len,
269 lwsl_notice("unable to convert memory privkey\n");
274 #if !defined(USE_WOLFSSL)
275 ret = SSL_CTX_use_PrivateKey_ASN1(EVP_PKEY_RSA, vhost->tls.ssl_ctx, p,
276 (long)(long long)flen);
278 ret = SSL_CTX_use_PrivateKey_ASN1(EVP_PKEY_EC,
279 vhost->tls.ssl_ctx, p,
280 (long)(long long)flen);
283 ret = wolfSSL_CTX_use_PrivateKey_buffer(vhost->tls.ssl_ctx, p, flen,
284 WOLFSSL_FILETYPE_ASN1);
286 lws_free_set_NULL(p);
288 lwsl_notice("unable to use memory privkey\n");
295 * Although we have prepared update certs, we no longer have
296 * the rights to read our own cert + key we saved.
298 * If we were passed copies in memory buffers, use those
301 * The passed memory-buffer cert image is in DER, and the
302 * memory-buffer private key image is PEM.
305 if (lws_tls_alloc_pem_to_der_file(vhost->context, cert, mem_cert,
306 mem_cert_len, &p, &flen)) {
307 lwsl_err("%s: couldn't convert pem to der\n", __func__);
310 if (SSL_CTX_use_certificate_ASN1(vhost->tls.ssl_ctx,
312 (uint8_t *)p) != 1) {
314 if (wolfSSL_CTX_use_certificate_buffer(vhost->tls.ssl_ctx,
317 WOLFSSL_FILETYPE_ASN1) != 1) {
320 lwsl_err("Problem loading update cert\n");
325 if (lws_tls_alloc_pem_to_der_file(vhost->context, NULL,
326 mem_privkey, mem_privkey_len,
328 lwsl_notice("unable to convert memory privkey\n");
333 if (SSL_CTX_use_PrivateKey_ASN1(EVP_PKEY_RSA,
334 vhost->tls.ssl_ctx, p,
335 (long)(long long)flen) != 1) {
337 if (wolfSSL_CTX_use_PrivateKey_buffer(vhost->tls.ssl_ctx, p,
338 flen, WOLFSSL_FILETYPE_ASN1) != 1) {
340 lwsl_notice("unable to use memory privkey\n");
348 /* set the local certificate from CertFile */
349 m = SSL_CTX_use_certificate_chain_file(vhost->tls.ssl_ctx, cert);
351 error = ERR_get_error();
352 lwsl_err("problem getting cert '%s' %lu: %s\n",
353 cert, error, ERR_error_string(error,
354 (char *)vhost->context->pt[0].serv_buf));
359 if (n != LWS_TLS_EXTANT_ALTERNATIVE && private_key) {
360 /* set the private key from KeyFile */
361 if (SSL_CTX_use_PrivateKey_file(vhost->tls.ssl_ctx, private_key,
362 SSL_FILETYPE_PEM) != 1) {
363 error = ERR_get_error();
364 lwsl_err("ssl problem getting key '%s' %lu: %s\n",
366 ERR_error_string(error,
367 (char *)vhost->context->pt[0].serv_buf));
371 if (vhost->protocols[0].callback(wsi,
372 LWS_CALLBACK_OPENSSL_CONTEXT_REQUIRES_PRIVATE_KEY,
373 vhost->tls.ssl_ctx, NULL, 0)) {
374 lwsl_err("ssl private key not set\n");
383 /* verify private key */
384 if (!SSL_CTX_check_private_key(vhost->tls.ssl_ctx)) {
385 lwsl_err("Private SSL key doesn't match cert\n");
391 #if !defined(OPENSSL_NO_EC)
392 if (vhost->tls.ecdh_curve[0])
393 ecdh_curve = vhost->tls.ecdh_curve;
395 ecdh_nid = OBJ_sn2nid(ecdh_curve);
396 if (NID_undef == ecdh_nid) {
397 lwsl_err("SSL: Unknown curve name '%s'", ecdh_curve);
401 ecdh = EC_KEY_new_by_curve_name(ecdh_nid);
403 lwsl_err("SSL: Unable to create curve '%s'", ecdh_curve);
406 SSL_CTX_set_tmp_ecdh(vhost->tls.ssl_ctx, ecdh);
409 SSL_CTX_set_options(vhost->tls.ssl_ctx, SSL_OP_SINGLE_ECDH_USE);
411 lwsl_notice(" SSL ECDH curve '%s'\n", ecdh_curve);
413 if (lws_check_opt(vhost->context->options, LWS_SERVER_OPTION_SSL_ECDH))
414 lwsl_notice(" Using ECDH certificate support\n");
416 /* Get X509 certificate from ssl context */
417 #if !defined(LWS_WITH_BORINGSSL)
418 #if !defined(LWS_HAVE_SSL_EXTRA_CHAIN_CERTS)
419 x = sk_X509_value(vhost->tls.ssl_ctx->extra_certs, 0);
421 SSL_CTX_get_extra_chain_certs_only(vhost->tls.ssl_ctx, &extra_certs);
423 x = sk_X509_value(extra_certs, 0);
425 lwsl_info("%s: no extra certs\n", __func__);
428 //lwsl_err("%s: x is NULL\n", __func__);
434 /* Get the public key from certificate */
435 pkey = X509_get_pubkey(x);
437 lwsl_err("%s: pkey is NULL\n", __func__);
441 /* Get the key type */
442 KeyType = EVP_PKEY_type(EVP_PKEY_id(pkey));
444 if (EVP_PKEY_EC != KeyType) {
445 lwsl_notice("Key type is not EC\n");
449 EC_key = EVP_PKEY_get1_EC_KEY(pkey);
450 /* Set ECDH parameter */
452 lwsl_err("%s: ECDH key is NULL \n", __func__);
455 SSL_CTX_set_tmp_ecdh(vhost->tls.ssl_ctx, EC_key);
459 lwsl_notice(" OpenSSL doesn't support ECDH\n");
461 #if !defined(OPENSSL_NO_EC) && !defined(LWS_WITH_BORINGSSL)
464 vhost->tls.skipped_certs = 0;
470 lws_tls_server_vhost_backend_init(const struct lws_context_creation_info *info,
471 struct lws_vhost *vhost, struct lws *wsi)
474 SSL_METHOD *method = (SSL_METHOD *)SSLv23_server_method();
477 error = ERR_get_error();
478 lwsl_err("problem creating ssl method %lu: %s\n",
479 error, ERR_error_string(error,
480 (char *)vhost->context->pt[0].serv_buf));
483 vhost->tls.ssl_ctx = SSL_CTX_new(method); /* create context */
484 if (!vhost->tls.ssl_ctx) {
485 error = ERR_get_error();
486 lwsl_err("problem creating ssl context %lu: %s\n",
487 error, ERR_error_string(error,
488 (char *)vhost->context->pt[0].serv_buf));
492 SSL_CTX_set_ex_data(vhost->tls.ssl_ctx,
493 openssl_SSL_CTX_private_data_index,
494 (char *)vhost->context);
495 /* Disable SSLv2 and SSLv3 */
496 SSL_CTX_set_options(vhost->tls.ssl_ctx, SSL_OP_NO_SSLv2 |
498 #ifdef SSL_OP_NO_COMPRESSION
499 SSL_CTX_set_options(vhost->tls.ssl_ctx, SSL_OP_NO_COMPRESSION);
501 SSL_CTX_set_options(vhost->tls.ssl_ctx, SSL_OP_SINGLE_DH_USE);
502 SSL_CTX_set_options(vhost->tls.ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
504 if (info->ssl_cipher_list)
505 SSL_CTX_set_cipher_list(vhost->tls.ssl_ctx, info->ssl_cipher_list);
507 #if defined(LWS_HAVE_SSL_CTX_set_ciphersuites)
508 if (info->tls1_3_plus_cipher_list)
509 SSL_CTX_set_ciphersuites(vhost->tls.ssl_ctx,
510 info->tls1_3_plus_cipher_list);
513 #if !defined(OPENSSL_NO_TLSEXT)
514 SSL_CTX_set_tlsext_servername_callback(vhost->tls.ssl_ctx,
515 lws_ssl_server_name_cb);
516 SSL_CTX_set_tlsext_servername_arg(vhost->tls.ssl_ctx, vhost->context);
519 if (info->ssl_ca_filepath &&
520 !SSL_CTX_load_verify_locations(vhost->tls.ssl_ctx,
521 info->ssl_ca_filepath, NULL)) {
522 lwsl_err("%s: SSL_CTX_load_verify_locations unhappy\n",
526 if (info->ssl_options_set)
527 SSL_CTX_set_options(vhost->tls.ssl_ctx, info->ssl_options_set);
529 /* SSL_clear_options introduced in 0.9.8m */
530 #if (OPENSSL_VERSION_NUMBER >= 0x009080df) && !defined(USE_WOLFSSL)
531 if (info->ssl_options_clear)
532 SSL_CTX_clear_options(vhost->tls.ssl_ctx,
533 info->ssl_options_clear);
536 lwsl_info(" SSL options 0x%lX\n",
537 (unsigned long)SSL_CTX_get_options(vhost->tls.ssl_ctx));
538 if (!vhost->tls.use_ssl ||
539 (!info->ssl_cert_filepath && !info->server_ssl_cert_mem))
542 lws_ssl_bind_passphrase(vhost->tls.ssl_ctx, 0, info);
544 return lws_tls_server_certs_load(vhost, wsi, info->ssl_cert_filepath,
545 info->ssl_private_key_filepath,
546 info->server_ssl_cert_mem,
547 info->server_ssl_cert_mem_len,
548 info->server_ssl_private_key_mem,
549 info->server_ssl_private_key_mem_len);
553 lws_tls_server_new_nonblocking(struct lws *wsi, lws_sockfd_type accept_fd)
555 #if !defined(USE_WOLFSSL)
561 wsi->tls.ssl = SSL_new(wsi->vhost->tls.ssl_ctx);
562 if (wsi->tls.ssl == NULL) {
563 lwsl_err("SSL_new failed: %d (errno %d)\n",
564 lws_ssl_get_error(wsi, 0), errno);
566 lws_tls_err_describe_clear();
570 SSL_set_ex_data(wsi->tls.ssl, openssl_websocket_private_data_index, wsi);
571 SSL_set_fd(wsi->tls.ssl, (int)(long long)accept_fd);
574 #ifdef USE_OLD_CYASSL
575 CyaSSL_set_using_nonblock(wsi->tls.ssl, 1);
577 wolfSSL_set_using_nonblock(wsi->tls.ssl, 1);
581 SSL_set_mode(wsi->tls.ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
582 SSL_MODE_RELEASE_BUFFERS);
583 bio = SSL_get_rbio(wsi->tls.ssl);
585 BIO_set_nbio(bio, 1); /* nonblocking */
587 lwsl_notice("NULL rbio\n");
588 bio = SSL_get_wbio(wsi->tls.ssl);
590 BIO_set_nbio(bio, 1); /* nonblocking */
592 lwsl_notice("NULL rbio\n");
595 #if defined (LWS_HAVE_SSL_SET_INFO_CALLBACK)
596 if (wsi->vhost->tls.ssl_info_event_mask)
597 SSL_set_info_callback(wsi->tls.ssl, lws_ssl_info_callback);
604 lws_tls_server_abort_connection(struct lws *wsi)
606 SSL_shutdown(wsi->tls.ssl);
607 SSL_free(wsi->tls.ssl);
612 enum lws_ssl_capable_status
613 lws_tls_server_accept(struct lws *wsi)
615 struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
616 union lws_tls_cert_info_results ir;
621 n = SSL_accept(wsi->tls.ssl);
624 n = lws_tls_peer_cert_info(wsi, LWS_TLS_CERT_INFO_COMMON_NAME, &ir,
627 lwsl_notice("%s: client cert CN '%s'\n", __func__,
630 lwsl_info("%s: no client cert CN\n", __func__);
632 lws_openssl_describe_cipher(wsi);
634 if (SSL_pending(wsi->tls.ssl) &&
635 lws_dll2_is_detached(&wsi->tls.dll_pending_tls))
636 lws_dll2_add_head(&wsi->tls.dll_pending_tls,
637 &pt->tls.dll_pending_tls_owner);
639 return LWS_SSL_CAPABLE_DONE;
642 m = lws_ssl_get_error(wsi, n);
643 lws_tls_err_describe_clear();
645 if (m == SSL_ERROR_SYSCALL || m == SSL_ERROR_SSL)
646 return LWS_SSL_CAPABLE_ERROR;
648 if (m == SSL_ERROR_WANT_READ ||
649 (m != SSL_ERROR_ZERO_RETURN && SSL_want_read(wsi->tls.ssl))) {
650 if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) {
651 lwsl_info("%s: WANT_READ change_pollfd failed\n",
653 return LWS_SSL_CAPABLE_ERROR;
656 lwsl_info("SSL_ERROR_WANT_READ: m %d\n", m);
657 return LWS_SSL_CAPABLE_MORE_SERVICE_READ;
659 if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl)) {
660 lwsl_debug("%s: WANT_WRITE\n", __func__);
662 if (lws_change_pollfd(wsi, 0, LWS_POLLOUT)) {
663 lwsl_info("%s: WANT_WRITE change_pollfd failed\n",
665 return LWS_SSL_CAPABLE_ERROR;
667 return LWS_SSL_CAPABLE_MORE_SERVICE_WRITE;
670 return LWS_SSL_CAPABLE_ERROR;
673 #if defined(LWS_WITH_ACME)
675 lws_tls_openssl_rsa_new_key(RSA **rsa, int bits)
677 BIGNUM *bn = BN_new();
683 if (BN_set_word(bn, RSA_F4) != 1) {
694 n = RSA_generate_key_ex(*rsa, bits, bn, NULL);
705 struct lws_tls_ss_pieces {
711 LWS_VISIBLE LWS_EXTERN int
712 lws_tls_acme_sni_cert_create(struct lws_vhost *vhost, const char *san_a,
715 GENERAL_NAMES *gens = sk_GENERAL_NAME_new_null();
716 GENERAL_NAME *gen = NULL;
717 ASN1_IA5STRING *ia5 = NULL;
723 vhost->tls.ss = lws_zalloc(sizeof(*vhost->tls.ss), "sni cert");
724 if (!vhost->tls.ss) {
725 GENERAL_NAMES_free(gens);
729 vhost->tls.ss->x509 = X509_new();
730 if (!vhost->tls.ss->x509)
733 ASN1_INTEGER_set(X509_get_serialNumber(vhost->tls.ss->x509), 1);
734 X509_gmtime_adj(X509_get_notBefore(vhost->tls.ss->x509), 0);
735 X509_gmtime_adj(X509_get_notAfter(vhost->tls.ss->x509), 3600);
737 vhost->tls.ss->pkey = EVP_PKEY_new();
738 if (!vhost->tls.ss->pkey)
741 if (lws_tls_openssl_rsa_new_key(&vhost->tls.ss->rsa, 4096))
744 if (!EVP_PKEY_assign_RSA(vhost->tls.ss->pkey, vhost->tls.ss->rsa))
747 X509_set_pubkey(vhost->tls.ss->x509, vhost->tls.ss->pkey);
749 name = X509_get_subject_name(vhost->tls.ss->x509);
750 X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC,
751 (unsigned char *)"GB", -1, -1, 0);
752 X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC,
753 (unsigned char *)"somecompany", -1, -1, 0);
754 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_UTF8,
755 (unsigned char *)"temp.acme.invalid",
757 lwsl_notice("failed to add CN\n");
760 X509_set_issuer_name(vhost->tls.ss->x509, name);
762 /* add the SAN payloads */
764 gen = GENERAL_NAME_new();
765 ia5 = ASN1_IA5STRING_new();
766 if (!ASN1_STRING_set(ia5, san_a, -1)) {
767 lwsl_notice("failed to set ia5\n");
768 GENERAL_NAME_free(gen);
771 GENERAL_NAME_set0_value(gen, GEN_DNS, ia5);
772 sk_GENERAL_NAME_push(gens, gen);
774 if (X509_add1_ext_i2d(vhost->tls.ss->x509, NID_subject_alt_name,
775 gens, 0, X509V3_ADD_APPEND) != 1)
778 GENERAL_NAMES_free(gens);
780 if (san_b && san_b[0]) {
781 gens = sk_GENERAL_NAME_new_null();
782 gen = GENERAL_NAME_new();
783 ia5 = ASN1_IA5STRING_new();
784 if (!ASN1_STRING_set(ia5, san_a, -1)) {
785 lwsl_notice("failed to set ia5\n");
786 GENERAL_NAME_free(gen);
789 GENERAL_NAME_set0_value(gen, GEN_DNS, ia5);
790 sk_GENERAL_NAME_push(gens, gen);
792 if (X509_add1_ext_i2d(vhost->tls.ss->x509, NID_subject_alt_name,
793 gens, 0, X509V3_ADD_APPEND) != 1)
796 GENERAL_NAMES_free(gens);
799 /* sign it with our private key */
800 if (!X509_sign(vhost->tls.ss->x509, vhost->tls.ss->pkey, EVP_sha256()))
804 {/* useful to take a sample of a working cert for mbedtls to crib */
805 FILE *fp = fopen("/tmp/acme-temp-cert", "w+");
807 i2d_X509_fp(fp, vhost->tls.ss->x509);
812 /* tell the vhost to use our crafted certificate */
813 SSL_CTX_use_certificate(vhost->tls.ssl_ctx, vhost->tls.ss->x509);
814 /* and to use our generated private key */
815 SSL_CTX_use_PrivateKey(vhost->tls.ssl_ctx, vhost->tls.ss->pkey);
820 RSA_free(vhost->tls.ss->rsa);
822 EVP_PKEY_free(vhost->tls.ss->pkey);
824 X509_free(vhost->tls.ss->x509);
826 lws_free(vhost->tls.ss);
827 GENERAL_NAMES_free(gens);
833 lws_tls_acme_sni_cert_destroy(struct lws_vhost *vhost)
838 EVP_PKEY_free(vhost->tls.ss->pkey);
839 X509_free(vhost->tls.ss->x509);
840 lws_free_set_NULL(vhost->tls.ss);
844 lws_tls_openssl_add_nid(X509_NAME *name, int nid, const char *value)
849 if (!value || value[0] == '\0')
852 e = X509_NAME_ENTRY_create_by_NID(NULL, nid, MBSTRING_ASC,
853 (unsigned char *)value, -1);
856 n = X509_NAME_add_entry(name, e, -1, 0);
857 X509_NAME_ENTRY_free(e);
862 static int nid_list[] = {
863 NID_countryName, /* LWS_TLS_REQ_ELEMENT_COUNTRY */
864 NID_stateOrProvinceName, /* LWS_TLS_REQ_ELEMENT_STATE */
865 NID_localityName, /* LWS_TLS_REQ_ELEMENT_LOCALITY */
866 NID_organizationName, /* LWS_TLS_REQ_ELEMENT_ORGANIZATION */
867 NID_commonName, /* LWS_TLS_REQ_ELEMENT_COMMON_NAME */
868 NID_organizationalUnitName, /* LWS_TLS_REQ_ELEMENT_EMAIL */
871 LWS_VISIBLE LWS_EXTERN int
872 lws_tls_acme_sni_csr_create(struct lws_context *context, const char *elements[],
873 uint8_t *csr, size_t csr_len, char **privkey_pem,
876 uint8_t *csr_in = csr;
886 if (lws_tls_openssl_rsa_new_key(&rsakey, 4096))
889 pkey = EVP_PKEY_new();
892 if (!EVP_PKEY_set1_RSA(pkey, rsakey))
895 req = X509_REQ_new();
899 X509_REQ_set_pubkey(req, pkey);
901 subj = X509_NAME_new();
905 for (n = 0; n < LWS_TLS_REQ_ELEMENT_COUNT; n++)
906 if (lws_tls_openssl_add_nid(subj, nid_list[n], elements[n])) {
907 lwsl_notice("%s: failed to add element %d\n", __func__,
912 if (X509_REQ_set_subject_name(req, subj) != 1)
915 if (!X509_REQ_sign(req, pkey, EVP_sha256()))
919 * issue the CSR as PEM to a BIO, and translate to b64urlenc without
920 * headers, trailers, or whitespace
923 bio = BIO_new(BIO_s_mem());
927 if (PEM_write_bio_X509_REQ(bio, req) != 1) {
932 bio_len = BIO_get_mem_data(bio, &p);
935 /* strip the header line */
936 while (p < end && *p != '\n')
939 while (p < end && csr_len) {
960 lwsl_notice("%s: need %ld for CSR\n", __func__, bio_len);
965 * Also return the private key as a PEM in memory
966 * (platform may not have a filesystem)
968 bio = BIO_new(BIO_s_mem());
972 if (PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, 0, NULL) != 1) {
976 bio_len = BIO_get_mem_data(bio, &p);
977 *privkey_pem = malloc(bio_len); /* malloc so user code can own / free */
978 *privkey_len = (size_t)bio_len;
980 lwsl_notice("%s: need %ld for private key\n", __func__,
985 memcpy(*privkey_pem, p, (int)(long long)bio_len);
988 ret = lws_ptr_diff(csr, csr_in);
991 X509_NAME_free(subj);