Coverage Report

Created: 2026-07-24 06:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libwebsockets/lib/tls/openssl/openssl-server.c
Line
Count
Source
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-openssl.h"
27
28
/*
29
 * Care: many openssl apis return 1 for success.  These are translated to the
30
 * lws convention of 0 for success.
31
 */
32
33
extern int openssl_websocket_private_data_index,
34
     openssl_SSL_CTX_private_data_index;
35
36
int lws_openssl_describe_cipher(struct lws *wsi);
37
38
static int
39
OpenSSL_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
40
0
{
41
0
  SSL *ssl;
42
0
  int n;
43
0
  struct lws *wsi;
44
0
  union lws_tls_cert_info_results ir;
45
0
  X509 *topcert = X509_STORE_CTX_get_current_cert(x509_ctx);
46
47
0
  ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
48
0
    SSL_get_ex_data_X509_STORE_CTX_idx());
49
50
  /*
51
   * !!! nasty openssl requires the index to come as a library-scope
52
   * static
53
   */
54
0
  wsi = SSL_get_ex_data(ssl, openssl_websocket_private_data_index);
55
0
  if (!wsi)
56
0
    return 0; /* OpenSSL failure */
57
58
0
  n = lws_tls_openssl_cert_info(topcert, LWS_TLS_CERT_INFO_COMMON_NAME,
59
0
              &ir, sizeof(ir.ns.name));
60
0
  if (!n)
61
0
    lwsl_info("%s: client cert CN '%s'\n", __func__, ir.ns.name);
62
0
  else
63
0
    lwsl_info("%s: couldn't get client cert CN\n", __func__);
64
65
0
  n = wsi->a.vhost->protocols[0].callback(wsi,
66
0
      LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION,
67
0
             x509_ctx, ssl, (unsigned int)preverify_ok);
68
69
  /* convert return code from 0 = OK to 1 = OK */
70
0
  return !n;
71
0
}
72
73
int
74
lws_tls_server_client_cert_verify_config(struct lws_vhost *vh)
75
0
{
76
0
  int verify_options = SSL_VERIFY_PEER;
77
78
  /* as a server, are we requiring clients to identify themselves? */
79
80
0
  if (!lws_check_opt(vh->options,
81
0
        LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT))
82
0
    return 0;
83
84
0
  if (!lws_check_opt(vh->options,
85
0
         LWS_SERVER_OPTION_PEER_CERT_NOT_REQUIRED))
86
0
    verify_options |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
87
88
0
  SSL_CTX_set_session_id_context(vh->tls.ssl_ctx, (uint8_t *)vh->context,
89
0
               sizeof(void *));
90
91
  /* absolutely require the client cert */
92
0
  SSL_CTX_set_verify(vh->tls.ssl_ctx, verify_options,
93
0
         OpenSSL_verify_callback);
94
95
0
  return 0;
96
0
}
97
98
#if defined(SSL_TLSEXT_ERR_NOACK) && !defined(OPENSSL_NO_TLSEXT)
99
static int
100
lws_ssl_server_name_cb(SSL *ssl, int *ad, void *arg)
101
0
{
102
0
  struct lws_context *context = (struct lws_context *)arg;
103
0
  struct lws_vhost *vhost, *vh;
104
0
  const char *servername;
105
106
0
  if (!ssl)
107
0
    return SSL_TLSEXT_ERR_NOACK;
108
109
  /*
110
   * We can only get ssl accepted connections by using a vhost's ssl_ctx
111
   * find out which listening one took us and only match vhosts on the
112
   * same port.
113
   */
114
0
  vh = context->vhost_list;
115
0
  while (vh) {
116
0
    if (!vh->being_destroyed &&
117
0
        vh->tls.ssl_ctx == SSL_get_SSL_CTX(ssl))
118
0
      break;
119
0
    vh = vh->vhost_next;
120
0
  }
121
122
0
  if (!vh) {
123
0
    assert(vh); /* can't match the incoming vh? */
124
0
    return SSL_TLSEXT_ERR_OK;
125
0
  }
126
127
0
  servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
128
0
  if (!servername) {
129
    /* the client doesn't know what hostname it wants */
130
0
    lwsl_info("SNI: Unknown ServerName\n");
131
132
0
    return SSL_TLSEXT_ERR_OK;
133
0
  }
134
135
0
  vhost = lws_select_vhost(context, vh->listen_port, servername);
136
0
  if (!vhost) {
137
0
    lwsl_info("SNI: none: %s:%d\n", servername, vh->listen_port);
138
139
0
    return SSL_TLSEXT_ERR_OK;
140
0
  }
141
142
0
  lwsl_info("SNI: Found: %s:%d\n", servername, vh->listen_port);
143
144
0
  if (!vhost->tls.ssl_ctx) {
145
0
    lwsl_info("SNI: %s has no tls ctx yet\n", servername);
146
0
    return SSL_TLSEXT_ERR_OK;
147
0
  }
148
149
  /* select the ssl ctx from the selected vhost for this conn */
150
0
  SSL_set_SSL_CTX(ssl, vhost->tls.ssl_ctx);
151
152
  /*
153
   * OpenSSL's SSL_set_SSL_CTX does NOT copy the verify mode or client CA list
154
   * from the new context to the active SSL object! We must do it manually
155
   * so SNI vhosts can have different client cert requirements than the default vhost.
156
   */
157
0
  SSL_set_verify(ssl, SSL_CTX_get_verify_mode(vhost->tls.ssl_ctx),
158
0
           SSL_CTX_get_verify_callback(vhost->tls.ssl_ctx));
159
160
0
  if (SSL_CTX_get_client_CA_list(vhost->tls.ssl_ctx))
161
0
    SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(vhost->tls.ssl_ctx)));
162
163
0
  return SSL_TLSEXT_ERR_OK;
164
0
}
165
#endif
166
167
/*
168
 * this may now get called after the vhost creation, when certs become
169
 * available.
170
 */
171
int
172
lws_tls_server_certs_load(struct lws_vhost *vhost, struct lws *wsi,
173
        const char *cert, const char *private_key,
174
        const char *mem_cert, size_t mem_cert_len,
175
        const char *mem_privkey, size_t mem_privkey_len)
176
0
{
177
0
#if !defined(OPENSSL_NO_EC) && defined(LWS_HAVE_EC_KEY_new_by_curve_name) && \
178
0
    ((OPENSSL_VERSION_NUMBER < 0x30000000l) || \
179
0
     defined(LWS_SUPPRESS_DEPRECATED_API_WARNINGS))
180
0
  const char *ecdh_curve = "prime256v1";
181
0
#if !defined(LWS_WITH_BORINGSSL) && !defined(LWS_WITH_AWSLC) && defined(LWS_HAVE_SSL_EXTRA_CHAIN_CERTS)
182
0
  STACK_OF(X509) *extra_certs = NULL;
183
0
#endif
184
0
  EC_KEY *ecdh, *EC_key = NULL;
185
0
  EVP_PKEY *pkey;
186
0
  X509 *x = NULL;
187
0
  int ecdh_nid;
188
0
  int KeyType;
189
0
#endif
190
0
  unsigned long error;
191
0
  lws_filepos_t flen;
192
0
  uint8_t *p;
193
0
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
194
0
  int ret;
195
0
#endif
196
0
  char resolved_cert[256];
197
0
  char resolved_key[256];
198
199
0
  if (cert && private_key) {
200
0
    if (lws_tls_resolve_grace_period_certs(vhost->context, cert, private_key,
201
0
                   resolved_cert, sizeof(resolved_cert),
202
0
                   resolved_key, sizeof(resolved_key)) == 0) {
203
0
      cert = resolved_cert;
204
0
      private_key = resolved_key;
205
0
    }
206
0
  }
207
208
0
  int n = (int)lws_tls_generic_cert_checks(vhost, cert, private_key), m;
209
210
0
  if (!cert && !private_key)
211
0
    n = LWS_TLS_EXTANT_ALTERNATIVE;
212
213
0
  if (n == LWS_TLS_EXTANT_NO && (!mem_cert || !mem_privkey))
214
0
    return 0;
215
0
  if (n == LWS_TLS_EXTANT_NO)
216
0
    n = LWS_TLS_EXTANT_ALTERNATIVE;
217
218
0
  if (n == LWS_TLS_EXTANT_ALTERNATIVE && (!mem_cert || !mem_privkey))
219
0
    return 1; /* no alternative */
220
221
0
  if (n == LWS_TLS_EXTANT_ALTERNATIVE) {
222
223
0
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
224
225
    /*
226
     * Although we have prepared update certs, we no longer have
227
     * the rights to read our own cert + key we saved.
228
     *
229
     * If we were passed copies in memory buffers, use those
230
     * in favour of the filepaths we normally want.
231
     */
232
0
    cert = NULL;
233
0
    private_key = NULL;
234
0
  }
235
236
  /*
237
   * use the multi-cert interface for backwards compatibility in the
238
   * both simple files case
239
   */
240
241
0
  if (n != LWS_TLS_EXTANT_ALTERNATIVE && cert) {
242
243
    /* set the local certificate from CertFile */
244
0
    m = SSL_CTX_use_certificate_chain_file(vhost->tls.ssl_ctx, cert);
245
0
    if (m != 1) {
246
0
      const char *s;
247
0
      char buf[256];
248
0
      error = ERR_peek_error();
249
0
      s = ERR_error_string(LWS_TLS_ERR_CAST(ERR_get_error()), buf);
250
251
0
      lwsl_err("problem getting cert '%s' %lu: %s\n",
252
0
         cert, error, s);
253
254
0
      return 1;
255
0
    }
256
257
0
    if (!private_key) {
258
0
      lwsl_err("ssl private key not set\n");
259
0
      return 1;
260
0
    } else {
261
      /* set the private key from KeyFile */
262
0
      if (SSL_CTX_use_PrivateKey_file(vhost->tls.ssl_ctx, private_key,
263
0
              SSL_FILETYPE_PEM) != 1) {
264
0
        const char *s;
265
0
        char buf[256];
266
0
        error = ERR_peek_error();
267
0
        s = ERR_error_string(LWS_TLS_ERR_CAST(ERR_get_error()), buf);
268
0
        lwsl_err("ssl problem getting key '%s' %lu: %s\n",
269
0
           private_key, error, s);
270
0
        return 1;
271
0
      }
272
0
    }
273
274
0
    return 0;
275
0
  }
276
277
  /* otherwise allow for DER or PEM, file or memory image */
278
279
0
  if (lws_tls_alloc_pem_to_der_file(vhost->context, cert, mem_cert,
280
0
            mem_cert_len, &p, &flen)) {
281
0
    lwsl_err("%s: couldn't read cert file\n", __func__);
282
283
0
    return 1;
284
0
  }
285
286
0
#if !defined(USE_WOLFSSL)
287
0
  ret = SSL_CTX_use_certificate_ASN1(vhost->tls.ssl_ctx, SSL_SIZE_T_CAST(flen), p);
288
#else
289
  ret = wolfSSL_CTX_use_certificate_buffer(vhost->tls.ssl_ctx,
290
             (uint8_t *)p, (int)flen,
291
             WOLFSSL_FILETYPE_ASN1);
292
#endif
293
0
  lws_free_set_NULL(p);
294
0
  if (ret != 1) {
295
0
    lwsl_err("%s: Problem loading cert\n", __func__);
296
297
0
    return 1;
298
0
  }
299
300
0
  if (lws_tls_alloc_pem_to_der_file(vhost->context, private_key,
301
0
            mem_privkey, mem_privkey_len,
302
0
            &p, &flen)) {
303
0
    lwsl_notice("unable to convert memory privkey\n");
304
305
0
    return 1;
306
0
  }
307
308
0
#if !defined(USE_WOLFSSL)
309
0
  ret = SSL_CTX_use_PrivateKey_ASN1(EVP_PKEY_RSA, vhost->tls.ssl_ctx, p,
310
#if defined(LWS_WITH_BORINGSSL) || defined(LWS_WITH_AWSLC)
311
      (size_t)
312
#else
313
0
            (long)(long long)
314
0
#endif
315
0
            flen);
316
0
  if (ret != 1) {
317
0
    ret = SSL_CTX_use_PrivateKey_ASN1(EVP_PKEY_EC,
318
0
              vhost->tls.ssl_ctx, p,
319
#if defined(LWS_WITH_BORINGSSL) || defined(LWS_WITH_AWSLC)
320
      (size_t)
321
#else
322
0
            (long)(long long)
323
0
#endif
324
0
              flen);
325
0
  }
326
#else
327
  ret = wolfSSL_CTX_use_PrivateKey_buffer(vhost->tls.ssl_ctx, p, (long) flen,
328
            WOLFSSL_FILETYPE_ASN1);
329
#endif
330
0
  lws_free_set_NULL(p);
331
0
  if (ret != 1)  {
332
0
    lwsl_notice("unable to use memory privkey\n");
333
334
0
    return 1;
335
0
  }
336
337
#else
338
    /*
339
     * Although we have prepared update certs, we no longer have
340
     * the rights to read our own cert + key we saved.
341
     *
342
     * If we were passed copies in memory buffers, use those
343
     * instead.
344
     *
345
     * The passed memory-buffer cert image is in DER, and the
346
     * memory-buffer private key image is PEM.
347
     */
348
    if (lws_tls_alloc_pem_to_der_file(vhost->context, cert, mem_cert,
349
              mem_cert_len, &p, &flen)) {
350
      lwsl_err("%s: couldn't convert pem to der\n", __func__);
351
      return 1;
352
    }
353
#ifndef USE_WOLFSSL
354
    if (SSL_CTX_use_certificate_ASN1(vhost->tls.ssl_ctx,
355
             (int)flen,
356
             (uint8_t *)p) != 1) {
357
#else
358
    if (wolfSSL_CTX_use_certificate_buffer(vhost->tls.ssl_ctx,
359
             (uint8_t *)p,
360
             (int)flen,
361
             WOLFSSL_FILETYPE_ASN1) != 1) {
362
363
#endif
364
      lwsl_err("Problem loading update cert\n");
365
366
      return 1;
367
    }
368
369
    if (lws_tls_alloc_pem_to_der_file(vhost->context, NULL,
370
              mem_privkey, mem_privkey_len,
371
              &p, &flen)) {
372
      lwsl_notice("unable to convert memory privkey\n");
373
374
      return 1;
375
    }
376
#ifndef USE_WOLFSSL
377
    if (SSL_CTX_use_PrivateKey_ASN1(EVP_PKEY_RSA,
378
            vhost->tls.ssl_ctx, p,
379
            (long)(long long)flen) != 1) {
380
#else
381
    if (wolfSSL_CTX_use_PrivateKey_buffer(vhost->tls.ssl_ctx, p,
382
              (long)flen, WOLFSSL_FILETYPE_ASN1) != 1) {
383
#endif
384
      lwsl_notice("unable to use memory privkey\n");
385
386
      return 1;
387
    }
388
389
    goto check_key;
390
  }
391
392
  /* set the local certificate from CertFile */
393
  m = SSL_CTX_use_certificate_chain_file(vhost->tls.ssl_ctx, cert);
394
  if (m != 1) {
395
    char buf[256];
396
    error = ERR_get_error();
397
    lwsl_err("problem getting cert '%s' %lu: %s\n",
398
       cert, error, ERR_error_string(LWS_TLS_ERR_CAST(error), buf));
399
400
    return 1;
401
  }
402
403
  if (n == LWS_TLS_EXTANT_ALTERNATIVE || !private_key) {
404
    lwsl_err("ssl private key not set\n");
405
    return 1;
406
  } else {
407
    /* set the private key from KeyFile */
408
    if (SSL_CTX_use_PrivateKey_file(vhost->tls.ssl_ctx, private_key,
409
                  SSL_FILETYPE_PEM) != 1) {
410
      char buf[256];
411
      error = ERR_get_error();
412
      lwsl_err("ssl problem getting key '%s' %lu: %s\n",
413
         private_key, error,
414
         ERR_error_string(LWS_TLS_ERR_CAST(error), buf));
415
      return 1;
416
    }
417
  }
418
419
check_key:
420
#endif
421
422
  /* verify private key */
423
0
  if (!SSL_CTX_check_private_key(vhost->tls.ssl_ctx)) {
424
0
    lwsl_err("Private SSL key doesn't match cert\n");
425
426
0
    return 1;
427
0
  }
428
429
430
0
#if !defined(OPENSSL_NO_EC) && defined(LWS_HAVE_EC_KEY_new_by_curve_name) && \
431
0
    ((OPENSSL_VERSION_NUMBER < 0x30000000l) || \
432
0
     defined(LWS_SUPPRESS_DEPRECATED_API_WARNINGS))
433
0
  if (vhost->tls.ecdh_curve[0])
434
0
    ecdh_curve = vhost->tls.ecdh_curve;
435
436
0
  ecdh_nid = OBJ_sn2nid(ecdh_curve);
437
0
  if (NID_undef == ecdh_nid) {
438
0
    lwsl_err("SSL: Unknown curve name '%s'", ecdh_curve);
439
0
    return 1;
440
0
  }
441
442
0
  ecdh = EC_KEY_new_by_curve_name(ecdh_nid);
443
0
  if (NULL == ecdh) {
444
0
    lwsl_err("SSL: Unable to create curve '%s'", ecdh_curve);
445
0
    return 1;
446
0
  }
447
0
  SSL_CTX_set_tmp_ecdh(vhost->tls.ssl_ctx, ecdh);
448
0
  EC_KEY_free(ecdh);
449
450
0
  SSL_CTX_set_options(vhost->tls.ssl_ctx, SSL_OP_SINGLE_ECDH_USE);
451
452
0
  lwsl_notice(" SSL ECDH curve '%s'\n", ecdh_curve);
453
454
0
  if (lws_check_opt(vhost->context->options, LWS_SERVER_OPTION_SSL_ECDH))
455
0
    lwsl_notice(" Using ECDH certificate support\n");
456
457
  /* Get X509 certificate from ssl context */
458
0
#if !defined(LWS_WITH_BORINGSSL) && !defined(LWS_WITH_AWSLC) && !defined(USE_WOLFSSL)
459
#if !defined(LWS_HAVE_SSL_EXTRA_CHAIN_CERTS)
460
  x = sk_X509_value(vhost->tls.ssl_ctx->extra_certs, 0);
461
#else
462
0
  SSL_CTX_get_extra_chain_certs_only(vhost->tls.ssl_ctx, &extra_certs);
463
0
  if (extra_certs)
464
0
    x = sk_X509_value(extra_certs, 0);
465
0
  else
466
0
    lwsl_info("%s: no extra certs\n", __func__);
467
0
#endif
468
0
  if (!x) {
469
    //lwsl_err("%s: x is NULL\n", __func__);
470
0
    goto post_ecdh;
471
0
  }
472
#else
473
  return 0;
474
#endif /* !boringssl */
475
476
  /* Get the public key from certificate */
477
0
  pkey = X509_get_pubkey(x);
478
0
  if (!pkey) {
479
0
    lwsl_err("%s: pkey is NULL\n", __func__);
480
481
0
    return 1;
482
0
  }
483
  /* Get the key type */
484
0
  KeyType = EVP_PKEY_type(EVP_PKEY_id(pkey));
485
486
0
  if (EVP_PKEY_EC != KeyType) {
487
0
    lwsl_notice("Key type is not EC\n");
488
0
    return 0;
489
0
  }
490
  /* Get the key */
491
0
  EC_key = EVP_PKEY_get1_EC_KEY(pkey);
492
  /* Set ECDH parameter */
493
0
  if (!EC_key) {
494
0
    lwsl_err("%s: ECDH key is NULL \n", __func__);
495
0
    return 1;
496
0
  }
497
0
  SSL_CTX_set_tmp_ecdh(vhost->tls.ssl_ctx, EC_key);
498
499
0
  EC_KEY_free(EC_key);
500
501
0
#if !defined(OPENSSL_NO_EC) && !defined(LWS_WITH_BORINGSSL) && !defined(LWS_WITH_AWSLC) && !defined(USE_WOLFSSL)
502
0
post_ecdh:
503
0
#endif
504
0
  vhost->tls.skipped_certs = 0;
505
#else
506
  lwsl_notice(" OpenSSL doesn't support ECDH\n");
507
#endif
508
509
0
  return 0;
510
0
}
511
512
513
514
int
515
lws_tls_vhost_backend_create_ctx(struct lws_vhost *vhost)
516
0
{
517
0
  unsigned long error;
518
0
  SSL_METHOD *method = (SSL_METHOD *)SSLv23_server_method();
519
0
  struct lws_vhost_tls *tls = &vhost->tls;
520
521
0
  if (!method) {
522
0
    const char *s;
523
0
    char buf[256];
524
0
    error = ERR_peek_error();
525
0
    s = ERR_error_string(LWS_TLS_ERR_CAST(ERR_get_error()), buf);
526
527
0
    lwsl_err("problem creating ssl method %lu: %s\n",
528
0
        error, s);
529
0
    return 1;
530
0
  }
531
0
  tls->ssl_ctx = SSL_CTX_new(method); /* create context */
532
0
  if (!tls->ssl_ctx) {
533
0
    const char *s;
534
0
    char buf[256];
535
536
0
    error = ERR_peek_error();
537
0
    s = ERR_error_string(LWS_TLS_ERR_CAST(ERR_get_error()), buf);
538
0
    lwsl_err("problem creating ssl context %lu: %s\n",
539
0
        error, s);
540
0
    return 1;
541
0
  }
542
  /* Added for sniffing packets on hub side */
543
0
#if defined(LWS_WITH_TLS_KEYLOG) && \
544
0
    defined(LWS_WITH_TLS) && (defined(LWS_WITH_CLIENT) || defined(LWS_WITH_SERVER))
545
0
  SSL_CTX_set_keylog_callback(tls->ssl_ctx, lws_klog_dump);
546
0
#endif
547
548
0
  SSL_CTX_set_ex_data(tls->ssl_ctx,
549
0
          openssl_SSL_CTX_private_data_index,
550
0
          (char *)vhost->context);
551
  /* Disable SSLv2 and SSLv3 */
552
0
  SSL_CTX_set_options(tls->ssl_ctx, SSL_OP_NO_SSLv2 |
553
0
            SSL_OP_NO_SSLv3);
554
0
#ifdef SSL_OP_NO_COMPRESSION
555
0
  SSL_CTX_set_options(tls->ssl_ctx, SSL_OP_NO_COMPRESSION);
556
0
#endif
557
0
  if (lws_check_opt(vhost->options,
558
0
                    LWS_SERVER_OPTION_OPENSSL_AUTO_DH_PARAMETERS))
559
0
#if defined(LWS_HAVE_SSL_CTX_SET_ECDH_AUTO) || defined(LWS_WITH_BORINGSSL)
560
0
    (void)SSL_CTX_set_ecdh_auto(tls->ssl_ctx, 1);
561
#else
562
    SSL_CTX_set_dh_auto(tls->ssl_ctx, 1);
563
#endif
564
565
0
  SSL_CTX_set_options(tls->ssl_ctx, SSL_OP_SINGLE_DH_USE);
566
0
  SSL_CTX_set_options(tls->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
567
568
0
  if (tls->cfg_tls_ciphers_iana) {
569
0
    char *p = lws_strdup(tls->cfg_tls_ciphers_iana);
570
0
    if (p) {
571
0
      char *q = p;
572
0
      while (*q) {
573
0
        if (*q == ',')
574
0
          *q = ':';
575
0
        q++;
576
0
      }
577
0
      SSL_CTX_set_cipher_list(tls->ssl_ctx, p);
578
0
#if defined(LWS_HAVE_SSL_CTX_set_ciphersuites)
579
0
      SSL_CTX_set_ciphersuites(tls->ssl_ctx, p);
580
0
#endif
581
0
      lws_free(p);
582
0
    }
583
0
  } else if (tls->cfg_ssl_cipher_list)
584
0
    SSL_CTX_set_cipher_list(tls->ssl_ctx, tls->cfg_ssl_cipher_list);
585
586
0
#if defined(LWS_HAVE_SSL_CTX_set_ciphersuites)
587
0
  if (tls->cfg_tls1_3_plus_cipher_list)
588
0
    SSL_CTX_set_ciphersuites(tls->ssl_ctx,
589
0
           tls->cfg_tls1_3_plus_cipher_list);
590
0
#endif
591
592
0
#if !defined(OPENSSL_NO_TLSEXT)
593
0
  SSL_CTX_set_tlsext_servername_callback(tls->ssl_ctx,
594
0
                 lws_ssl_server_name_cb);
595
0
  SSL_CTX_set_tlsext_servername_arg(tls->ssl_ctx, vhost->context);
596
0
#endif
597
598
0
  if (tls->cfg_ssl_ca_filepath) {
599
#if defined(LWS_HAVE_SSL_CTX_load_verify_file)
600
      if (!SSL_CTX_load_verify_file(tls->ssl_ctx,
601
              tls->cfg_ssl_ca_filepath)) {
602
#else
603
0
      if (!SSL_CTX_load_verify_locations(tls->ssl_ctx,
604
0
             tls->cfg_ssl_ca_filepath, NULL)) {
605
0
#endif
606
0
      lwsl_err("%s: SSL_CTX_load_verify_locations unhappy\n",
607
0
         __func__);
608
0
    } else {
609
      /*
610
       * Provide the CA list to the client so it knows what client certs to send
611
       */
612
0
      STACK_OF(X509_NAME) *calist = SSL_load_client_CA_file(tls->cfg_ssl_ca_filepath);
613
0
      if (!calist) {
614
0
        lwsl_err("%s: SSL_load_client_CA_file failed to load %s\n", __func__, tls->cfg_ssl_ca_filepath);
615
0
      } else {
616
0
        lwsl_notice("%s: Loaded %d CAs for client CA list from %s\n", __func__, (int)sk_X509_NAME_num(calist), tls->cfg_ssl_ca_filepath);
617
0
        SSL_CTX_set_client_CA_list(tls->ssl_ctx, calist);
618
0
      }
619
0
    }
620
0
  } else if (tls->cfg_server_ssl_ca_mem && tls->cfg_server_ssl_ca_mem_len) {
621
0
    lws_filepos_t amount = 0;
622
0
    const uint8_t *up;
623
0
    uint8_t *up1;
624
625
0
    if (lws_tls_alloc_pem_to_der_file(vhost->context, NULL, tls->cfg_server_ssl_ca_mem,
626
0
              tls->cfg_server_ssl_ca_mem_len, &up1, &amount)) {
627
0
      lwsl_err("%s: Unable to decode x.509 mem\n", __func__);
628
0
    } else {
629
0
      up = up1;
630
#if defined(USE_WOLFSSL)
631
      X509 *client_CA = d2i_X509(NULL, &up, (int)amount);
632
#else
633
0
      X509 *client_CA = d2i_X509(NULL, &up, (long)amount);
634
0
#endif
635
0
      if (!client_CA) {
636
0
        lwsl_err("server CA: x509 parse failed\n");
637
0
      } else {
638
0
        X509_STORE *x509_store = X509_STORE_new();
639
0
        if (!X509_STORE_add_cert(x509_store, client_CA)) {
640
0
          X509_STORE_free(x509_store);
641
0
          lwsl_err("Unable to load SSL server certs from "
642
0
             "ssl_ca_mem -- server ssl isn't going to work\n");
643
0
        } else {
644
0
          SSL_CTX_set_cert_store(tls->ssl_ctx, x509_store);
645
0
          STACK_OF(X509_NAME) *calist = sk_X509_NAME_new_null();
646
0
          if (calist) {
647
0
            X509_NAME *name = X509_get_subject_name(client_CA);
648
0
            if (name)
649
0
              sk_X509_NAME_push(calist, X509_NAME_dup(name));
650
0
            SSL_CTX_set_client_CA_list(tls->ssl_ctx, calist);
651
0
          }
652
0
          lwsl_notice("%s: vh %s: mem CA OK\n", __func__, vhost->name);
653
0
        }
654
0
        X509_free(client_CA);
655
0
      }
656
0
      lws_free(up1);
657
0
    }
658
0
  }
659
660
0
  SSL_OPT_TYPE ssl_options_set_value = (SSL_OPT_TYPE) tls->ssl_options_set;
661
662
0
  if (tls->ssl_options_set)
663
0
    SSL_CTX_set_options(tls->ssl_ctx, ssl_options_set_value);
664
665
0
#if (OPENSSL_VERSION_NUMBER >= 0x009080df) && !defined(USE_WOLFSSL)
666
667
/* SSL_clear_options introduced in 0.9.8m */
668
0
  SSL_OPT_TYPE ssl_options_clear_value = (SSL_OPT_TYPE) tls->ssl_options_clear;
669
670
0
  if (tls->ssl_options_clear) {
671
0
    SSL_CTX_clear_options(tls->ssl_ctx, ssl_options_clear_value);
672
0
  }
673
674
0
  lwsl_info(" SSL options 0x%lX\n",
675
0
      (unsigned long)SSL_CTX_get_options(tls->ssl_ctx));
676
0
#endif
677
678
0
  return 0;
679
0
}
680
681
int
682
lws_tls_server_vhost_backend_init(const struct lws_context_creation_info *info,
683
          struct lws_vhost *vhost, struct lws *wsi)
684
0
{
685
0
  int n, m;
686
687
0
  if (lws_tls_vhost_backend_create_ctx(vhost))
688
0
    return 1;
689
690
0
  if (!vhost->tls.use_ssl ||
691
0
      (!info->ssl_cert_filepath && !info->server_ssl_cert_mem))
692
0
    return 0;
693
694
0
  n = (int)lws_tls_generic_cert_checks(vhost, info->ssl_cert_filepath,
695
0
               info->ssl_private_key_filepath);
696
697
0
  if (n == LWS_TLS_EXTANT_NO &&
698
0
      (vhost->options & LWS_SERVER_OPTION_IGNORE_MISSING_CERT)) {
699
0
    lwsl_notice("No certs found, continuing without SSL_CTX\n");
700
0
    SSL_CTX_free(vhost->tls.ssl_ctx);
701
0
    vhost->tls.ssl_ctx = NULL;
702
0
    return 0;
703
0
  }
704
705
0
  lws_ssl_bind_passphrase(vhost->tls.ssl_ctx, 0, info);
706
707
0
  m = lws_tls_server_certs_load(vhost, wsi, info->ssl_cert_filepath,
708
0
           info->ssl_private_key_filepath,
709
0
           info->server_ssl_cert_mem,
710
0
           info->server_ssl_cert_mem_len,
711
0
           info->server_ssl_private_key_mem,
712
0
           info->server_ssl_private_key_mem_len);
713
714
0
  if (m && n != LWS_TLS_EXTANT_NO)
715
0
    return 1;
716
717
#if defined(LWS_ROLE_QUIC) && !defined(LWS_WITH_MBEDTLS) && !defined(LWS_WITH_WOLFSSL) && !defined(LWS_WITH_SCHANNEL) && !defined(LWS_WITH_GNUTLS) && !defined(LWS_WITH_BEARSSL)
718
  lws_tls_quic_vhost_init(vhost->tls.ssl_ctx);
719
#endif
720
721
0
  return 0;
722
0
}
723
724
int
725
lws_tls_server_new_nonblocking(struct lws *wsi, lws_sockfd_type accept_fd)
726
0
{
727
0
#if !defined(USE_WOLFSSL)
728
0
  BIO *bio;
729
0
#endif
730
731
0
  errno = 0;
732
0
  ERR_clear_error();
733
0
  wsi->tls.ctx_ref = lws_tls_ctx_ref_get(wsi->a.vhost);
734
0
  wsi->tls.ssl = SSL_new(wsi->tls.ctx_ref ? wsi->tls.ctx_ref->ctx : wsi->a.vhost->tls.ssl_ctx);
735
0
  if (wsi->tls.ssl == NULL) {
736
0
    lwsl_err("SSL_new failed: %d (errno %d)\n",
737
0
       lws_ssl_get_error(wsi, 0), errno);
738
739
0
    lws_tls_err_describe_clear();
740
0
    return 1;
741
0
  }
742
743
0
  SSL_set_ex_data(wsi->tls.ssl, openssl_websocket_private_data_index, wsi);
744
0
  SSL_set_fd(wsi->tls.ssl, (int)(lws_intptr_t)accept_fd);
745
746
#ifdef USE_WOLFSSL
747
#ifdef USE_OLD_CYASSL
748
  CyaSSL_set_using_nonblock(wsi->tls.ssl, 1);
749
#else
750
  wolfSSL_set_using_nonblock(wsi->tls.ssl, 1);
751
#endif
752
#else
753
754
0
  SSL_set_mode(wsi->tls.ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
755
0
           SSL_MODE_RELEASE_BUFFERS);
756
0
  bio = SSL_get_rbio(wsi->tls.ssl);
757
0
  if (bio)
758
0
    BIO_set_nbio(bio, 1); /* nonblocking */
759
0
  else
760
0
    lwsl_notice("NULL rbio\n");
761
0
  bio = SSL_get_wbio(wsi->tls.ssl);
762
0
  if (bio)
763
0
    BIO_set_nbio(bio, 1); /* nonblocking */
764
0
  else
765
0
    lwsl_notice("NULL rbio\n");
766
0
#endif
767
768
0
#if defined (LWS_HAVE_SSL_SET_INFO_CALLBACK)
769
0
    if (wsi->a.vhost->tls.ssl_info_event_mask)
770
0
      SSL_set_info_callback(wsi->tls.ssl, lws_ssl_info_callback);
771
0
#endif
772
773
0
  return 0;
774
0
}
775
776
enum lws_ssl_capable_status
777
lws_tls_server_abort_connection(struct lws *wsi)
778
0
{
779
0
  if (wsi->tls.use_ssl)
780
0
    SSL_shutdown(wsi->tls.ssl);
781
0
  SSL_free(wsi->tls.ssl);
782
783
0
  return LWS_SSL_CAPABLE_DONE;
784
0
}
785
786
#if defined(LWS_WITH_TCP_TLS)
787
enum lws_ssl_capable_status
788
lws_tls_server_accept(struct lws *wsi)
789
0
{
790
0
  struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
791
0
  union lws_tls_cert_info_results ir;
792
0
  int m, n;
793
794
0
  errno = 0;
795
0
  ERR_clear_error();
796
797
#if defined(LWS_WITH_LATENCY)
798
  lws_usec_t _o_ssl_acc_start = lws_now_usecs();
799
#endif
800
801
0
  n = SSL_accept(wsi->tls.ssl);
802
803
#if defined(LWS_WITH_LATENCY)
804
  {
805
    unsigned int ms = (unsigned int)((lws_now_usecs() - _o_ssl_acc_start) / 1000);
806
    if (ms > 2 && !wsi->tls.ssl_accept_in_bg)
807
      lws_latency_note(pt, _o_ssl_acc_start, 2000, "ssl_accept:%dms", ms);
808
  }
809
#endif
810
811
0
  wsi->skip_fallback = 1;
812
813
0
  if (n == 1) {
814
0
    n = lws_tls_peer_cert_info(wsi, LWS_TLS_CERT_INFO_COMMON_NAME, &ir,
815
0
             sizeof(ir.ns.name));
816
0
    if (!n)
817
0
      lwsl_notice("%s: client cert CN '%s'\n", __func__,
818
0
            ir.ns.name);
819
0
    else
820
0
      lwsl_info("%s: no client cert CN\n", __func__);
821
822
0
    lws_openssl_describe_cipher(wsi);
823
824
0
    if (SSL_pending(wsi->tls.ssl) &&
825
0
        lws_dll2_is_detached(&wsi->tls.dll_pending_tls)) {
826
0
      if (!wsi->tls.ssl_accept_in_bg) {
827
0
        lws_dll2_add_head(&wsi->tls.dll_pending_tls,
828
0
              &pt->tls.dll_pending_tls_owner);
829
0
      }
830
0
    }
831
832
0
    return LWS_SSL_CAPABLE_DONE;
833
0
  }
834
835
0
  m = lws_ssl_get_error(wsi, n);
836
0
  lws_tls_err_describe_clear();
837
838
0
  if (m == SSL_ERROR_SYSCALL || m == SSL_ERROR_SSL)
839
0
    return LWS_SSL_CAPABLE_ERROR;
840
841
0
  if (m == SSL_ERROR_WANT_READ ||
842
0
      (m != SSL_ERROR_ZERO_RETURN && SSL_want_read(wsi->tls.ssl))) {
843
0
    if (!wsi->tls.ssl_accept_in_bg && lws_change_pollfd(wsi, 0, LWS_POLLIN)) {
844
0
      lwsl_info("%s: WANT_READ change_pollfd failed\n",
845
0
          __func__);
846
0
      return LWS_SSL_CAPABLE_ERROR;
847
0
    }
848
849
0
    lwsl_info("SSL_ERROR_WANT_READ: m %d\n", m);
850
0
    return LWS_SSL_CAPABLE_MORE_SERVICE_READ;
851
0
  }
852
0
  if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl)) {
853
0
    lwsl_debug("%s: WANT_WRITE\n", __func__);
854
855
0
    if (!wsi->tls.ssl_accept_in_bg && lws_change_pollfd(wsi, 0, LWS_POLLOUT)) {
856
0
      lwsl_info("%s: WANT_WRITE change_pollfd failed\n",
857
0
          __func__);
858
0
      return LWS_SSL_CAPABLE_ERROR;
859
0
    }
860
0
    return LWS_SSL_CAPABLE_MORE_SERVICE_WRITE;
861
0
  }
862
863
0
  return LWS_SSL_CAPABLE_ERROR;
864
0
}
865
#endif
866
867
#if defined(LWS_WITH_ACME)
868
static int
869
lws_tls_openssl_rsa_new_key(RSA **rsa, int bits)
870
{
871
  BIGNUM *bn = BN_new();
872
  int n;
873
874
  if (!bn)
875
    return 1;
876
877
  if (BN_set_word(bn, RSA_F4) != 1) {
878
    BN_free(bn);
879
    return 1;
880
  }
881
882
  *rsa = RSA_new();
883
  if (!*rsa) {
884
    BN_free(bn);
885
    return 1;
886
  }
887
888
  n = RSA_generate_key_ex(*rsa, bits, bn, NULL);
889
  BN_free(bn);
890
  if (n == 1)
891
    return 0;
892
893
  RSA_free(*rsa);
894
  *rsa = NULL;
895
896
  return 1;
897
}
898
899
struct lws_tls_ss_pieces {
900
  X509 *x509;
901
  EVP_PKEY *pkey;
902
  RSA *rsa;
903
};
904
905
int
906
lws_tls_acme_sni_cert_create(struct lws_vhost *vhost, const char *san_a,
907
           const char *san_b)
908
{
909
  GENERAL_NAMES *gens = sk_GENERAL_NAME_new_null();
910
  GENERAL_NAME *gen = NULL;
911
  ASN1_IA5STRING *ia5 = NULL;
912
  X509_NAME *name;
913
914
  if (!gens)
915
    return 1;
916
917
  vhost->tls.ss = lws_zalloc(sizeof(*vhost->tls.ss), "sni cert");
918
  if (!vhost->tls.ss) {
919
    GENERAL_NAMES_free(gens);
920
    return 1;
921
  }
922
923
  vhost->tls.ss->x509 = X509_new();
924
  if (!vhost->tls.ss->x509)
925
    goto bail;
926
927
  ASN1_INTEGER_set(X509_get_serialNumber(vhost->tls.ss->x509), 1);
928
  X509_gmtime_adj(X509_get_notBefore(vhost->tls.ss->x509), 0);
929
  X509_gmtime_adj(X509_get_notAfter(vhost->tls.ss->x509), 3600);
930
931
  vhost->tls.ss->pkey = EVP_PKEY_new();
932
  if (!vhost->tls.ss->pkey)
933
    goto bail0;
934
935
  if (lws_tls_openssl_rsa_new_key(&vhost->tls.ss->rsa, 4096))
936
    goto bail1;
937
938
  if (!EVP_PKEY_assign_RSA(vhost->tls.ss->pkey, vhost->tls.ss->rsa))
939
    goto bail2;
940
941
  X509_set_pubkey(vhost->tls.ss->x509, vhost->tls.ss->pkey);
942
943
  name = X509_get_subject_name(vhost->tls.ss->x509);
944
  X509_NAME_add_entry_by_txt(name, "C",  MBSTRING_ASC,
945
           (unsigned char *)"GB",          -1, -1, 0);
946
  X509_NAME_add_entry_by_txt(name, "O",  MBSTRING_ASC,
947
           (unsigned char *)"somecompany", -1, -1, 0);
948
  if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_UTF8,
949
           (unsigned char *)"temp.acme.invalid",
950
                   -1, -1, 0) != 1) {
951
    lwsl_notice("failed to add CN\n");
952
    goto bail2;
953
  }
954
  X509_set_issuer_name(vhost->tls.ss->x509, name);
955
956
  /* add the SAN payloads */
957
958
  gen = GENERAL_NAME_new();
959
  ia5 = ASN1_IA5STRING_new();
960
  if (!ASN1_STRING_set(ia5, san_a, -1)) {
961
    lwsl_notice("failed to set ia5\n");
962
    GENERAL_NAME_free(gen);
963
    goto bail2;
964
  }
965
  GENERAL_NAME_set0_value(gen, GEN_DNS, ia5);
966
  sk_GENERAL_NAME_push(gens, gen);
967
968
  if (X509_add1_ext_i2d(vhost->tls.ss->x509, NID_subject_alt_name,
969
          gens, 0, X509V3_ADD_APPEND) != 1)
970
    goto bail2;
971
972
  GENERAL_NAMES_free(gens);
973
974
  if (san_b && san_b[0]) {
975
    gens = sk_GENERAL_NAME_new_null();
976
    gen = GENERAL_NAME_new();
977
    ia5 = ASN1_IA5STRING_new();
978
    if (!ASN1_STRING_set(ia5, san_a, -1)) {
979
      lwsl_notice("failed to set ia5\n");
980
      GENERAL_NAME_free(gen);
981
      goto bail2;
982
    }
983
    GENERAL_NAME_set0_value(gen, GEN_DNS, ia5);
984
    sk_GENERAL_NAME_push(gens, gen);
985
986
    if (X509_add1_ext_i2d(vhost->tls.ss->x509, NID_subject_alt_name,
987
            gens, 0, X509V3_ADD_APPEND) != 1)
988
      goto bail2;
989
990
    GENERAL_NAMES_free(gens);
991
  }
992
993
  /* sign it with our private key */
994
  if (!X509_sign(vhost->tls.ss->x509, vhost->tls.ss->pkey, EVP_sha256()))
995
    goto bail2;
996
997
#if 0
998
  {/* useful to take a sample of a working cert for mbedtls to crib */
999
    FILE *fp = fopen("/tmp/acme-temp-cert", "w+");
1000
1001
    i2d_X509_fp(fp, vhost->tls.ss->x509);
1002
    fclose(fp);
1003
  }
1004
#endif
1005
1006
  /* tell the vhost to use our crafted certificate */
1007
  SSL_CTX_use_certificate(vhost->tls.ssl_ctx, vhost->tls.ss->x509);
1008
  /* and to use our generated private key */
1009
  SSL_CTX_use_PrivateKey(vhost->tls.ssl_ctx, vhost->tls.ss->pkey);
1010
1011
  return 0;
1012
1013
bail2:
1014
  RSA_free(vhost->tls.ss->rsa);
1015
bail1:
1016
  EVP_PKEY_free(vhost->tls.ss->pkey);
1017
bail0:
1018
  X509_free(vhost->tls.ss->x509);
1019
bail:
1020
  lws_free(vhost->tls.ss);
1021
  GENERAL_NAMES_free(gens);
1022
1023
  return 1;
1024
}
1025
1026
void
1027
lws_tls_acme_sni_cert_destroy(struct lws_vhost *vhost)
1028
{
1029
  if (!vhost->tls.ss)
1030
    return;
1031
1032
  EVP_PKEY_free(vhost->tls.ss->pkey);
1033
  X509_free(vhost->tls.ss->x509);
1034
  lws_free_set_NULL(vhost->tls.ss);
1035
}
1036
1037
static int
1038
lws_tls_openssl_add_nid(X509_NAME *name, int nid, const char *value)
1039
{
1040
  X509_NAME_ENTRY *e;
1041
  int n;
1042
1043
  if (!value || value[0] == '\0')
1044
    value = "none";
1045
1046
  e = X509_NAME_ENTRY_create_by_NID(NULL, nid, MBSTRING_ASC,
1047
            (const unsigned char *)value, -1);
1048
  if (!e)
1049
    return 1;
1050
  n = X509_NAME_add_entry(name, e, -1, 0);
1051
  X509_NAME_ENTRY_free(e);
1052
1053
  return n != 1;
1054
}
1055
1056
static int nid_list[] = {
1057
  NID_countryName,    /* LWS_TLS_REQ_ELEMENT_COUNTRY */
1058
  NID_stateOrProvinceName,  /* LWS_TLS_REQ_ELEMENT_STATE */
1059
  NID_localityName,   /* LWS_TLS_REQ_ELEMENT_LOCALITY */
1060
  NID_organizationName,   /* LWS_TLS_REQ_ELEMENT_ORGANIZATION */
1061
  NID_commonName,     /* LWS_TLS_REQ_ELEMENT_COMMON_NAME */
1062
  NID_subject_alt_name,   /* LWS_TLS_REQ_ELEMENT_SUBJECT_ALT_NAME */
1063
  NID_pkcs9_emailAddress,   /* LWS_TLS_REQ_ELEMENT_EMAIL */
1064
};
1065
1066
int
1067
lws_tls_acme_sni_csr_create(struct lws_context *context, const char *elements[],
1068
          uint8_t *csr, size_t csr_len, char **privkey_pem,
1069
          size_t *privkey_len)
1070
{
1071
  uint8_t *csr_in = csr;
1072
  RSA *rsakey;
1073
  X509_REQ *req;
1074
  X509_NAME *subj;
1075
  EVP_PKEY *pkey;
1076
  char *p, *end;
1077
  BIO *bio;
1078
  long bio_len;
1079
  int n, ret = -1;
1080
1081
  if (lws_tls_openssl_rsa_new_key(&rsakey, 4096))
1082
    return -1;
1083
1084
  pkey = EVP_PKEY_new();
1085
  if (!pkey)
1086
    goto bail0;
1087
  if (!EVP_PKEY_set1_RSA(pkey, rsakey))
1088
    goto bail1;
1089
1090
  req = X509_REQ_new();
1091
  if (!req)
1092
          goto bail1;
1093
1094
  X509_REQ_set_pubkey(req, pkey);
1095
1096
  subj = X509_NAME_new();
1097
  if (!subj)
1098
    goto bail2;
1099
1100
  for (n = 0; n < LWS_TLS_REQ_ELEMENT_COUNT; n++)
1101
    if (elements[n] &&
1102
      lws_tls_openssl_add_nid(subj, nid_list[n],
1103
        elements[n])) {
1104
        lwsl_notice("%s: failed to add element %d\n",
1105
            __func__, n);
1106
      goto bail3;
1107
    }
1108
1109
  if (X509_REQ_set_subject_name(req, subj) != 1)
1110
    goto bail3;
1111
1112
  if (elements[LWS_TLS_REQ_ELEMENT_SUBJECT_ALT_NAME]) {
1113
    STACK_OF(X509_EXTENSION) *exts;
1114
    X509_EXTENSION *ext;
1115
    char san[256];
1116
1117
    exts = sk_X509_EXTENSION_new_null();
1118
    if (!exts)
1119
      goto bail3;
1120
1121
    lws_snprintf(san, sizeof(san), "DNS:%s,DNS:%s",
1122
        elements[LWS_TLS_REQ_ELEMENT_COMMON_NAME],
1123
        elements[LWS_TLS_REQ_ELEMENT_SUBJECT_ALT_NAME]);
1124
1125
    ext = X509V3_EXT_conf_nid(NULL, NULL, NID_subject_alt_name,
1126
        san);
1127
    if (!ext) {
1128
      sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
1129
      goto bail3;
1130
    }
1131
    sk_X509_EXTENSION_push(exts, ext);
1132
1133
    if (!X509_REQ_add_extensions(req, exts)) {
1134
      sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
1135
      goto bail3;
1136
    }
1137
    sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
1138
  }
1139
1140
  if (!X509_REQ_sign(req, pkey, EVP_sha256()))
1141
    goto bail3;
1142
1143
  /*
1144
   * issue the CSR as PEM to a BIO, and translate to b64urlenc without
1145
   * headers, trailers, or whitespace
1146
   */
1147
1148
  bio = BIO_new(BIO_s_mem());
1149
  if (!bio)
1150
    goto bail3;
1151
1152
  if (PEM_write_bio_X509_REQ(bio, req) != 1) {
1153
    BIO_free(bio);
1154
    goto bail3;
1155
  }
1156
1157
  bio_len = BIO_get_mem_data(bio, &p);
1158
  end = p + bio_len;
1159
1160
  /* strip the header line */
1161
  while (p < end && *p != '\n')
1162
    p++;
1163
1164
  while (p < end && csr_len) {
1165
    if (*p == '\n') {
1166
      p++;
1167
      continue;
1168
    }
1169
1170
    if (*p == '-')
1171
      break;
1172
1173
    if (*p == '+')
1174
      *csr++ = '-';
1175
    else
1176
      if (*p == '/')
1177
        *csr++ = '_';
1178
      else
1179
        *csr++ = (uint8_t)*p;
1180
    p++;
1181
    csr_len--;
1182
  }
1183
  BIO_free(bio);
1184
  if (!csr_len) {
1185
    lwsl_notice("%s: need %ld for CSR\n", __func__, bio_len);
1186
    goto bail3;
1187
  }
1188
1189
  /*
1190
   * Also return the private key as a PEM in memory
1191
   * (platform may not have a filesystem)
1192
   */
1193
  bio = BIO_new(BIO_s_mem());
1194
  if (!bio)
1195
    goto bail3;
1196
1197
  if (PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, 0, NULL) != 1) {
1198
    BIO_free(bio);
1199
    goto bail3;
1200
  }
1201
  bio_len = BIO_get_mem_data(bio, &p);
1202
  *privkey_pem = malloc((unsigned long)bio_len); /* malloc so user code can own / free */
1203
  *privkey_len = (size_t)bio_len;
1204
  if (!*privkey_pem) {
1205
    lwsl_notice("%s: need %ld for private key\n", __func__,
1206
          bio_len);
1207
    BIO_free(bio);
1208
    goto bail3;
1209
  }
1210
  memcpy(*privkey_pem, p, (unsigned int)(int)(long long)bio_len);
1211
  BIO_free(bio);
1212
1213
  ret = lws_ptr_diff(csr, csr_in);
1214
1215
bail3:
1216
  X509_NAME_free(subj);
1217
bail2:
1218
  X509_REQ_free(req);
1219
bail1:
1220
  EVP_PKEY_free(pkey);
1221
bail0:
1222
  RSA_free(rsakey);
1223
1224
  return ret;
1225
}
1226
1227
int
1228
lws_tls_acme_sni_csr_create_ecdsa(struct lws_context *context, const char *elements[],
1229
          uint8_t *csr, size_t csr_len, char **privkey_pem,
1230
          size_t *privkey_len)
1231
{
1232
#if defined(OPENSSL_NO_EC)
1233
  return -1;
1234
#else
1235
  uint8_t *csr_in = csr;
1236
  EC_KEY *eckey = NULL;
1237
  X509_REQ *req;
1238
  X509_NAME *subj;
1239
  EVP_PKEY *pkey;
1240
  char *p, *end;
1241
  BIO *bio;
1242
  long bio_len;
1243
  int n, ret = -1;
1244
1245
  eckey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
1246
  if (!eckey)
1247
    return -1;
1248
1249
  if (!EC_KEY_generate_key(eckey)) {
1250
    EC_KEY_free(eckey);
1251
    return -1;
1252
  }
1253
1254
  pkey = EVP_PKEY_new();
1255
  if (!pkey)
1256
    goto bail0;
1257
  if (!EVP_PKEY_assign_EC_KEY(pkey, eckey))
1258
    goto bail1;
1259
1260
  req = X509_REQ_new();
1261
  if (!req)
1262
          goto bail1;
1263
1264
  X509_REQ_set_pubkey(req, pkey);
1265
1266
  subj = X509_NAME_new();
1267
  if (!subj)
1268
    goto bail2;
1269
1270
  for (n = 0; n < LWS_TLS_REQ_ELEMENT_COUNT; n++)
1271
    if (elements[n] &&
1272
      lws_tls_openssl_add_nid(subj, nid_list[n],
1273
        elements[n])) {
1274
        lwsl_notice("%s: failed to add element %d\n",
1275
            __func__, n);
1276
      goto bail3;
1277
    }
1278
1279
  if (X509_REQ_set_subject_name(req, subj) != 1)
1280
    goto bail3;
1281
1282
  if (elements[LWS_TLS_REQ_ELEMENT_SUBJECT_ALT_NAME]) {
1283
    STACK_OF(X509_EXTENSION) *exts;
1284
    X509_EXTENSION *ext;
1285
    char san[256];
1286
1287
    exts = sk_X509_EXTENSION_new_null();
1288
    if (!exts)
1289
      goto bail3;
1290
1291
    lws_snprintf(san, sizeof(san), "DNS:%s,DNS:%s",
1292
        elements[LWS_TLS_REQ_ELEMENT_COMMON_NAME],
1293
        elements[LWS_TLS_REQ_ELEMENT_SUBJECT_ALT_NAME]);
1294
1295
    ext = X509V3_EXT_conf_nid(NULL, NULL, NID_subject_alt_name,
1296
        san);
1297
    if (!ext) {
1298
      sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
1299
      goto bail3;
1300
    }
1301
    sk_X509_EXTENSION_push(exts, ext);
1302
1303
    if (!X509_REQ_add_extensions(req, exts)) {
1304
      sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
1305
      goto bail3;
1306
    }
1307
    sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
1308
  }
1309
1310
  if (!X509_REQ_sign(req, pkey, EVP_sha256()))
1311
    goto bail3;
1312
1313
  /*
1314
   * issue the CSR as PEM to a BIO, and translate to b64urlenc without
1315
   * headers, trailers, or whitespace
1316
   */
1317
1318
  bio = BIO_new(BIO_s_mem());
1319
  if (!bio)
1320
    goto bail3;
1321
1322
  if (PEM_write_bio_X509_REQ(bio, req) != 1) {
1323
    BIO_free(bio);
1324
    goto bail3;
1325
  }
1326
1327
  bio_len = BIO_get_mem_data(bio, &p);
1328
  end = p + bio_len;
1329
1330
  /* strip the header line */
1331
  while (p < end && *p != '\n')
1332
    p++;
1333
1334
  while (p < end && csr_len) {
1335
    if (*p == '\n') {
1336
      p++;
1337
      continue;
1338
    }
1339
1340
    if (*p == '-')
1341
      break;
1342
1343
    if (*p == '+')
1344
      *csr++ = '-';
1345
    else
1346
      if (*p == '/')
1347
        *csr++ = '_';
1348
      else
1349
        *csr++ = (uint8_t)*p;
1350
    p++;
1351
    csr_len--;
1352
  }
1353
  BIO_free(bio);
1354
  if (!csr_len) {
1355
    lwsl_notice("%s: need %ld for CSR\n", __func__, bio_len);
1356
    goto bail3;
1357
  }
1358
1359
  /*
1360
   * Also return the private key as a PEM in memory
1361
   * (platform may not have a filesystem)
1362
   */
1363
  bio = BIO_new(BIO_s_mem());
1364
  if (!bio)
1365
    goto bail3;
1366
1367
  if (PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, 0, NULL) != 1) {
1368
    BIO_free(bio);
1369
    goto bail3;
1370
  }
1371
  bio_len = BIO_get_mem_data(bio, &p);
1372
  *privkey_pem = malloc((unsigned long)bio_len); /* malloc so user code can own / free */
1373
  *privkey_len = (size_t)bio_len;
1374
  if (!*privkey_pem) {
1375
    lwsl_notice("%s: need %ld for private key\n", __func__,
1376
          bio_len);
1377
    BIO_free(bio);
1378
    goto bail3;
1379
  }
1380
  memcpy(*privkey_pem, p, (unsigned int)(int)(long long)bio_len);
1381
  BIO_free(bio);
1382
1383
  ret = lws_ptr_diff(csr, csr_in);
1384
1385
bail3:
1386
  X509_NAME_free(subj);
1387
bail2:
1388
  X509_REQ_free(req);
1389
bail1:
1390
  EVP_PKEY_free(pkey);
1391
  return ret;
1392
bail0:
1393
  if (eckey)
1394
    EC_KEY_free(eckey);
1395
  return -1;
1396
#endif
1397
}
1398
#endif