Coverage Report

Created: 2026-01-25 06:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/curl/lib/vtls/openssl.c
Line
Count
Source
1
/***************************************************************************
2
 *                                  _   _ ____  _
3
 *  Project                     ___| | | |  _ \| |
4
 *                             / __| | | | |_) | |
5
 *                            | (__| |_| |  _ <| |___
6
 *                             \___|\___/|_| \_\_____|
7
 *
8
 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
9
 *
10
 * This software is licensed as described in the file COPYING, which
11
 * you should have received as part of this distribution. The terms
12
 * are also available at https://curl.se/docs/copyright.html.
13
 *
14
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15
 * copies of the Software, and permit persons to whom the Software is
16
 * furnished to do so, under the terms of the COPYING file.
17
 *
18
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
 * KIND, either express or implied.
20
 *
21
 * SPDX-License-Identifier: curl
22
 *
23
 ***************************************************************************/
24
/*
25
 * Source file for all OpenSSL-specific code for the TLS/SSL layer. No code
26
 * but vtls.c should ever call or use these functions.
27
 */
28
#include "../curl_setup.h"
29
30
#if defined(USE_QUICHE) || defined(USE_OPENSSL)
31
32
/* Wincrypt must be included before anything that could include OpenSSL. */
33
#ifdef USE_WIN32_CRYPTO
34
#include <wincrypt.h>
35
/* Undefine wincrypt conflicting symbols for BoringSSL. */
36
#undef X509_NAME
37
#undef X509_EXTENSIONS
38
#undef PKCS7_ISSUER_AND_SERIAL
39
#undef PKCS7_SIGNER_INFO
40
#undef OCSP_REQUEST
41
#undef OCSP_RESPONSE
42
#endif
43
44
#include "../urldata.h"
45
#include "../curl_trc.h"
46
#include "../httpsrr.h"
47
#include "../formdata.h" /* for the boundary function */
48
#include "../url.h" /* for the ssl config check function */
49
#include "../curlx/inet_pton.h"
50
#include "openssl.h"
51
#include "../connect.h"
52
#include "../progress.h"
53
#include "vtls.h"
54
#include "vtls_int.h"
55
#include "vtls_scache.h"
56
#include "../vauth/vauth.h"
57
#include "keylog.h"
58
#include "hostcheck.h"
59
#include "../transfer.h"
60
#include "../multiif.h"
61
#include "../curlx/strerr.h"
62
#include "../curlx/strparse.h"
63
#include "../curlx/strcopy.h"
64
#include "../strdup.h"
65
#include "apple.h"
66
67
#include <openssl/rand.h>
68
#include <openssl/x509v3.h>
69
#ifndef OPENSSL_NO_DSA
70
#include <openssl/dsa.h>
71
#endif
72
#include <openssl/dh.h>
73
#include <openssl/err.h>
74
#include <openssl/conf.h>
75
#include <openssl/bn.h>
76
#include <openssl/rsa.h>
77
#include <openssl/bio.h>
78
#include <openssl/pkcs12.h>
79
#include <openssl/tls1.h>
80
#include <openssl/evp.h>
81
82
#if defined(HAVE_SSL_SET1_ECH_CONFIG_LIST) && !defined(HAVE_BORINGSSL_LIKE)
83
#include <openssl/ech.h>
84
#endif
85
86
#ifndef OPENSSL_NO_OCSP
87
#include <openssl/ocsp.h>
88
#endif
89
90
#if !defined(OPENSSL_NO_ENGINE) && !defined(OPENSSL_NO_UI_CONSOLE)
91
#define USE_OPENSSL_ENGINE
92
#include <openssl/engine.h>
93
#endif
94
95
#ifdef LIBRESSL_VERSION_NUMBER
96
/* As of LibreSSL 2.0.0-4.0.0: OPENSSL_VERSION_NUMBER == 0x20000000L */
97
#  if LIBRESSL_VERSION_NUMBER < 0x2090100fL /* 2019-04-13 */
98
#    error "LibreSSL 2.9.1 or later required"
99
#  endif
100
#elif !defined(HAVE_BORINGSSL_LIKE)
101
#  ifndef HAVE_OPENSSL3 /* 2021-09-07 */
102
#    error "OpenSSL 3.0.0 or later required"
103
#  endif
104
#endif
105
106
#if defined(HAVE_OPENSSL3) && !defined(OPENSSL_NO_UI_CONSOLE)
107
#include <openssl/provider.h>
108
#include <openssl/store.h>
109
/* this is used in the following conditions to make them easier to read */
110
#define OPENSSL_HAS_PROVIDERS
111
#endif
112
113
/* AWS-LC fixed a bug with large buffers in v1.61.0 which also introduced
114
 * X509_V_ERR_EC_KEY_EXPLICIT_PARAMS. */
115
#if !defined(LIBRESSL_VERSION_NUMBER) && !defined(OPENSSL_IS_BORINGSSL) && \
116
  (!defined(OPENSSL_IS_AWSLC) || defined(X509_V_ERR_EC_KEY_EXPLICIT_PARAMS))
117
#define HAVE_SSL_CTX_SET_DEFAULT_READ_BUFFER_LEN 1
118
#endif
119
120
#if defined(USE_OPENSSL_ENGINE) || defined(OPENSSL_HAS_PROVIDERS)
121
#include <openssl/ui.h>
122
#endif
123
124
#ifdef HAVE_OPENSSL3
125
#define HAVE_EVP_PKEY_GET_PARAMS 1
126
#endif
127
128
#ifdef HAVE_EVP_PKEY_GET_PARAMS
129
#include <openssl/core_names.h>
130
0
#define DECLARE_PKEY_PARAM_BIGNUM(name) BIGNUM *name = NULL
131
0
#define FREE_PKEY_PARAM_BIGNUM(name) BN_clear_free(name)
132
#else
133
#define DECLARE_PKEY_PARAM_BIGNUM(name) const BIGNUM *name
134
#define FREE_PKEY_PARAM_BIGNUM(name)
135
#endif
136
137
/* Whether SSL_CTX_set_ciphersuites is available.
138
 * OpenSSL: supported since 1.1.1 (commit a53b5be6a05)
139
 * BoringSSL: no
140
 * LibreSSL: supported since 3.4.1 (released 2021-10-14)
141
 */
142
#if (!defined(LIBRESSL_VERSION_NUMBER) || \
143
     (defined(LIBRESSL_VERSION_NUMBER) && \
144
      LIBRESSL_VERSION_NUMBER >= 0x3040100fL)) && \
145
    !defined(OPENSSL_IS_BORINGSSL)
146
#  define HAVE_SSL_CTX_SET_CIPHERSUITES
147
#  ifndef OPENSSL_IS_AWSLC
148
#    define HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH
149
#  endif
150
#endif
151
152
/* Whether SSL_CTX_set1_sigalgs_list is available
153
 * OpenSSL: supported since 1.0.2 (commit 0b362de5f575)
154
 * BoringSSL: supported since 0.20240913.0 (commit 826ce15)
155
 * LibreSSL: no
156
 */
157
#ifndef LIBRESSL_VERSION_NUMBER
158
#define HAVE_SSL_CTX_SET1_SIGALGS
159
#endif
160
161
#ifdef LIBRESSL_VERSION_NUMBER
162
#define OSSL_PACKAGE "LibreSSL"
163
#elif defined(OPENSSL_IS_BORINGSSL)
164
#define OSSL_PACKAGE "BoringSSL"
165
#elif defined(OPENSSL_IS_AWSLC)
166
#define OSSL_PACKAGE "AWS-LC"
167
#elif defined(USE_NGTCP2) && defined(USE_NGHTTP3) && \
168
  !defined(OPENSSL_QUIC_API2)
169
#define OSSL_PACKAGE "quictls"
170
#else
171
0
#define OSSL_PACKAGE "OpenSSL"
172
#endif
173
174
#ifdef HAVE_BORINGSSL_LIKE
175
typedef size_t numcert_t;
176
typedef uint32_t sslerr_t;
177
#else
178
typedef int numcert_t;
179
typedef unsigned long sslerr_t;
180
#endif
181
#define ossl_valsize_t numcert_t
182
183
static CURLcode push_certinfo(struct Curl_easy *data,
184
                              BIO *mem, const char *label, int num)
185
  WARN_UNUSED_RESULT;
186
187
static CURLcode push_certinfo(struct Curl_easy *data,
188
                              BIO *mem, const char *label, int num)
189
0
{
190
0
  char *ptr;
191
0
  long len = BIO_get_mem_data(mem, &ptr);
192
0
  CURLcode result = Curl_ssl_push_certinfo_len(data, num, label, ptr, len);
193
0
  (void)BIO_reset(mem);
194
0
  return result;
195
0
}
196
197
static CURLcode pubkey_show(struct Curl_easy *data,
198
                            BIO *mem,
199
                            int num,
200
                            const char *type,
201
                            const char *name,
202
                            const BIGNUM *bn) WARN_UNUSED_RESULT;
203
204
static CURLcode pubkey_show(struct Curl_easy *data,
205
                            BIO *mem,
206
                            int num,
207
                            const char *type,
208
                            const char *name,
209
                            const BIGNUM *bn)
210
0
{
211
0
  char namebuf[32];
212
213
0
  curl_msnprintf(namebuf, sizeof(namebuf), "%s(%s)", type, name);
214
215
0
  if(bn)
216
0
    BN_print(mem, bn);
217
0
  return push_certinfo(data, mem, namebuf, num);
218
0
}
219
220
#define print_pubkey_BN(_type, _name, _num)           \
221
0
  pubkey_show(data, mem, _num, #_type, #_name, _name)
222
223
static int asn1_object_dump(const ASN1_OBJECT *a, char *buf, size_t len)
224
0
{
225
0
  int i = i2t_ASN1_OBJECT(buf, (int)len, a);
226
0
  return (i >= (int)len);  /* buffer too small */
227
0
}
228
229
static CURLcode X509V3_ext(struct Curl_easy *data,
230
                           int certnum,
231
                           const STACK_OF(X509_EXTENSION) *extsarg)
232
0
{
233
0
  int i;
234
0
  CURLcode result = CURLE_OK;
235
#ifdef LIBRESSL_VERSION_NUMBER
236
  STACK_OF(X509_EXTENSION) *exts = CURL_UNCONST(extsarg);
237
#else
238
0
  const STACK_OF(X509_EXTENSION) *exts = extsarg;
239
0
#endif
240
241
0
  if((int)sk_X509_EXTENSION_num(exts) <= 0)
242
    /* no extensions, bail out */
243
0
    return result;
244
245
0
  for(i = 0; i < (int)sk_X509_EXTENSION_num(exts); i++) {
246
0
    ASN1_OBJECT *obj;
247
0
    X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, (ossl_valsize_t)i);
248
0
    BUF_MEM *biomem;
249
0
    char namebuf[128];
250
0
    BIO *bio_out = BIO_new(BIO_s_mem());
251
252
0
    if(!bio_out)
253
0
      return result;
254
255
0
    obj = X509_EXTENSION_get_object(ext);
256
257
0
    if(asn1_object_dump(obj, namebuf, sizeof(namebuf)))
258
      /* make sure the name is null-terminated */
259
0
      namebuf[sizeof(namebuf) - 1] = 0;
260
261
0
    if(!X509V3_EXT_print(bio_out, ext, 0, 0))
262
0
      ASN1_STRING_print(bio_out, (ASN1_STRING *)X509_EXTENSION_get_data(ext));
263
264
0
    BIO_get_mem_ptr(bio_out, &biomem);
265
0
    result = Curl_ssl_push_certinfo_len(data, certnum, namebuf, biomem->data,
266
0
                                        biomem->length);
267
0
    BIO_free(bio_out);
268
0
    if(result)
269
0
      break;
270
0
  }
271
0
  return result;
272
0
}
273
274
static CURLcode get_pkey_rsa(struct Curl_easy *data,
275
                             EVP_PKEY *pubkey, BIO *mem, int i)
276
0
{
277
0
  CURLcode result = CURLE_OK;
278
#ifndef HAVE_EVP_PKEY_GET_PARAMS
279
  RSA *rsa = EVP_PKEY_get0_RSA(pubkey);
280
#endif /* !HAVE_EVP_PKEY_GET_PARAMS */
281
0
  DECLARE_PKEY_PARAM_BIGNUM(n);
282
0
  DECLARE_PKEY_PARAM_BIGNUM(e);
283
0
#ifdef HAVE_EVP_PKEY_GET_PARAMS
284
0
  EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_N, &n);
285
0
  EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_E, &e);
286
#else
287
  RSA_get0_key(rsa, &n, &e, NULL);
288
#endif /* HAVE_EVP_PKEY_GET_PARAMS */
289
0
  BIO_printf(mem, "%d", n ? BN_num_bits(n) : 0);
290
0
  result = push_certinfo(data, mem, "RSA Public Key", i);
291
0
  if(!result) {
292
0
    result = print_pubkey_BN(rsa, n, i);
293
0
    if(!result)
294
0
      result = print_pubkey_BN(rsa, e, i);
295
0
  }
296
0
  FREE_PKEY_PARAM_BIGNUM(n);
297
0
  FREE_PKEY_PARAM_BIGNUM(e);
298
0
  return result;
299
0
}
300
301
#ifndef OPENSSL_NO_DSA
302
static CURLcode get_pkey_dsa(struct Curl_easy *data,
303
                             EVP_PKEY *pubkey, BIO *mem, int i)
304
0
{
305
0
  CURLcode result = CURLE_OK;
306
#ifndef HAVE_EVP_PKEY_GET_PARAMS
307
  DSA *dsa = EVP_PKEY_get0_DSA(pubkey);
308
#endif /* !HAVE_EVP_PKEY_GET_PARAMS */
309
0
  DECLARE_PKEY_PARAM_BIGNUM(p);
310
0
  DECLARE_PKEY_PARAM_BIGNUM(q);
311
0
  DECLARE_PKEY_PARAM_BIGNUM(g);
312
0
  DECLARE_PKEY_PARAM_BIGNUM(pub_key);
313
0
#ifdef HAVE_EVP_PKEY_GET_PARAMS
314
0
  EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_P, &p);
315
0
  EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_Q, &q);
316
0
  EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_G, &g);
317
0
  EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_PUB_KEY, &pub_key);
318
#else
319
  DSA_get0_pqg(dsa, &p, &q, &g);
320
  DSA_get0_key(dsa, &pub_key, NULL);
321
#endif /* HAVE_EVP_PKEY_GET_PARAMS */
322
0
  result = print_pubkey_BN(dsa, p, i);
323
0
  if(!result)
324
0
    result = print_pubkey_BN(dsa, q, i);
325
0
  if(!result)
326
0
    result = print_pubkey_BN(dsa, g, i);
327
0
  if(!result)
328
0
    result = print_pubkey_BN(dsa, pub_key, i);
329
0
  FREE_PKEY_PARAM_BIGNUM(p);
330
0
  FREE_PKEY_PARAM_BIGNUM(q);
331
0
  FREE_PKEY_PARAM_BIGNUM(g);
332
0
  FREE_PKEY_PARAM_BIGNUM(pub_key);
333
0
  return result;
334
0
}
335
#endif /* !OPENSSL_NO_DSA */
336
337
static CURLcode get_pkey_dh(struct Curl_easy *data,
338
                            EVP_PKEY *pubkey, BIO *mem, int i)
339
0
{
340
0
  CURLcode result;
341
#ifndef HAVE_EVP_PKEY_GET_PARAMS
342
  DH *dh = EVP_PKEY_get0_DH(pubkey);
343
#endif /* !HAVE_EVP_PKEY_GET_PARAMS */
344
0
  DECLARE_PKEY_PARAM_BIGNUM(p);
345
0
  DECLARE_PKEY_PARAM_BIGNUM(q);
346
0
  DECLARE_PKEY_PARAM_BIGNUM(g);
347
0
  DECLARE_PKEY_PARAM_BIGNUM(pub_key);
348
0
#ifdef HAVE_EVP_PKEY_GET_PARAMS
349
0
  EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_P, &p);
350
0
  EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_Q, &q);
351
0
  EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_G, &g);
352
0
  EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_PUB_KEY, &pub_key);
353
#else
354
  DH_get0_pqg(dh, &p, &q, &g);
355
  DH_get0_key(dh, &pub_key, NULL);
356
#endif /* HAVE_EVP_PKEY_GET_PARAMS */
357
0
  result = print_pubkey_BN(dh, p, i);
358
0
  if(!result)
359
0
    result = print_pubkey_BN(dh, q, i);
360
0
  if(!result)
361
0
    result = print_pubkey_BN(dh, g, i);
362
0
  if(!result)
363
0
    result = print_pubkey_BN(dh, pub_key, i);
364
0
  FREE_PKEY_PARAM_BIGNUM(p);
365
0
  FREE_PKEY_PARAM_BIGNUM(q);
366
0
  FREE_PKEY_PARAM_BIGNUM(g);
367
0
  FREE_PKEY_PARAM_BIGNUM(pub_key);
368
0
  return result;
369
0
}
370
371
static CURLcode ossl_certchain(struct Curl_easy *data, SSL *ssl)
372
0
{
373
0
  CURLcode result;
374
0
  STACK_OF(X509) *sk;
375
0
  int i;
376
0
  numcert_t numcerts;
377
0
  BIO *mem;
378
379
0
  DEBUGASSERT(ssl);
380
381
0
  sk = SSL_get_peer_cert_chain(ssl);
382
0
  if(!sk)
383
0
    return CURLE_SSL_CONNECT_ERROR;
384
385
0
  numcerts = sk_X509_num(sk);
386
0
  if(numcerts > MAX_ALLOWED_CERT_AMOUNT) {
387
0
    failf(data, "%d certificates is more than allowed (%u)", (int)numcerts,
388
0
          MAX_ALLOWED_CERT_AMOUNT);
389
0
    return CURLE_SSL_CONNECT_ERROR;
390
0
  }
391
392
0
  result = Curl_ssl_init_certinfo(data, (int)numcerts);
393
0
  if(result)
394
0
    return result;
395
396
0
  mem = BIO_new(BIO_s_mem());
397
0
  if(!mem)
398
0
    result = CURLE_OUT_OF_MEMORY;
399
400
0
  for(i = 0; !result && (i < (int)numcerts); i++) {
401
0
    ASN1_INTEGER *num;
402
0
    const unsigned char *numdata;
403
0
    X509 *x = sk_X509_value(sk, (ossl_valsize_t)i);
404
0
    EVP_PKEY *pubkey = NULL;
405
0
    int j;
406
0
    const ASN1_BIT_STRING *psig = NULL;
407
408
0
    X509_NAME_print_ex(mem, X509_get_subject_name(x), 0, XN_FLAG_ONELINE);
409
0
    result = push_certinfo(data, mem, "Subject", i);
410
0
    if(result)
411
0
      break;
412
413
0
    X509_NAME_print_ex(mem, X509_get_issuer_name(x), 0, XN_FLAG_ONELINE);
414
0
    result = push_certinfo(data, mem, "Issuer", i);
415
0
    if(result)
416
0
      break;
417
418
0
    BIO_printf(mem, "%lx", X509_get_version(x));
419
0
    result = push_certinfo(data, mem, "Version", i);
420
0
    if(result)
421
0
      break;
422
423
0
    num = X509_get_serialNumber(x);
424
0
    if(ASN1_STRING_type(num) == V_ASN1_NEG_INTEGER)
425
0
      BIO_puts(mem, "-");
426
0
    numdata = ASN1_STRING_get0_data(num);
427
0
    for(j = 0; j < ASN1_STRING_length(num); j++)
428
0
      BIO_printf(mem, "%02x", numdata[j]);
429
0
    result = push_certinfo(data, mem, "Serial Number", i);
430
0
    if(result)
431
0
      break;
432
433
0
    {
434
0
      const X509_ALGOR *sigalg = NULL;
435
0
      X509_PUBKEY *xpubkey = NULL;
436
0
      ASN1_OBJECT *pubkeyoid = NULL;
437
438
0
      X509_get0_signature(&psig, &sigalg, x);
439
0
      if(sigalg) {
440
0
        const ASN1_OBJECT *sigalgoid = NULL;
441
0
        X509_ALGOR_get0(&sigalgoid, NULL, NULL, sigalg);
442
0
        i2a_ASN1_OBJECT(mem, sigalgoid);
443
0
        result = push_certinfo(data, mem, "Signature Algorithm", i);
444
0
        if(result)
445
0
          break;
446
0
      }
447
448
0
      xpubkey = X509_get_X509_PUBKEY(x);
449
0
      if(xpubkey) {
450
0
        X509_PUBKEY_get0_param(&pubkeyoid, NULL, NULL, NULL, xpubkey);
451
0
        if(pubkeyoid) {
452
0
          i2a_ASN1_OBJECT(mem, pubkeyoid);
453
0
          result = push_certinfo(data, mem, "Public Key Algorithm", i);
454
0
          if(result)
455
0
            break;
456
0
        }
457
0
      }
458
459
0
      result = X509V3_ext(data, i, X509_get0_extensions(x));
460
0
      if(result)
461
0
        break;
462
0
    }
463
464
0
    ASN1_TIME_print(mem, X509_get0_notBefore(x));
465
0
    result = push_certinfo(data, mem, "Start date", i);
466
0
    if(result)
467
0
      break;
468
469
0
    ASN1_TIME_print(mem, X509_get0_notAfter(x));
470
0
    result = push_certinfo(data, mem, "Expire date", i);
471
0
    if(result)
472
0
      break;
473
474
0
    pubkey = X509_get_pubkey(x);
475
0
    if(!pubkey)
476
0
      infof(data, "   Unable to load public key");
477
0
    else {
478
0
      switch(EVP_PKEY_id(pubkey)) {
479
0
      case EVP_PKEY_RSA:
480
0
        result = get_pkey_rsa(data, pubkey, mem, i);
481
0
        break;
482
483
0
#ifndef OPENSSL_NO_DSA
484
0
      case EVP_PKEY_DSA:
485
0
        result = get_pkey_dsa(data, pubkey, mem, i);
486
0
        break;
487
0
#endif
488
489
0
      case EVP_PKEY_DH:
490
0
        result = get_pkey_dh(data, pubkey, mem, i);
491
0
        break;
492
0
      }
493
0
      EVP_PKEY_free(pubkey);
494
0
    }
495
496
0
    if(!result && psig) {
497
0
      const unsigned char *psigdata = ASN1_STRING_get0_data(psig);
498
0
      for(j = 0; j < ASN1_STRING_length(psig); j++)
499
0
        BIO_printf(mem, "%02x:", psigdata[j]);
500
0
      result = push_certinfo(data, mem, "Signature", i);
501
0
    }
502
503
0
    if(!result) {
504
0
      PEM_write_bio_X509(mem, x);
505
0
      result = push_certinfo(data, mem, "Cert", i);
506
0
    }
507
0
  }
508
509
0
  BIO_free(mem);
510
511
0
  if(result)
512
    /* cleanup all leftovers */
513
0
    Curl_ssl_free_certinfo(data);
514
515
0
  return result;
516
0
}
517
518
#endif /* USE_QUICHE || USE_OPENSSL */
519
520
#ifdef USE_OPENSSL
521
522
static int ossl_bio_cf_create(BIO *bio)
523
0
{
524
0
  BIO_set_shutdown(bio, 1);
525
0
  BIO_set_init(bio, 1);
526
0
  BIO_set_data(bio, NULL);
527
0
  return 1;
528
0
}
529
530
static int ossl_bio_cf_destroy(BIO *bio)
531
0
{
532
0
  if(!bio)
533
0
    return 0;
534
0
  return 1;
535
0
}
536
537
static long ossl_bio_cf_ctrl(BIO *bio, int cmd, long num, void *ptr)
538
0
{
539
0
  struct Curl_cfilter *cf = BIO_get_data(bio);
540
0
  long ret = 1;
541
542
0
  (void)cf;
543
0
  (void)ptr;
544
0
  switch(cmd) {
545
0
  case BIO_CTRL_GET_CLOSE:
546
0
    ret = (long)BIO_get_shutdown(bio);
547
0
    break;
548
0
  case BIO_CTRL_SET_CLOSE:
549
0
    BIO_set_shutdown(bio, (int)num);
550
0
    break;
551
0
  case BIO_CTRL_FLUSH:
552
    /* we do no delayed writes, but if we ever would, this
553
     * needs to trigger it. */
554
0
    ret = 1;
555
0
    break;
556
0
  case BIO_CTRL_DUP:
557
0
    ret = 1;
558
0
    break;
559
0
  case BIO_CTRL_EOF: {
560
    /* EOF has been reached on input? */
561
0
    struct ssl_connect_data *connssl = cf->ctx;
562
0
    return connssl->peer_closed;
563
0
  }
564
0
  default:
565
0
    ret = 0;
566
0
    break;
567
0
  }
568
0
  return ret;
569
0
}
570
571
static int ossl_bio_cf_out_write(BIO *bio, const char *buf, int blen)
572
0
{
573
0
  struct Curl_cfilter *cf = BIO_get_data(bio);
574
0
  struct ssl_connect_data *connssl = cf->ctx;
575
0
  struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
576
0
  struct Curl_easy *data = CF_DATA_CURRENT(cf);
577
0
  size_t nwritten;
578
0
  CURLcode result;
579
580
0
  DEBUGASSERT(data);
581
0
  if(blen < 0)
582
0
    return 0;
583
584
0
  result = Curl_conn_cf_send(cf->next, data,
585
0
                             (const uint8_t *)buf, (size_t)blen, FALSE,
586
0
                             &nwritten);
587
0
  CURL_TRC_CF(data, cf, "ossl_bio_cf_out_write(len=%d) -> %d, %zu",
588
0
              blen, result, nwritten);
589
0
  BIO_clear_retry_flags(bio);
590
0
  octx->io_result = result;
591
0
  if(result) {
592
0
    if(CURLE_AGAIN == result)
593
0
      BIO_set_retry_write(bio);
594
0
    return -1;
595
0
  }
596
0
  return (int)nwritten;
597
0
}
598
599
static int ossl_bio_cf_in_read(BIO *bio, char *buf, int blen)
600
0
{
601
0
  struct Curl_cfilter *cf = BIO_get_data(bio);
602
0
  struct ssl_connect_data *connssl = cf->ctx;
603
0
  struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
604
0
  struct Curl_easy *data = CF_DATA_CURRENT(cf);
605
0
  size_t nread;
606
0
  CURLcode result, r2;
607
608
0
  DEBUGASSERT(data);
609
  /* OpenSSL catches this case, so should we. */
610
0
  if(!buf)
611
0
    return 0;
612
0
  if(blen < 0)
613
0
    return 0;
614
615
0
  result = Curl_conn_cf_recv(cf->next, data, buf, (size_t)blen, &nread);
616
0
  CURL_TRC_CF(data, cf, "ossl_bio_cf_in_read(len=%d) -> %d, %zu",
617
0
              blen, result, nread);
618
0
  BIO_clear_retry_flags(bio);
619
0
  octx->io_result = result;
620
0
  if(result) {
621
0
    if(CURLE_AGAIN == result)
622
0
      BIO_set_retry_read(bio);
623
0
  }
624
0
  else {
625
    /* feeding data to OpenSSL means SSL_read() might succeed */
626
0
    connssl->input_pending = TRUE;
627
0
    if(nread == 0)
628
0
      connssl->peer_closed = TRUE;
629
0
  }
630
631
  /* Before returning server replies to the SSL instance, we need
632
   * to have setup the x509 store or verification will fail. */
633
0
  if(!octx->x509_store_setup) {
634
0
    r2 = Curl_ssl_setup_x509_store(cf, data, octx);
635
0
    if(r2) {
636
0
      BIO_clear_retry_flags(bio);
637
0
      octx->io_result = r2;
638
0
      return -1;
639
0
    }
640
0
    octx->x509_store_setup = TRUE;
641
0
  }
642
0
  return result ? -1 : (int)nread;
643
0
}
644
645
static BIO_METHOD *ossl_bio_cf_method_create(void)
646
0
{
647
0
  BIO_METHOD *m = BIO_meth_new(BIO_TYPE_MEM, "OpenSSL CF BIO");
648
0
  if(m) {
649
0
    BIO_meth_set_write(m, &ossl_bio_cf_out_write);
650
0
    BIO_meth_set_read(m, &ossl_bio_cf_in_read);
651
0
    BIO_meth_set_ctrl(m, &ossl_bio_cf_ctrl);
652
0
    BIO_meth_set_create(m, &ossl_bio_cf_create);
653
0
    BIO_meth_set_destroy(m, &ossl_bio_cf_destroy);
654
0
  }
655
0
  return m;
656
0
}
657
658
static void ossl_bio_cf_method_free(BIO_METHOD *m)
659
0
{
660
0
  if(m)
661
0
    BIO_meth_free(m);
662
0
}
663
664
#ifdef HAVE_KEYLOG_CALLBACK
665
static void ossl_keylog_callback(const SSL *ssl, const char *line)
666
0
{
667
0
  (void)ssl;
668
669
0
  Curl_tls_keylog_write_line(line);
670
0
}
671
#else
672
/*
673
 * ossl_log_tls12_secret is called by libcurl to make the CLIENT_RANDOMs if the
674
 * OpenSSL being used does not have native support for doing that.
675
 */
676
static void ossl_log_tls12_secret(const SSL *ssl, bool *keylog_done)
677
{
678
  const SSL_SESSION *session;
679
  unsigned char client_random[SSL3_RANDOM_SIZE];
680
  unsigned char master_key[SSL_MAX_MASTER_KEY_LENGTH];
681
  int master_key_length = 0;
682
683
  ERR_set_mark();
684
685
  session = SSL_get_session(ssl);
686
687
  if(!session || *keylog_done) {
688
    ERR_pop_to_mark();
689
    return;
690
  }
691
692
  SSL_get_client_random(ssl, client_random, SSL3_RANDOM_SIZE);
693
  master_key_length = (int)
694
    SSL_SESSION_get_master_key(session, master_key, SSL_MAX_MASTER_KEY_LENGTH);
695
696
  ERR_pop_to_mark();
697
698
  /* The handshake has not progressed sufficiently yet, or this is a TLS 1.3
699
   * session (when curl was built with older OpenSSL headers and running with
700
   * newer OpenSSL runtime libraries). */
701
  if(master_key_length <= 0)
702
    return;
703
704
  *keylog_done = TRUE;
705
  Curl_tls_keylog_write("CLIENT_RANDOM", client_random,
706
                        master_key, master_key_length);
707
}
708
#endif /* !HAVE_KEYLOG_CALLBACK */
709
710
static const char *SSL_ERROR_to_str(int err)
711
0
{
712
0
  switch(err) {
713
0
  case SSL_ERROR_NONE:
714
0
    return "SSL_ERROR_NONE";
715
0
  case SSL_ERROR_SSL:
716
0
    return "SSL_ERROR_SSL";
717
0
  case SSL_ERROR_WANT_READ:
718
0
    return "SSL_ERROR_WANT_READ";
719
0
  case SSL_ERROR_WANT_WRITE:
720
0
    return "SSL_ERROR_WANT_WRITE";
721
0
  case SSL_ERROR_WANT_X509_LOOKUP:
722
0
    return "SSL_ERROR_WANT_X509_LOOKUP";
723
0
  case SSL_ERROR_SYSCALL:
724
0
    return "SSL_ERROR_SYSCALL";
725
0
  case SSL_ERROR_ZERO_RETURN:
726
0
    return "SSL_ERROR_ZERO_RETURN";
727
0
  case SSL_ERROR_WANT_CONNECT:
728
0
    return "SSL_ERROR_WANT_CONNECT";
729
0
  case SSL_ERROR_WANT_ACCEPT:
730
0
    return "SSL_ERROR_WANT_ACCEPT";
731
0
#ifdef SSL_ERROR_WANT_ASYNC  /* OpenSSL 1.1.0+, LibreSSL 3.6.0+ */
732
0
  case SSL_ERROR_WANT_ASYNC:
733
0
    return "SSL_ERROR_WANT_ASYNC";
734
0
#endif
735
0
#ifdef SSL_ERROR_WANT_ASYNC_JOB  /* OpenSSL 1.1.0+, LibreSSL 3.6.0+ */
736
0
  case SSL_ERROR_WANT_ASYNC_JOB:
737
0
    return "SSL_ERROR_WANT_ASYNC_JOB";
738
0
#endif
739
0
#ifdef SSL_ERROR_WANT_CLIENT_HELLO_CB  /* OpenSSL 1.1.1, LibreSSL 3.6.0+ */
740
0
  case SSL_ERROR_WANT_CLIENT_HELLO_CB:
741
0
    return "SSL_ERROR_WANT_CLIENT_HELLO_CB";
742
0
#endif
743
0
  default:
744
0
    return "SSL_ERROR unknown";
745
0
  }
746
0
}
747
748
/* Return error string for last OpenSSL error
749
 */
750
static char *ossl_strerror(unsigned long error, char *buf, size_t size)
751
0
{
752
0
  size_t len;
753
0
  DEBUGASSERT(size);
754
0
  *buf = '\0';
755
756
0
  len = Curl_ossl_version(buf, size);
757
0
  DEBUGASSERT(len < (size - 2));
758
0
  if(len < (size - 2)) {
759
0
    buf += len;
760
0
    size -= (len + 2);
761
0
    *buf++ = ':';
762
0
    *buf++ = ' ';
763
0
    *buf = '\0';
764
0
  }
765
766
#ifdef HAVE_BORINGSSL_LIKE
767
  ERR_error_string_n((uint32_t)error, buf, size);
768
#else
769
0
  ERR_error_string_n(error, buf, size);
770
0
#endif
771
772
0
  if(!*buf) {
773
0
    const char *msg = error ? "Unknown error" : "No error";
774
0
    curlx_strcopy(buf, size, msg, strlen(msg));
775
0
  }
776
777
0
  return buf;
778
0
}
779
780
static int passwd_callback(char *buf, int num, int encrypting, void *password)
781
0
{
782
0
  DEBUGASSERT(encrypting == 0);
783
784
0
  if(!encrypting && num >= 0 && password) {
785
0
    int klen = curlx_uztosi(strlen((char *)password));
786
0
    if(num > klen) {
787
0
      memcpy(buf, password, klen + 1);
788
0
      return klen;
789
0
    }
790
0
  }
791
0
  return 0;
792
0
}
793
794
/*
795
 * rand_enough() returns TRUE if we have seeded the random engine properly.
796
 */
797
static bool rand_enough(void)
798
0
{
799
0
  return RAND_status() != 0;
800
0
}
801
802
static CURLcode ossl_seed(struct Curl_easy *data)
803
0
{
804
  /* This might get called before it has been added to a multi handle */
805
0
  if(data->multi && data->multi->ssl_seeded)
806
0
    return CURLE_OK;
807
808
0
  if(rand_enough()) {
809
    /* OpenSSL 1.1.0+ should return here */
810
0
    if(data->multi)
811
0
      data->multi->ssl_seeded = TRUE;
812
0
    return CURLE_OK;
813
0
  }
814
0
  failf(data, "Insufficient randomness");
815
0
  return CURLE_SSL_CONNECT_ERROR;
816
0
}
817
818
#ifndef SSL_FILETYPE_ENGINE
819
0
#define SSL_FILETYPE_ENGINE 42
820
#endif
821
#ifndef SSL_FILETYPE_PKCS12
822
0
#define SSL_FILETYPE_PKCS12 43
823
#endif
824
#ifndef SSL_FILETYPE_PROVIDER
825
0
#define SSL_FILETYPE_PROVIDER 44
826
#endif
827
static int ossl_do_file_type(const char *type)
828
0
{
829
0
  if(!type || !type[0])
830
0
    return SSL_FILETYPE_PEM;
831
0
  if(curl_strequal(type, "PEM"))
832
0
    return SSL_FILETYPE_PEM;
833
0
  if(curl_strequal(type, "DER"))
834
0
    return SSL_FILETYPE_ASN1;
835
0
  if(curl_strequal(type, "PROV"))
836
0
    return SSL_FILETYPE_PROVIDER;
837
0
  if(curl_strequal(type, "ENG"))
838
0
    return SSL_FILETYPE_ENGINE;
839
0
  if(curl_strequal(type, "P12"))
840
0
    return SSL_FILETYPE_PKCS12;
841
0
  return -1;
842
0
}
843
844
#if defined(USE_OPENSSL_ENGINE) || defined(OPENSSL_HAS_PROVIDERS)
845
/*
846
 * Supply default password to the engine user interface conversation.
847
 * The password is passed by OpenSSL engine from ENGINE_load_private_key()
848
 * last argument to the ui and can be obtained by UI_get0_user_data(ui) here.
849
 */
850
static int ssl_ui_reader(UI *ui, UI_STRING *uis)
851
0
{
852
0
  const char *password;
853
0
  switch(UI_get_string_type(uis)) {
854
0
  case UIT_PROMPT:
855
0
  case UIT_VERIFY:
856
0
    password = (const char *)UI_get0_user_data(ui);
857
0
    if(password && (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD)) {
858
0
      UI_set_result(ui, uis, password);
859
0
      return 1;
860
0
    }
861
0
    FALLTHROUGH();
862
0
  default:
863
0
    break;
864
0
  }
865
0
  return (UI_method_get_reader(UI_OpenSSL()))(ui, uis);
866
0
}
867
868
/*
869
 * Suppress interactive request for a default password if available.
870
 */
871
static int ssl_ui_writer(UI *ui, UI_STRING *uis)
872
0
{
873
0
  switch(UI_get_string_type(uis)) {
874
0
  case UIT_PROMPT:
875
0
  case UIT_VERIFY:
876
0
    if(UI_get0_user_data(ui) &&
877
0
       (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD)) {
878
0
      return 1;
879
0
    }
880
0
    FALLTHROUGH();
881
0
  default:
882
0
    break;
883
0
  }
884
0
  return (UI_method_get_writer(UI_OpenSSL()))(ui, uis);
885
0
}
886
887
/*
888
 * Check if a given string is a PKCS#11 URI
889
 */
890
static bool is_pkcs11_uri(const char *string)
891
0
{
892
0
  return string && curl_strnequal(string, "pkcs11:", 7);
893
0
}
894
895
#endif
896
897
static CURLcode ossl_set_engine(struct Curl_easy *data, const char *engine);
898
#ifdef OPENSSL_HAS_PROVIDERS
899
static CURLcode ossl_set_provider(struct Curl_easy *data,
900
                                  const char *provider);
901
#endif
902
903
static int use_certificate_blob(SSL_CTX *ctx, const struct curl_blob *blob,
904
                                int type, const char *key_passwd)
905
0
{
906
0
  int ret = 0;
907
0
  X509 *x = NULL;
908
  /* the typecast of blob->len is fine since it is guaranteed to never be
909
     larger than CURL_MAX_INPUT_LENGTH */
910
0
  BIO *in = BIO_new_mem_buf(blob->data, (int)(blob->len));
911
0
  if(!in)
912
0
    return CURLE_OUT_OF_MEMORY;
913
914
0
  if(type == SSL_FILETYPE_ASN1) {
915
    /* j = ERR_R_ASN1_LIB; */
916
0
    x = d2i_X509_bio(in, NULL);
917
0
  }
918
0
  else if(type == SSL_FILETYPE_PEM) {
919
    /* ERR_R_PEM_LIB; */
920
0
    x = PEM_read_bio_X509(in, NULL, passwd_callback, CURL_UNCONST(key_passwd));
921
0
  }
922
0
  else {
923
0
    ret = 0;
924
0
    goto end;
925
0
  }
926
927
0
  if(!x) {
928
0
    ret = 0;
929
0
    goto end;
930
0
  }
931
932
0
  ret = SSL_CTX_use_certificate(ctx, x);
933
0
end:
934
0
  X509_free(x);
935
0
  BIO_free(in);
936
0
  return ret;
937
0
}
938
939
static int use_privatekey_blob(SSL_CTX *ctx, const struct curl_blob *blob,
940
                               int type, const char *key_passwd)
941
0
{
942
0
  int ret = 0;
943
0
  EVP_PKEY *pkey = NULL;
944
0
  BIO *in = BIO_new_mem_buf(blob->data, (int)(blob->len));
945
0
  if(!in)
946
0
    return CURLE_OUT_OF_MEMORY;
947
948
0
  if(type == SSL_FILETYPE_PEM)
949
0
    pkey = PEM_read_bio_PrivateKey(in, NULL, passwd_callback,
950
0
                                   CURL_UNCONST(key_passwd));
951
0
  else if(type == SSL_FILETYPE_ASN1)
952
0
    pkey = d2i_PrivateKey_bio(in, NULL);
953
0
  else
954
0
    goto end;
955
956
0
  if(!pkey)
957
0
    goto end;
958
959
0
  ret = SSL_CTX_use_PrivateKey(ctx, pkey);
960
0
  EVP_PKEY_free(pkey);
961
0
end:
962
0
  BIO_free(in);
963
0
  return ret;
964
0
}
965
966
static int use_certificate_chain_blob(SSL_CTX *ctx,
967
                                      const struct curl_blob *blob,
968
                                      const char *key_passwd)
969
0
{
970
0
  int ret = 0;
971
0
  X509 *x = NULL;
972
0
  BIO *in = BIO_new_mem_buf(blob->data, (int)(blob->len));
973
0
  if(!in)
974
0
    return CURLE_OUT_OF_MEMORY;
975
976
0
  ERR_clear_error();
977
978
0
  x = PEM_read_bio_X509_AUX(in, NULL,
979
0
                            passwd_callback, CURL_UNCONST(key_passwd));
980
0
  if(!x)
981
0
    goto end;
982
983
0
  ret = SSL_CTX_use_certificate(ctx, x);
984
985
0
  if(ERR_peek_error() != 0)
986
0
    ret = 0;
987
988
0
  if(ret) {
989
0
    X509 *ca;
990
0
    sslerr_t err;
991
992
0
    if(!SSL_CTX_clear_chain_certs(ctx)) {
993
0
      ret = 0;
994
0
      goto end;
995
0
    }
996
997
0
    while((ca = PEM_read_bio_X509(in, NULL, passwd_callback,
998
0
                                  CURL_UNCONST(key_passwd))) != NULL) {
999
1000
0
      if(!SSL_CTX_add0_chain_cert(ctx, ca)) {
1001
0
        X509_free(ca);
1002
0
        ret = 0;
1003
0
        goto end;
1004
0
      }
1005
0
    }
1006
1007
0
    err = ERR_peek_last_error();
1008
0
    if((ERR_GET_LIB(err) == ERR_LIB_PEM) &&
1009
0
       (ERR_GET_REASON(err) == PEM_R_NO_START_LINE))
1010
0
      ERR_clear_error();
1011
0
    else
1012
0
      ret = 0;
1013
0
  }
1014
1015
0
end:
1016
0
  X509_free(x);
1017
0
  BIO_free(in);
1018
0
  return ret;
1019
0
}
1020
1021
static int enginecheck(struct Curl_easy *data,
1022
                       SSL_CTX* ctx,
1023
                       const char *key_file,
1024
                       const char *key_passwd)
1025
0
{
1026
0
#ifdef USE_OPENSSL_ENGINE
1027
0
  EVP_PKEY *priv_key = NULL;
1028
1029
  /* Implicitly use pkcs11 engine if none was provided and the
1030
   * key_file is a PKCS#11 URI */
1031
0
  if(!data->state.engine) {
1032
0
    if(is_pkcs11_uri(key_file)) {
1033
0
      if(ossl_set_engine(data, "pkcs11") != CURLE_OK) {
1034
0
        return 0;
1035
0
      }
1036
0
    }
1037
0
  }
1038
1039
0
  if(data->state.engine) {
1040
0
    UI_METHOD *ui_method = UI_create_method("curl user interface");
1041
0
    if(!ui_method) {
1042
0
      failf(data, "unable to create " OSSL_PACKAGE " user-interface method");
1043
0
      return 0;
1044
0
    }
1045
0
    UI_method_set_opener(ui_method, UI_method_get_opener(UI_OpenSSL()));
1046
0
    UI_method_set_closer(ui_method, UI_method_get_closer(UI_OpenSSL()));
1047
0
    UI_method_set_reader(ui_method, ssl_ui_reader);
1048
0
    UI_method_set_writer(ui_method, ssl_ui_writer);
1049
0
    priv_key = ENGINE_load_private_key(data->state.engine, key_file,
1050
0
                                       ui_method,
1051
0
                                       CURL_UNCONST(key_passwd));
1052
0
    UI_destroy_method(ui_method);
1053
0
    if(!priv_key) {
1054
0
      failf(data, "failed to load private key from crypto engine");
1055
0
      return 0;
1056
0
    }
1057
0
    if(SSL_CTX_use_PrivateKey(ctx, priv_key) != 1) {
1058
0
      failf(data, "unable to set private key");
1059
0
      EVP_PKEY_free(priv_key);
1060
0
      return 0;
1061
0
    }
1062
0
    EVP_PKEY_free(priv_key);  /* we do not need the handle any more... */
1063
0
  }
1064
0
  else {
1065
0
    failf(data, "crypto engine not set, cannot load private key");
1066
0
    return 0;
1067
0
  }
1068
0
  return 1;
1069
#else
1070
  (void)ctx;
1071
  (void)key_file;
1072
  (void)key_passwd;
1073
  failf(data, "SSL_FILETYPE_ENGINE not supported for private key");
1074
  return 0;
1075
#endif
1076
0
}
1077
1078
static int providercheck(struct Curl_easy *data,
1079
                         SSL_CTX* ctx,
1080
                         const char *key_file)
1081
0
{
1082
0
#ifdef OPENSSL_HAS_PROVIDERS
1083
0
  char error_buffer[256];
1084
  /* Implicitly use pkcs11 provider if none was provided and the
1085
   * key_file is a PKCS#11 URI */
1086
0
  if(!data->state.provider_loaded) {
1087
0
    if(is_pkcs11_uri(key_file)) {
1088
0
      if(ossl_set_provider(data, "pkcs11") != CURLE_OK) {
1089
0
        return 0;
1090
0
      }
1091
0
    }
1092
0
  }
1093
1094
0
  if(data->state.provider_loaded) {
1095
    /* Load the private key from the provider */
1096
0
    EVP_PKEY *priv_key = NULL;
1097
0
    OSSL_STORE_CTX *store = NULL;
1098
0
    OSSL_STORE_INFO *info = NULL;
1099
0
    UI_METHOD *ui_method = UI_create_method("curl user interface");
1100
0
    if(!ui_method) {
1101
0
      failf(data, "unable to create " OSSL_PACKAGE " user-interface method");
1102
0
      return 0;
1103
0
    }
1104
0
    UI_method_set_opener(ui_method, UI_method_get_opener(UI_OpenSSL()));
1105
0
    UI_method_set_closer(ui_method, UI_method_get_closer(UI_OpenSSL()));
1106
0
    UI_method_set_reader(ui_method, ssl_ui_reader);
1107
0
    UI_method_set_writer(ui_method, ssl_ui_writer);
1108
1109
0
    store = OSSL_STORE_open_ex(key_file, data->state.libctx,
1110
0
                               data->state.propq, ui_method, NULL, NULL,
1111
0
                               NULL, NULL);
1112
0
    if(!store) {
1113
0
      failf(data, "Failed to open OpenSSL store: %s",
1114
0
            ossl_strerror(ERR_get_error(), error_buffer,
1115
0
                          sizeof(error_buffer)));
1116
0
      UI_destroy_method(ui_method);
1117
0
      return 0;
1118
0
    }
1119
0
    if(OSSL_STORE_expect(store, OSSL_STORE_INFO_PKEY) != 1) {
1120
0
      failf(data, "Failed to set store preference. Ignoring the error: %s",
1121
0
            ossl_strerror(ERR_get_error(), error_buffer,
1122
0
                          sizeof(error_buffer)));
1123
0
    }
1124
1125
0
    info = OSSL_STORE_load(store);
1126
0
    if(info) {
1127
0
      int ossl_type = OSSL_STORE_INFO_get_type(info);
1128
1129
0
      if(ossl_type == OSSL_STORE_INFO_PKEY)
1130
0
        priv_key = OSSL_STORE_INFO_get1_PKEY(info);
1131
0
      OSSL_STORE_INFO_free(info);
1132
0
    }
1133
0
    OSSL_STORE_close(store);
1134
0
    UI_destroy_method(ui_method);
1135
0
    if(!priv_key) {
1136
0
      failf(data, "No private key found in the openssl store: %s",
1137
0
            ossl_strerror(ERR_get_error(), error_buffer,
1138
0
                          sizeof(error_buffer)));
1139
0
      return 0;
1140
0
    }
1141
1142
0
    if(SSL_CTX_use_PrivateKey(ctx, priv_key) != 1) {
1143
0
      failf(data, "unable to set private key [%s]",
1144
0
            ossl_strerror(ERR_get_error(), error_buffer,
1145
0
                          sizeof(error_buffer)));
1146
0
      EVP_PKEY_free(priv_key);
1147
0
      return 0;
1148
0
    }
1149
0
    EVP_PKEY_free(priv_key); /* we do not need the handle any more... */
1150
0
  }
1151
0
  else {
1152
0
    failf(data, "crypto provider not set, cannot load private key");
1153
0
    return 0;
1154
0
  }
1155
0
  return 1;
1156
#else
1157
  (void)ctx;
1158
  (void)key_file;
1159
  failf(data, "SSL_FILETYPE_PROVIDER not supported for private key");
1160
  return 0;
1161
#endif
1162
0
}
1163
1164
static int engineload(struct Curl_easy *data,
1165
                      SSL_CTX* ctx,
1166
                      const char *cert_file)
1167
0
{
1168
/* ENGINE_CTRL_GET_CMD_FROM_NAME supported by OpenSSL, LibreSSL <=3.8.3 */
1169
0
#if defined(USE_OPENSSL_ENGINE) && defined(ENGINE_CTRL_GET_CMD_FROM_NAME)
1170
0
  char error_buffer[256];
1171
  /* Implicitly use pkcs11 engine if none was provided and the
1172
   * cert_file is a PKCS#11 URI */
1173
0
  if(!data->state.engine) {
1174
0
    if(is_pkcs11_uri(cert_file)) {
1175
0
      if(ossl_set_engine(data, "pkcs11") != CURLE_OK) {
1176
0
        return 0;
1177
0
      }
1178
0
    }
1179
0
  }
1180
1181
0
  if(data->state.engine) {
1182
0
    const char *cmd_name = "LOAD_CERT_CTRL";
1183
0
    struct {
1184
0
      const char *cert_id;
1185
0
      X509 *cert;
1186
0
    } params;
1187
1188
0
    params.cert_id = cert_file;
1189
0
    params.cert = NULL;
1190
1191
    /* Does the engine supports LOAD_CERT_CTRL ? */
1192
0
    if(!ENGINE_ctrl(data->state.engine, ENGINE_CTRL_GET_CMD_FROM_NAME,
1193
0
                    0, CURL_UNCONST(cmd_name), NULL)) {
1194
0
      failf(data, "ssl engine does not support loading certificates");
1195
0
      return 0;
1196
0
    }
1197
1198
    /* Load the certificate from the engine */
1199
0
    if(!ENGINE_ctrl_cmd(data->state.engine, cmd_name, 0, &params, NULL, 1)) {
1200
0
      failf(data, "ssl engine cannot load client cert with id '%s' [%s]",
1201
0
            cert_file,
1202
0
            ossl_strerror(ERR_get_error(), error_buffer,
1203
0
                          sizeof(error_buffer)));
1204
0
      return 0;
1205
0
    }
1206
1207
0
    if(!params.cert) {
1208
0
      failf(data, "ssl engine did not initialized the certificate properly.");
1209
0
      return 0;
1210
0
    }
1211
1212
0
    if(SSL_CTX_use_certificate(ctx, params.cert) != 1) {
1213
0
      failf(data, "unable to set client certificate [%s]",
1214
0
            ossl_strerror(ERR_get_error(), error_buffer,
1215
0
                          sizeof(error_buffer)));
1216
0
      X509_free(params.cert);
1217
0
      return 0;
1218
0
    }
1219
0
    X509_free(params.cert); /* we do not need the handle any more... */
1220
0
  }
1221
0
  else {
1222
0
    failf(data, "crypto engine not set, cannot load certificate");
1223
0
    return 0;
1224
0
  }
1225
0
  return 1;
1226
#else
1227
  (void)ctx;
1228
  (void)cert_file;
1229
  failf(data, "SSL_FILETYPE_ENGINE not supported for certificate");
1230
  return 0;
1231
#endif
1232
0
}
1233
1234
static int providerload(struct Curl_easy *data,
1235
                        SSL_CTX* ctx,
1236
                        const char *cert_file)
1237
0
{
1238
0
#ifdef OPENSSL_HAS_PROVIDERS
1239
0
  char error_buffer[256];
1240
  /* Implicitly use pkcs11 provider if none was provided and the
1241
   * cert_file is a PKCS#11 URI */
1242
0
  if(!data->state.provider_loaded) {
1243
0
    if(is_pkcs11_uri(cert_file)) {
1244
0
      if(ossl_set_provider(data, "pkcs11") != CURLE_OK) {
1245
0
        return 0;
1246
0
      }
1247
0
    }
1248
0
  }
1249
1250
0
  if(data->state.provider_loaded) {
1251
    /* Load the certificate from the provider */
1252
0
    OSSL_STORE_INFO *info = NULL;
1253
0
    X509 *cert = NULL;
1254
0
    OSSL_STORE_CTX *store =
1255
0
      OSSL_STORE_open_ex(cert_file, data->state.libctx,
1256
0
                         NULL, NULL, NULL, NULL, NULL, NULL);
1257
0
    int rc;
1258
1259
0
    if(!store) {
1260
0
      failf(data, "Failed to open OpenSSL store: %s",
1261
0
            ossl_strerror(ERR_get_error(), error_buffer,
1262
0
                          sizeof(error_buffer)));
1263
0
      return 0;
1264
0
    }
1265
0
    if(OSSL_STORE_expect(store, OSSL_STORE_INFO_CERT) != 1) {
1266
0
      failf(data, "Failed to set store preference. Ignoring the error: %s",
1267
0
            ossl_strerror(ERR_get_error(), error_buffer,
1268
0
                          sizeof(error_buffer)));
1269
0
    }
1270
1271
0
    info = OSSL_STORE_load(store);
1272
0
    if(info) {
1273
0
      int ossl_type = OSSL_STORE_INFO_get_type(info);
1274
1275
0
      if(ossl_type == OSSL_STORE_INFO_CERT)
1276
0
        cert = OSSL_STORE_INFO_get1_CERT(info);
1277
0
      OSSL_STORE_INFO_free(info);
1278
0
    }
1279
0
    OSSL_STORE_close(store);
1280
0
    if(!cert) {
1281
0
      failf(data, "No cert found in the openssl store: %s",
1282
0
            ossl_strerror(ERR_get_error(), error_buffer,
1283
0
                          sizeof(error_buffer)));
1284
0
      return 0;
1285
0
    }
1286
1287
0
    rc = SSL_CTX_use_certificate(ctx, cert);
1288
0
    X509_free(cert); /* we do not need the handle any more... */
1289
1290
0
    if(rc != 1) {
1291
0
      failf(data, "unable to set client certificate [%s]",
1292
0
            ossl_strerror(ERR_get_error(), error_buffer,
1293
0
                          sizeof(error_buffer)));
1294
0
      return 0;
1295
0
    }
1296
0
  }
1297
0
  else {
1298
0
    failf(data, "crypto provider not set, cannot load certificate");
1299
0
    return 0;
1300
0
  }
1301
0
  return 1;
1302
#else
1303
  (void)ctx;
1304
  (void)cert_file;
1305
  failf(data, "SSL_FILETYPE_PROVIDER not supported for certificate");
1306
  return 0;
1307
#endif
1308
0
}
1309
1310
static int pkcs12load(struct Curl_easy *data,
1311
                      SSL_CTX* ctx,
1312
                      const struct curl_blob *cert_blob,
1313
                      const char *cert_file,
1314
                      const char *key_passwd)
1315
0
{
1316
0
  char error_buffer[256];
1317
0
  BIO *cert_bio = NULL;
1318
0
  PKCS12 *p12 = NULL;
1319
0
  EVP_PKEY *pri;
1320
0
  X509 *x509;
1321
0
  int cert_done = 0;
1322
0
  STACK_OF(X509) *ca = NULL;
1323
0
  if(cert_blob) {
1324
0
    cert_bio = BIO_new_mem_buf(cert_blob->data, (int)(cert_blob->len));
1325
0
    if(!cert_bio) {
1326
0
      failf(data, "BIO_new_mem_buf NULL, " OSSL_PACKAGE " error %s",
1327
0
            ossl_strerror(ERR_get_error(), error_buffer,
1328
0
                          sizeof(error_buffer)));
1329
0
      return 0;
1330
0
    }
1331
0
  }
1332
0
  else {
1333
0
    cert_bio = BIO_new(BIO_s_file());
1334
0
    if(!cert_bio) {
1335
0
      failf(data, "BIO_new return NULL, " OSSL_PACKAGE " error %s",
1336
0
            ossl_strerror(ERR_get_error(), error_buffer,
1337
0
                          sizeof(error_buffer)));
1338
0
      return 0;
1339
0
    }
1340
1341
0
    if(BIO_read_filename(cert_bio, CURL_UNCONST(cert_file)) <= 0) {
1342
0
      failf(data, "could not open PKCS12 file '%s'", cert_file);
1343
0
      BIO_free(cert_bio);
1344
0
      return 0;
1345
0
    }
1346
0
  }
1347
1348
0
  p12 = d2i_PKCS12_bio(cert_bio, NULL);
1349
0
  BIO_free(cert_bio);
1350
1351
0
  if(!p12) {
1352
0
    failf(data, "error reading PKCS12 file '%s'",
1353
0
          cert_blob ? "(memory blob)" : cert_file);
1354
0
    return 0;
1355
0
  }
1356
1357
0
  if(!PKCS12_parse(p12, key_passwd, &pri, &x509, &ca)) {
1358
0
    failf(data, "could not parse PKCS12 file, check password, " OSSL_PACKAGE
1359
0
          " error %s",
1360
0
          ossl_strerror(ERR_get_error(), error_buffer, sizeof(error_buffer)));
1361
0
    PKCS12_free(p12);
1362
0
    return 0;
1363
0
  }
1364
1365
0
  PKCS12_free(p12);
1366
1367
0
  if(SSL_CTX_use_certificate(ctx, x509) != 1) {
1368
0
    failf(data, "could not load PKCS12 client certificate, " OSSL_PACKAGE
1369
0
          " error %s",
1370
0
          ossl_strerror(ERR_get_error(), error_buffer, sizeof(error_buffer)));
1371
0
    goto fail;
1372
0
  }
1373
1374
0
  if(SSL_CTX_use_PrivateKey(ctx, pri) != 1) {
1375
0
    failf(data, "unable to use private key from PKCS12 file '%s'", cert_file);
1376
0
    goto fail;
1377
0
  }
1378
1379
0
  if(!SSL_CTX_check_private_key(ctx)) {
1380
0
    failf(data, "private key from PKCS12 file '%s' "
1381
0
          "does not match certificate in same file", cert_file);
1382
0
    goto fail;
1383
0
  }
1384
  /* Set Certificate Verification chain */
1385
0
  if(ca) {
1386
0
    while(sk_X509_num(ca)) {
1387
      /*
1388
       * Note that sk_X509_pop() is used below to make sure the cert is
1389
       * removed from the stack properly before getting passed to
1390
       * SSL_CTX_add_extra_chain_cert(), which takes ownership. Previously
1391
       * we used sk_X509_value() instead, but then we would clean it in the
1392
       * subsequent sk_X509_pop_free() call.
1393
       */
1394
0
      X509 *x = sk_X509_pop(ca);
1395
0
      if(!SSL_CTX_add_client_CA(ctx, x)) {
1396
0
        X509_free(x);
1397
0
        failf(data, "cannot add certificate to client CA list");
1398
0
        goto fail;
1399
0
      }
1400
0
      if(!SSL_CTX_add_extra_chain_cert(ctx, x)) {
1401
0
        X509_free(x);
1402
0
        failf(data, "cannot add certificate to certificate chain");
1403
0
        goto fail;
1404
0
      }
1405
0
    }
1406
0
  }
1407
1408
0
  cert_done = 1;
1409
0
fail:
1410
0
  EVP_PKEY_free(pri);
1411
0
  X509_free(x509);
1412
0
#if defined(__clang__) && __clang_major__ >= 16
1413
0
#pragma clang diagnostic push
1414
0
#pragma clang diagnostic ignored "-Wcast-function-type-strict"
1415
0
#endif
1416
0
  sk_X509_pop_free(ca, X509_free);
1417
0
#if defined(__clang__) && __clang_major__ >= 16
1418
0
#pragma clang diagnostic pop
1419
0
#endif
1420
0
  if(!cert_done)
1421
0
    return 0; /* failure! */
1422
0
  return 1;
1423
0
}
1424
1425
static CURLcode client_cert(struct Curl_easy *data,
1426
                            SSL_CTX* ctx,
1427
                            char *cert_file,
1428
                            const struct curl_blob *cert_blob,
1429
                            const char *cert_type,
1430
                            char *key_file,
1431
                            const struct curl_blob *key_blob,
1432
                            const char *key_type,
1433
                            char *key_passwd)
1434
0
{
1435
0
  char error_buffer[256];
1436
0
  bool check_privkey = TRUE;
1437
0
  int file_type = ossl_do_file_type(cert_type);
1438
1439
0
  if(cert_file || cert_blob || (file_type == SSL_FILETYPE_ENGINE) ||
1440
0
     (file_type == SSL_FILETYPE_PROVIDER)) {
1441
0
    SSL *ssl;
1442
0
    X509 *x509;
1443
0
    bool pcks12_done = FALSE;
1444
0
    int cert_use_result;
1445
1446
0
    if(key_passwd) {
1447
      /* set the password in the callback userdata */
1448
0
      SSL_CTX_set_default_passwd_cb_userdata(ctx, key_passwd);
1449
      /* Set passwd callback: */
1450
0
      SSL_CTX_set_default_passwd_cb(ctx, passwd_callback);
1451
0
    }
1452
1453
0
    switch(file_type) {
1454
0
    case SSL_FILETYPE_PEM:
1455
      /* SSL_CTX_use_certificate_chain_file() only works on PEM files */
1456
0
      cert_use_result = cert_blob ?
1457
0
        use_certificate_chain_blob(ctx, cert_blob, key_passwd) :
1458
0
        SSL_CTX_use_certificate_chain_file(ctx, cert_file);
1459
0
      if(cert_use_result != 1) {
1460
0
        failf(data,
1461
0
              "could not load PEM client certificate from %s, " OSSL_PACKAGE
1462
0
              " error %s, "
1463
0
              "(no key found, wrong passphrase, or wrong file format?)",
1464
0
              (cert_blob ? "CURLOPT_SSLCERT_BLOB" : cert_file),
1465
0
              ossl_strerror(ERR_get_error(), error_buffer,
1466
0
                            sizeof(error_buffer)));
1467
0
        return CURLE_SSL_CERTPROBLEM;
1468
0
      }
1469
0
      break;
1470
1471
0
    case SSL_FILETYPE_ASN1:
1472
      /* SSL_CTX_use_certificate_file() works with either PEM or ASN1, but
1473
         we use the case above for PEM so this can only be performed with
1474
         ASN1 files. */
1475
1476
0
      cert_use_result = cert_blob ?
1477
0
        use_certificate_blob(ctx, cert_blob, file_type, key_passwd) :
1478
0
      SSL_CTX_use_certificate_file(ctx, cert_file, file_type);
1479
0
      if(cert_use_result != 1) {
1480
0
        failf(data,
1481
0
              "could not load ASN1 client certificate from %s, " OSSL_PACKAGE
1482
0
              " error %s, "
1483
0
              "(no key found, wrong passphrase, or wrong file format?)",
1484
0
              (cert_blob ? "CURLOPT_SSLCERT_BLOB" : cert_file),
1485
0
              ossl_strerror(ERR_get_error(), error_buffer,
1486
0
                            sizeof(error_buffer)));
1487
0
        return CURLE_SSL_CERTPROBLEM;
1488
0
      }
1489
0
      break;
1490
1491
0
    case SSL_FILETYPE_ENGINE:
1492
0
      if(!cert_file || !engineload(data, ctx, cert_file))
1493
0
        return CURLE_SSL_CERTPROBLEM;
1494
0
      break;
1495
1496
0
    case SSL_FILETYPE_PROVIDER:
1497
0
      if(!cert_file || !providerload(data, ctx, cert_file))
1498
0
        return CURLE_SSL_CERTPROBLEM;
1499
0
      break;
1500
1501
0
    case SSL_FILETYPE_PKCS12:
1502
0
      if(!pkcs12load(data, ctx, cert_blob, cert_file, key_passwd))
1503
0
        return CURLE_SSL_CERTPROBLEM;
1504
0
      pcks12_done = TRUE;
1505
0
      break;
1506
1507
0
    default:
1508
0
      failf(data, "not supported file type '%s' for certificate", cert_type);
1509
0
      return CURLE_BAD_FUNCTION_ARGUMENT;
1510
0
    }
1511
1512
0
    if((!key_file) && (!key_blob)) {
1513
0
      key_file = cert_file;
1514
0
      key_blob = cert_blob;
1515
0
    }
1516
0
    else
1517
0
      file_type = ossl_do_file_type(key_type);
1518
1519
0
    switch(file_type) {
1520
0
    case SSL_FILETYPE_PEM:
1521
0
    case SSL_FILETYPE_ASN1:
1522
0
      cert_use_result = key_blob ?
1523
0
        use_privatekey_blob(ctx, key_blob, file_type, key_passwd) :
1524
0
      SSL_CTX_use_PrivateKey_file(ctx, key_file, file_type);
1525
0
      if(cert_use_result != 1) {
1526
0
        failf(data, "unable to set private key file: '%s' type %s",
1527
0
              key_file ? key_file : "(memory blob)",
1528
0
              key_type ? key_type : "PEM");
1529
0
        return CURLE_BAD_FUNCTION_ARGUMENT;
1530
0
      }
1531
0
      break;
1532
0
    case SSL_FILETYPE_ENGINE:
1533
0
      if(!enginecheck(data, ctx, key_file, key_passwd))
1534
0
        return CURLE_SSL_CERTPROBLEM;
1535
0
      break;
1536
1537
0
    case SSL_FILETYPE_PROVIDER:
1538
0
      if(!providercheck(data, ctx, key_file))
1539
0
        return CURLE_SSL_CERTPROBLEM;
1540
0
      break;
1541
1542
0
    case SSL_FILETYPE_PKCS12:
1543
0
      if(!pcks12_done) {
1544
0
        failf(data, "file type P12 for private key not supported");
1545
0
        return CURLE_SSL_CERTPROBLEM;
1546
0
      }
1547
0
      break;
1548
0
    default:
1549
0
      failf(data, "not supported file type for private key");
1550
0
      return CURLE_BAD_FUNCTION_ARGUMENT;
1551
0
    }
1552
1553
0
    ssl = SSL_new(ctx);
1554
0
    if(!ssl) {
1555
0
      failf(data, "unable to create an SSL structure");
1556
0
      return CURLE_OUT_OF_MEMORY;
1557
0
    }
1558
1559
0
    x509 = SSL_get_certificate(ssl);
1560
1561
0
    if(x509) {
1562
0
      EVP_PKEY *pktmp = X509_get_pubkey(x509);
1563
0
      EVP_PKEY_copy_parameters(pktmp, SSL_get_privatekey(ssl));
1564
0
      EVP_PKEY_free(pktmp);
1565
0
    }
1566
1567
0
#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DEPRECATED_3_0)
1568
0
    {
1569
      /* If RSA is used, do not check the private key if its flags indicate
1570
       * it does not support it. */
1571
0
      EVP_PKEY *priv_key = SSL_get_privatekey(ssl);
1572
0
      if(EVP_PKEY_id(priv_key) == EVP_PKEY_RSA) {
1573
0
        RSA *rsa = EVP_PKEY_get1_RSA(priv_key);
1574
0
        if(RSA_flags(rsa) & RSA_METHOD_FLAG_NO_CHECK)
1575
0
          check_privkey = FALSE;
1576
0
        RSA_free(rsa); /* Decrement reference count */
1577
0
      }
1578
0
    }
1579
0
#endif
1580
1581
0
    SSL_free(ssl);
1582
1583
    /* If we are using DSA, we can copy the parameters from
1584
     * the private key */
1585
1586
0
    if(check_privkey == TRUE) {
1587
      /* Now we know that a key and cert have been set against
1588
       * the SSL context */
1589
0
      if(!SSL_CTX_check_private_key(ctx)) {
1590
0
        failf(data, "Private key does not match the certificate public key");
1591
0
        return CURLE_SSL_CERTPROBLEM;
1592
0
      }
1593
0
    }
1594
0
  }
1595
0
  return CURLE_OK;
1596
0
}
1597
1598
#ifdef CURLVERBOSE
1599
/* returns non-zero on failure */
1600
static CURLcode x509_name_oneline(X509_NAME *a, struct dynbuf *d)
1601
0
{
1602
0
  BIO *bio_out = BIO_new(BIO_s_mem());
1603
0
  BUF_MEM *biomem;
1604
0
  int rc;
1605
0
  CURLcode result = CURLE_OUT_OF_MEMORY;
1606
1607
0
  if(bio_out) {
1608
0
    unsigned long flags = XN_FLAG_SEP_SPLUS_SPC |
1609
0
      (XN_FLAG_ONELINE & ~ASN1_STRFLGS_ESC_MSB & ~XN_FLAG_SPC_EQ);
1610
0
    curlx_dyn_reset(d);
1611
0
    rc = X509_NAME_print_ex(bio_out, a, 0, flags);
1612
0
    if(rc != -1) {
1613
0
      BIO_get_mem_ptr(bio_out, &biomem);
1614
0
      result = curlx_dyn_addn(d, biomem->data, biomem->length);
1615
0
    }
1616
0
    BIO_free(bio_out);
1617
0
  }
1618
0
  return result;
1619
0
}
1620
#endif
1621
1622
/**
1623
 * Global SSL init
1624
 *
1625
 * @retval 0 error initializing SSL
1626
 * @retval 1 SSL initialized successfully
1627
 */
1628
static int ossl_init(void)
1629
0
{
1630
0
  const uint64_t flags =
1631
0
#ifdef OPENSSL_INIT_ENGINE_ALL_BUILTIN
1632
    /* not present in BoringSSL */
1633
0
    OPENSSL_INIT_ENGINE_ALL_BUILTIN |
1634
0
#endif
1635
#ifdef CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG
1636
    OPENSSL_INIT_NO_LOAD_CONFIG |
1637
#else
1638
0
    OPENSSL_INIT_LOAD_CONFIG |
1639
0
#endif
1640
0
    0;
1641
0
  OPENSSL_init_ssl(flags, NULL);
1642
1643
0
  Curl_tls_keylog_open();
1644
1645
0
  return 1;
1646
0
}
1647
1648
/* Global cleanup */
1649
static void ossl_cleanup(void)
1650
0
{
1651
0
  Curl_tls_keylog_close();
1652
0
}
1653
1654
/* Selects an OpenSSL crypto engine or provider.
1655
 */
1656
static CURLcode ossl_set_engine(struct Curl_easy *data, const char *name)
1657
0
{
1658
0
#ifdef USE_OPENSSL_ENGINE
1659
0
  CURLcode result = CURLE_SSL_ENGINE_NOTFOUND;
1660
0
  ENGINE *e = ENGINE_by_id(name);
1661
1662
0
  if(e) {
1663
1664
0
    if(data->state.engine) {
1665
0
      ENGINE_finish(data->state.engine);
1666
0
      ENGINE_free(data->state.engine);
1667
0
      data->state.engine = NULL;
1668
0
    }
1669
0
    if(!ENGINE_init(e)) {
1670
0
      char buf[256];
1671
1672
0
      ENGINE_free(e);
1673
0
      failf(data, "Failed to initialise SSL Engine '%s': %s",
1674
0
            name, ossl_strerror(ERR_get_error(), buf, sizeof(buf)));
1675
0
      result = CURLE_SSL_ENGINE_INITFAILED;
1676
0
      e = NULL;
1677
0
    }
1678
0
    else {
1679
0
      result = CURLE_OK;
1680
0
    }
1681
0
    data->state.engine = e;
1682
0
    return result;
1683
0
  }
1684
0
#endif
1685
0
#ifdef OPENSSL_HAS_PROVIDERS
1686
0
  return ossl_set_provider(data, name);
1687
#else
1688
  (void)name;
1689
  failf(data, "OpenSSL engine not found");
1690
  return CURLE_SSL_ENGINE_NOTFOUND;
1691
#endif
1692
0
}
1693
1694
/* Sets engine as default for all SSL operations
1695
 */
1696
static CURLcode ossl_set_engine_default(struct Curl_easy *data)
1697
0
{
1698
0
#ifdef USE_OPENSSL_ENGINE
1699
0
  if(data->state.engine) {
1700
0
    if(ENGINE_set_default(data->state.engine, ENGINE_METHOD_ALL) > 0) {
1701
0
      infof(data, "set default crypto engine '%s'",
1702
0
            ENGINE_get_id(data->state.engine));
1703
0
    }
1704
0
    else {
1705
0
      failf(data, "set default crypto engine '%s' failed",
1706
0
            ENGINE_get_id(data->state.engine));
1707
0
      return CURLE_SSL_ENGINE_SETFAILED;
1708
0
    }
1709
0
  }
1710
#else
1711
  (void)data;
1712
#endif
1713
0
  return CURLE_OK;
1714
0
}
1715
1716
/* Return list of OpenSSL crypto engine names.
1717
 */
1718
static struct curl_slist *ossl_engines_list(struct Curl_easy *data)
1719
0
{
1720
0
  struct curl_slist *list = NULL;
1721
0
#ifdef USE_OPENSSL_ENGINE
1722
0
  struct curl_slist *beg;
1723
0
  ENGINE *e;
1724
1725
0
  for(e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) {
1726
0
    beg = curl_slist_append(list, ENGINE_get_id(e));
1727
0
    if(!beg) {
1728
0
      curl_slist_free_all(list);
1729
0
      return NULL;
1730
0
    }
1731
0
    list = beg;
1732
0
  }
1733
0
#endif
1734
0
  (void)data;
1735
0
  return list;
1736
0
}
1737
1738
#ifdef OPENSSL_HAS_PROVIDERS
1739
1740
static void ossl_provider_cleanup(struct Curl_easy *data)
1741
0
{
1742
0
  if(data->state.baseprov) {
1743
0
    OSSL_PROVIDER_unload(data->state.baseprov);
1744
0
    data->state.baseprov = NULL;
1745
0
  }
1746
0
  if(data->state.provider) {
1747
0
    OSSL_PROVIDER_unload(data->state.provider);
1748
0
    data->state.provider = NULL;
1749
0
  }
1750
0
  OSSL_LIB_CTX_free(data->state.libctx);
1751
0
  data->state.libctx = NULL;
1752
0
  Curl_safefree(data->state.propq);
1753
0
  data->state.provider_loaded = FALSE;
1754
0
}
1755
1756
0
#define MAX_PROVIDER_LEN 128 /* reasonable */
1757
1758
/* Selects an OpenSSL crypto provider.
1759
 *
1760
 * A provider might need an associated property, a string passed on to
1761
 * OpenSSL. Specify this as [PROVIDER][:PROPERTY]: separate the name and the
1762
 * property with a colon. No colon means no property is set.
1763
 *
1764
 * An example provider + property looks like "tpm2:?provider=tpm2".
1765
 */
1766
static CURLcode ossl_set_provider(struct Curl_easy *data, const char *iname)
1767
0
{
1768
0
  char name[MAX_PROVIDER_LEN + 1];
1769
0
  struct Curl_str prov;
1770
0
  const char *propq = NULL;
1771
1772
0
  if(!iname) {
1773
    /* clear and cleanup provider use */
1774
0
    ossl_provider_cleanup(data);
1775
0
    return CURLE_OK;
1776
0
  }
1777
0
  if(curlx_str_until(&iname, &prov, MAX_PROVIDER_LEN, ':'))
1778
0
    return CURLE_BAD_FUNCTION_ARGUMENT;
1779
1780
0
  if(!curlx_str_single(&iname, ':'))
1781
    /* there was a colon, get the propq until the end of string */
1782
0
    propq = iname;
1783
1784
  /* we need the name in a buffer, null-terminated */
1785
0
  memcpy(name, curlx_str(&prov), curlx_strlen(&prov));
1786
0
  name[curlx_strlen(&prov)] = 0;
1787
1788
0
  if(!data->state.libctx) {
1789
0
    OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new();
1790
0
    if(!libctx)
1791
0
      return CURLE_OUT_OF_MEMORY;
1792
0
    if(propq) {
1793
0
      data->state.propq = curlx_strdup(propq);
1794
0
      if(!data->state.propq) {
1795
0
        OSSL_LIB_CTX_free(libctx);
1796
0
        return CURLE_OUT_OF_MEMORY;
1797
0
      }
1798
0
    }
1799
0
    data->state.libctx = libctx;
1800
0
  }
1801
1802
0
#ifndef CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG
1803
  /* load the configuration file into the library context before checking the
1804
   * provider availability */
1805
0
  if(!OSSL_LIB_CTX_load_config(data->state.libctx, NULL)) {
1806
0
    infof(data, "Failed to load default openssl config. Proceeding.");
1807
0
  }
1808
0
#endif
1809
1810
0
  if(OSSL_PROVIDER_available(data->state.libctx, name)) {
1811
    /* already loaded through the configuration - no action needed */
1812
0
    data->state.provider_loaded = TRUE;
1813
0
    return CURLE_OK;
1814
0
  }
1815
1816
0
  data->state.provider = OSSL_PROVIDER_try_load(data->state.libctx, name, 1);
1817
0
  if(!data->state.provider) {
1818
0
    char error_buffer[256];
1819
0
    failf(data, "Failed to initialize provider: %s",
1820
0
          ossl_strerror(ERR_get_error(), error_buffer, sizeof(error_buffer)));
1821
0
    ossl_provider_cleanup(data);
1822
0
    return CURLE_SSL_ENGINE_NOTFOUND;
1823
0
  }
1824
1825
  /* load the base provider as well */
1826
0
  data->state.baseprov = OSSL_PROVIDER_try_load(data->state.libctx, "base", 1);
1827
0
  if(!data->state.baseprov) {
1828
0
    ossl_provider_cleanup(data);
1829
0
    failf(data, "Failed to load base");
1830
0
    return CURLE_SSL_ENGINE_NOTFOUND;
1831
0
  }
1832
0
  else
1833
0
    data->state.provider_loaded = TRUE;
1834
0
  return CURLE_OK;
1835
0
}
1836
#endif
1837
1838
static CURLcode ossl_shutdown(struct Curl_cfilter *cf,
1839
                              struct Curl_easy *data,
1840
                              bool send_shutdown, bool *done)
1841
0
{
1842
0
  struct ssl_connect_data *connssl = cf->ctx;
1843
0
  struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
1844
0
  CURLcode result = CURLE_OK;
1845
0
  char buf[1024];
1846
0
  int nread = -1, err;
1847
0
  size_t i;
1848
1849
0
  DEBUGASSERT(octx);
1850
0
  if(!octx->ssl || cf->shutdown) {
1851
0
    *done = TRUE;
1852
0
    goto out;
1853
0
  }
1854
1855
0
  connssl->io_need = CURL_SSL_IO_NEED_NONE;
1856
0
  *done = FALSE;
1857
0
  if(!(SSL_get_shutdown(octx->ssl) & SSL_SENT_SHUTDOWN)) {
1858
    /* We have not started the shutdown from our side yet. Check
1859
     * if the server already sent us one. */
1860
0
    ERR_clear_error();
1861
0
    for(i = 0; i < 10; ++i) {
1862
0
      nread = SSL_read(octx->ssl, buf, (int)sizeof(buf));
1863
0
      CURL_TRC_CF(data, cf, "SSL shutdown not sent, read -> %d", nread);
1864
0
      if(nread <= 0)
1865
0
        break;
1866
0
    }
1867
0
    err = SSL_get_error(octx->ssl, nread);
1868
0
    if(!nread && err == SSL_ERROR_ZERO_RETURN) {
1869
0
      bool input_pending;
1870
      /* Yes, it did. */
1871
0
      if(!send_shutdown) {
1872
0
        CURL_TRC_CF(data, cf, "SSL shutdown received, not sending");
1873
0
        *done = TRUE;
1874
0
        goto out;
1875
0
      }
1876
0
      else if(!cf->next->cft->is_alive(cf->next, data, &input_pending)) {
1877
        /* Server closed the connection after its closy notify. It
1878
         * seems not interested to see our close notify, so do not
1879
         * send it. We are done. */
1880
0
        connssl->peer_closed = TRUE;
1881
0
        CURL_TRC_CF(data, cf, "peer closed connection");
1882
0
        *done = TRUE;
1883
0
        goto out;
1884
0
      }
1885
0
    }
1886
0
  }
1887
1888
  /* SSL should now have started the shutdown from our side. Since it
1889
   * was not complete, we are lacking the close notify from the server. */
1890
0
  if(send_shutdown && !(SSL_get_shutdown(octx->ssl) & SSL_SENT_SHUTDOWN)) {
1891
0
    int rc;
1892
0
    ERR_clear_error();
1893
0
    CURL_TRC_CF(data, cf, "send SSL close notify");
1894
0
    rc = SSL_shutdown(octx->ssl);
1895
0
    if(rc == 1) {
1896
0
      CURL_TRC_CF(data, cf, "SSL shutdown finished");
1897
0
      *done = TRUE;
1898
0
      goto out;
1899
0
    }
1900
0
    if(SSL_ERROR_WANT_WRITE == SSL_get_error(octx->ssl, rc)) {
1901
0
      CURL_TRC_CF(data, cf, "SSL shutdown still wants to send");
1902
0
      connssl->io_need = CURL_SSL_IO_NEED_SEND;
1903
0
      goto out;
1904
0
    }
1905
    /* Having sent the close notify, we use SSL_read() to get the
1906
     * missing close notify from the server. */
1907
0
  }
1908
1909
0
  for(i = 0; i < 10; ++i) {
1910
0
    ERR_clear_error();
1911
0
    nread = SSL_read(octx->ssl, buf, (int)sizeof(buf));
1912
0
    CURL_TRC_CF(data, cf, "SSL shutdown read -> %d", nread);
1913
0
    if(nread <= 0)
1914
0
      break;
1915
0
  }
1916
0
  err = SSL_get_error(octx->ssl, nread);
1917
0
  switch(err) {
1918
0
  case SSL_ERROR_ZERO_RETURN: /* no more data */
1919
0
    if(SSL_shutdown(octx->ssl) == 1)
1920
0
      CURL_TRC_CF(data, cf, "SSL shutdown finished");
1921
0
    else
1922
0
      CURL_TRC_CF(data, cf, "SSL shutdown not received, but closed");
1923
0
    *done = TRUE;
1924
0
    break;
1925
0
  case SSL_ERROR_NONE: /* just did not get anything */
1926
0
  case SSL_ERROR_WANT_READ:
1927
    /* SSL has send its notify and now wants to read the reply
1928
     * from the server. We are not really interested in that. */
1929
0
    CURL_TRC_CF(data, cf, "SSL shutdown sent, want receive");
1930
0
    connssl->io_need = CURL_SSL_IO_NEED_RECV;
1931
0
    break;
1932
0
  case SSL_ERROR_WANT_WRITE:
1933
0
    CURL_TRC_CF(data, cf, "SSL shutdown send blocked");
1934
0
    connssl->io_need = CURL_SSL_IO_NEED_SEND;
1935
0
    break;
1936
0
  default:
1937
    /* Server seems to have closed the connection without sending us
1938
     * a close notify. */
1939
0
    {
1940
0
      VERBOSE(unsigned long sslerr = ERR_get_error());
1941
0
      CURL_TRC_CF(data, cf, "SSL shutdown, ignore recv error: '%s', errno %d",
1942
0
                  (sslerr ?
1943
0
                   ossl_strerror(sslerr, buf, sizeof(buf)) :
1944
0
                   SSL_ERROR_to_str(err)),
1945
0
                  SOCKERRNO);
1946
0
    }
1947
0
    *done = TRUE;
1948
0
    result = CURLE_OK;
1949
0
    break;
1950
0
  }
1951
1952
0
out:
1953
0
  cf->shutdown = (result || *done);
1954
0
  if(cf->shutdown || (connssl->io_need != CURL_SSL_IO_NEED_NONE))
1955
0
    connssl->input_pending = FALSE;
1956
0
  return result;
1957
0
}
1958
1959
static void ossl_close(struct Curl_cfilter *cf, struct Curl_easy *data)
1960
0
{
1961
0
  struct ssl_connect_data *connssl = cf->ctx;
1962
0
  struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
1963
1964
0
  (void)data;
1965
0
  DEBUGASSERT(octx);
1966
1967
0
  connssl->input_pending = FALSE;
1968
0
  if(octx->ssl) {
1969
0
    SSL_free(octx->ssl);
1970
0
    octx->ssl = NULL;
1971
0
  }
1972
0
  if(octx->ssl_ctx) {
1973
0
    SSL_CTX_free(octx->ssl_ctx);
1974
0
    octx->ssl_ctx = NULL;
1975
0
    octx->x509_store_setup = FALSE;
1976
0
  }
1977
0
  if(octx->bio_method) {
1978
0
    ossl_bio_cf_method_free(octx->bio_method);
1979
0
    octx->bio_method = NULL;
1980
0
  }
1981
0
}
1982
1983
/*
1984
 * This function is called when the 'data' struct is going away. Close
1985
 * down everything and free all resources!
1986
 */
1987
static void ossl_close_all(struct Curl_easy *data)
1988
0
{
1989
0
#ifdef USE_OPENSSL_ENGINE
1990
0
  if(data->state.engine) {
1991
0
    ENGINE_finish(data->state.engine);
1992
0
    ENGINE_free(data->state.engine);
1993
0
    data->state.engine = NULL;
1994
0
  }
1995
#else
1996
  (void)data;
1997
#endif
1998
0
#ifdef OPENSSL_HAS_PROVIDERS
1999
0
  ossl_provider_cleanup(data);
2000
0
#endif
2001
0
}
2002
2003
/* ====================================================== */
2004
2005
/* Quote from RFC2818 section 3.1 "Server Identity"
2006
2007
   If a subjectAltName extension of type dNSName is present, that MUST
2008
   be used as the identity. Otherwise, the (most specific) Common Name
2009
   field in the Subject field of the certificate MUST be used. Although
2010
   the use of the Common Name is existing practice, it is deprecated and
2011
   Certification Authorities are encouraged to use the dNSName instead.
2012
2013
   Matching is performed using the matching rules specified by
2014
   [RFC2459]. If more than one identity of a given type is present in
2015
   the certificate (e.g., more than one dNSName name, a match in any one
2016
   of the set is considered acceptable.) Names may contain the wildcard
2017
   character * which is considered to match any single domain name
2018
   component or component fragment. E.g., *.a.com matches foo.a.com but
2019
   not bar.foo.a.com. f*.com matches foo.com but not bar.com.
2020
2021
   In some cases, the URI is specified as an IP address rather than a
2022
   hostname. In this case, the iPAddress subjectAltName must be present
2023
   in the certificate and must exactly match the IP in the URI.
2024
2025
   This function is now used from ngtcp2 (QUIC) as well.
2026
*/
2027
static CURLcode ossl_verifyhost(struct Curl_easy *data,
2028
                                struct connectdata *conn,
2029
                                struct ssl_peer *peer,
2030
                                X509 *server_cert)
2031
0
{
2032
0
  bool matched = FALSE;
2033
0
  int target; /* target type, GEN_DNS or GEN_IPADD */
2034
0
  size_t addrlen = 0;
2035
0
  STACK_OF(GENERAL_NAME) *altnames;
2036
0
#ifdef USE_IPV6
2037
0
  struct in6_addr addr;
2038
#else
2039
  struct in_addr addr;
2040
#endif
2041
0
  CURLcode result = CURLE_OK;
2042
0
  bool dNSName = FALSE; /* if a dNSName field exists in the cert */
2043
0
  bool iPAddress = FALSE; /* if an iPAddress field exists in the cert */
2044
0
  size_t hostlen = strlen(peer->hostname);
2045
2046
0
  (void)conn;
2047
0
  switch(peer->type) {
2048
0
  case CURL_SSL_PEER_IPV4:
2049
0
    if(!curlx_inet_pton(AF_INET, peer->hostname, &addr))
2050
0
      return CURLE_PEER_FAILED_VERIFICATION;
2051
0
    target = GEN_IPADD;
2052
0
    addrlen = sizeof(struct in_addr);
2053
0
    break;
2054
0
#ifdef USE_IPV6
2055
0
  case CURL_SSL_PEER_IPV6:
2056
0
    if(!curlx_inet_pton(AF_INET6, peer->hostname, &addr))
2057
0
      return CURLE_PEER_FAILED_VERIFICATION;
2058
0
    target = GEN_IPADD;
2059
0
    addrlen = sizeof(struct in6_addr);
2060
0
    break;
2061
0
#endif
2062
0
  case CURL_SSL_PEER_DNS:
2063
0
    target = GEN_DNS;
2064
0
    break;
2065
0
  default:
2066
0
    DEBUGASSERT(0);
2067
0
    failf(data, "unexpected ssl peer type: %d", peer->type);
2068
0
    return CURLE_PEER_FAILED_VERIFICATION;
2069
0
  }
2070
2071
  /* get a "list" of alternative names */
2072
0
  altnames = X509_get_ext_d2i(server_cert, NID_subject_alt_name, NULL, NULL);
2073
2074
0
  if(altnames) {
2075
#ifdef HAVE_BORINGSSL_LIKE
2076
    size_t numalts;
2077
    size_t i;
2078
#else
2079
0
    int numalts;
2080
0
    int i;
2081
0
#endif
2082
2083
    /* get amount of alternatives, RFC2459 claims there MUST be at least
2084
       one, but we do not depend on it... */
2085
0
    numalts = sk_GENERAL_NAME_num(altnames);
2086
2087
    /* loop through all alternatives - until a dnsmatch */
2088
0
    for(i = 0; (i < numalts) && !matched; i++) {
2089
      /* get a handle to alternative name number i */
2090
0
      const GENERAL_NAME *check = sk_GENERAL_NAME_value(altnames, i);
2091
2092
0
      if(check->type == GEN_DNS)
2093
0
        dNSName = TRUE;
2094
0
      else if(check->type == GEN_IPADD)
2095
0
        iPAddress = TRUE;
2096
2097
      /* only check alternatives of the same type the target is */
2098
0
      if(check->type == target) {
2099
        /* get data and length */
2100
0
        const char *altptr = (const char *)ASN1_STRING_get0_data(check->d.ia5);
2101
0
        size_t altlen = (size_t)ASN1_STRING_length(check->d.ia5);
2102
2103
0
        switch(target) {
2104
0
        case GEN_DNS: /* name/pattern comparison */
2105
          /* The OpenSSL man page explicitly says: "In general it cannot be
2106
             assumed that the data returned by ASN1_STRING_data() is null
2107
             terminated or does not contain embedded nulls." But also that
2108
             "The actual format of the data will depend on the actual string
2109
             type itself: for example for an IA5String the data will be ASCII"
2110
2111
             It has been however verified that in 0.9.6 and 0.9.7, IA5String
2112
             is always null-terminated.
2113
          */
2114
0
          if((altlen == strlen(altptr)) &&
2115
             /* if this is not true, there was an embedded zero in the name
2116
                string and we cannot match it. */
2117
0
             Curl_cert_hostcheck(altptr, altlen, peer->hostname, hostlen)) {
2118
0
            matched = TRUE;
2119
0
            infof(data, "  subjectAltName: \"%s\" matches cert's \"%.*s\"",
2120
0
                  peer->dispname, (int)altlen, altptr);
2121
0
          }
2122
0
          break;
2123
2124
0
        case GEN_IPADD: /* IP address comparison */
2125
          /* compare alternative IP address if the data chunk is the same size
2126
             our server IP address is */
2127
0
          if((altlen == addrlen) && !memcmp(altptr, &addr, altlen)) {
2128
0
            matched = TRUE;
2129
0
            infof(data, "  subjectAltName: \"%s\" matches cert's IP address!",
2130
0
                  peer->dispname);
2131
0
          }
2132
0
          break;
2133
0
        }
2134
0
      }
2135
0
    }
2136
0
    GENERAL_NAMES_free(altnames);
2137
0
  }
2138
2139
0
  if(matched)
2140
    /* an alternative name matched */
2141
0
    ;
2142
0
  else if(dNSName || iPAddress) {
2143
0
    const char *tname = (peer->type == CURL_SSL_PEER_DNS) ? "hostname" :
2144
0
                        (peer->type == CURL_SSL_PEER_IPV4) ?
2145
0
                        "ipv4 address" : "ipv6 address";
2146
0
    infof(data, " subjectAltName does not match %s %s", tname, peer->dispname);
2147
0
    failf(data, "SSL: no alternative certificate subject name matches "
2148
0
          "target %s '%s'", tname, peer->dispname);
2149
0
    result = CURLE_PEER_FAILED_VERIFICATION;
2150
0
  }
2151
0
  else {
2152
    /* we have to look to the last occurrence of a commonName in the
2153
       distinguished one to get the most significant one. */
2154
0
    int i = -1;
2155
0
    unsigned char *cn = NULL;
2156
0
    int cnlen = 0;
2157
0
    bool free_cn = FALSE;
2158
2159
    /* The following is done because of a bug in 0.9.6b */
2160
0
    X509_NAME *name = X509_get_subject_name(server_cert);
2161
0
    if(name) {
2162
0
      int j;
2163
0
      while((j = X509_NAME_get_index_by_NID(name, NID_commonName, i)) >= 0)
2164
0
        i = j;
2165
0
    }
2166
2167
    /* we have the name entry and we will now convert this to a string
2168
       that we can use for comparison. Doing this we support BMPstring,
2169
       UTF8, etc. */
2170
2171
0
    if(i >= 0) {
2172
0
      ASN1_STRING *tmp =
2173
0
        X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i));
2174
2175
      /* In OpenSSL 0.9.7d and earlier, ASN1_STRING_to_UTF8 fails if the input
2176
         is already UTF-8 encoded. We check for this case and copy the raw
2177
         string manually to avoid the problem. This code can be made
2178
         conditional in the future when OpenSSL has been fixed. */
2179
0
      if(tmp) {
2180
0
        if(ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) {
2181
0
          cnlen = ASN1_STRING_length(tmp);
2182
0
          cn = (unsigned char *)CURL_UNCONST(ASN1_STRING_get0_data(tmp));
2183
0
        }
2184
0
        else { /* not a UTF8 name */
2185
0
          cnlen = ASN1_STRING_to_UTF8(&cn, tmp);
2186
0
          free_cn = TRUE;
2187
0
        }
2188
2189
0
        if((cnlen <= 0) || !cn)
2190
0
          result = CURLE_OUT_OF_MEMORY;
2191
0
        else if((size_t)cnlen != strlen((char *)cn)) {
2192
          /* there was a terminating zero before the end of string, this
2193
             cannot match and we return failure! */
2194
0
          failf(data, "SSL: illegal cert name field");
2195
0
          result = CURLE_PEER_FAILED_VERIFICATION;
2196
0
        }
2197
0
      }
2198
0
    }
2199
2200
0
    if(result)
2201
      /* error already detected, pass through */
2202
0
      ;
2203
0
    else if(!cn) {
2204
0
      failf(data, "SSL: unable to obtain common name from peer certificate");
2205
0
      result = CURLE_PEER_FAILED_VERIFICATION;
2206
0
    }
2207
0
    else if(!Curl_cert_hostcheck((const char *)cn, cnlen,
2208
0
                                 peer->hostname, hostlen)) {
2209
0
      failf(data, "SSL: certificate subject name '%s' does not match "
2210
0
            "target hostname '%s'", cn, peer->dispname);
2211
0
      result = CURLE_PEER_FAILED_VERIFICATION;
2212
0
    }
2213
0
    else {
2214
0
      infof(data, " common name: %s (matched)", cn);
2215
0
    }
2216
0
    if(free_cn)
2217
0
      OPENSSL_free(cn);
2218
0
  }
2219
2220
0
  return result;
2221
0
}
2222
2223
#ifndef OPENSSL_NO_OCSP
2224
static CURLcode verifystatus(struct Curl_cfilter *cf,
2225
                             struct Curl_easy *data,
2226
                             struct ossl_ctx *octx)
2227
0
{
2228
0
  int i, ocsp_status;
2229
#ifdef HAVE_BORINGSSL_LIKE
2230
  const uint8_t *status;
2231
#else
2232
0
  unsigned char *status;
2233
0
#endif
2234
0
  const unsigned char *p;
2235
0
  CURLcode result = CURLE_OK;
2236
0
  OCSP_RESPONSE *rsp = NULL;
2237
0
  OCSP_BASICRESP *br = NULL;
2238
0
  X509_STORE     *st = NULL;
2239
0
  STACK_OF(X509) *ch = NULL;
2240
0
  X509 *cert;
2241
0
  OCSP_CERTID *id = NULL;
2242
0
  int cert_status, crl_reason;
2243
0
  ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
2244
0
  int ret;
2245
0
  long len;
2246
2247
0
  (void)cf;
2248
0
  DEBUGASSERT(octx);
2249
2250
0
  len = (long)SSL_get_tlsext_status_ocsp_resp(octx->ssl, &status);
2251
2252
0
  if(!status) {
2253
0
    failf(data, "No OCSP response received");
2254
0
    result = CURLE_SSL_INVALIDCERTSTATUS;
2255
0
    goto end;
2256
0
  }
2257
0
  p = status;
2258
0
  rsp = d2i_OCSP_RESPONSE(NULL, &p, len);
2259
0
  if(!rsp) {
2260
0
    failf(data, "Invalid OCSP response");
2261
0
    result = CURLE_SSL_INVALIDCERTSTATUS;
2262
0
    goto end;
2263
0
  }
2264
2265
0
  ocsp_status = OCSP_response_status(rsp);
2266
0
  if(ocsp_status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
2267
0
    failf(data, "Invalid OCSP response status: %s (%d)",
2268
0
          OCSP_response_status_str(ocsp_status), ocsp_status);
2269
0
    result = CURLE_SSL_INVALIDCERTSTATUS;
2270
0
    goto end;
2271
0
  }
2272
2273
0
  br = OCSP_response_get1_basic(rsp);
2274
0
  if(!br) {
2275
0
    failf(data, "Invalid OCSP response");
2276
0
    result = CURLE_SSL_INVALIDCERTSTATUS;
2277
0
    goto end;
2278
0
  }
2279
2280
0
  ch = SSL_get_peer_cert_chain(octx->ssl);
2281
0
  if(!ch) {
2282
0
    failf(data, "Could not get peer certificate chain");
2283
0
    result = CURLE_SSL_INVALIDCERTSTATUS;
2284
0
    goto end;
2285
0
  }
2286
0
  st = SSL_CTX_get_cert_store(octx->ssl_ctx);
2287
2288
0
  if(OCSP_basic_verify(br, ch, st, 0) <= 0) {
2289
0
    failf(data, "OCSP response verification failed");
2290
0
    result = CURLE_SSL_INVALIDCERTSTATUS;
2291
0
    goto end;
2292
0
  }
2293
2294
  /* Compute the certificate's ID */
2295
0
  cert = SSL_get1_peer_certificate(octx->ssl);
2296
0
  if(!cert) {
2297
0
    failf(data, "Error getting peer certificate");
2298
0
    result = CURLE_SSL_INVALIDCERTSTATUS;
2299
0
    goto end;
2300
0
  }
2301
2302
0
  for(i = 0; i < (int)sk_X509_num(ch); i++) {
2303
0
    X509 *issuer = sk_X509_value(ch, (ossl_valsize_t)i);
2304
0
    if(X509_check_issued(issuer, cert) == X509_V_OK) {
2305
      /* Note to analysis tools: using SHA1 here is fine. The `id`
2306
       * generated is used as a hash lookup key, not as a verifier
2307
       * of the OCSP data itself. This all according to RFC 5019. */
2308
0
      id = OCSP_cert_to_id(EVP_sha1(), cert, issuer);
2309
0
      break;
2310
0
    }
2311
0
  }
2312
0
  X509_free(cert);
2313
2314
0
  if(!id) {
2315
0
    failf(data, "Error computing OCSP ID");
2316
0
    result = CURLE_SSL_INVALIDCERTSTATUS;
2317
0
    goto end;
2318
0
  }
2319
2320
  /* Find the single OCSP response corresponding to the certificate ID */
2321
0
  ret = OCSP_resp_find_status(br, id, &cert_status, &crl_reason, &rev,
2322
0
                              &thisupd, &nextupd);
2323
0
  OCSP_CERTID_free(id);
2324
0
  if(ret != 1) {
2325
0
    failf(data, "Could not find certificate ID in OCSP response");
2326
0
    result = CURLE_SSL_INVALIDCERTSTATUS;
2327
0
    goto end;
2328
0
  }
2329
2330
  /* Validate the OCSP response issuing and update times.
2331
   * - `thisupd` is the time the OCSP response was issued
2332
   * - `nextupd` is the time the OCSP response should be updated
2333
   *    (valid life time assigned by the OCSP responder)
2334
   * - 3rd param: how many seconds of clock skew we allow between
2335
   *   our clock and the instance that issued the OCSP response
2336
   * - 4th param: how many seconds in the past `thisupd` may be, with
2337
   *   -1 meaning there is no limit. */
2338
0
  if(!OCSP_check_validity(thisupd, nextupd, 300L, -1L)) {
2339
0
    failf(data, "OCSP response has expired");
2340
0
    result = CURLE_SSL_INVALIDCERTSTATUS;
2341
0
    goto end;
2342
0
  }
2343
2344
0
  infof(data, "SSL certificate status: %s (%d)",
2345
0
        OCSP_cert_status_str(cert_status), cert_status);
2346
2347
0
  switch(cert_status) {
2348
0
  case V_OCSP_CERTSTATUS_GOOD:
2349
0
    break;
2350
2351
0
  case V_OCSP_CERTSTATUS_REVOKED:
2352
0
    result = CURLE_SSL_INVALIDCERTSTATUS;
2353
0
    failf(data, "SSL certificate revocation reason: %s (%d)",
2354
0
          OCSP_crl_reason_str(crl_reason), crl_reason);
2355
0
    goto end;
2356
2357
0
  case V_OCSP_CERTSTATUS_UNKNOWN:
2358
0
  default:
2359
0
    result = CURLE_SSL_INVALIDCERTSTATUS;
2360
0
    goto end;
2361
0
  }
2362
2363
0
end:
2364
0
  if(br)
2365
0
    OCSP_BASICRESP_free(br);
2366
0
  OCSP_RESPONSE_free(rsp);
2367
2368
0
  return result;
2369
0
}
2370
#endif
2371
2372
static const char *ssl_msg_type(int ssl_ver, int msg)
2373
0
{
2374
#ifdef SSL2_VERSION_MAJOR  /* OpenSSL 1.0.2, LibreSSL <=3.9.2 */
2375
  if(ssl_ver == SSL2_VERSION_MAJOR) {
2376
    switch(msg) {
2377
    case SSL2_MT_ERROR:
2378
      return "Error";
2379
    case SSL2_MT_CLIENT_HELLO:
2380
      return "Client hello";
2381
    case SSL2_MT_CLIENT_MASTER_KEY:
2382
      return "Client key";
2383
    case SSL2_MT_CLIENT_FINISHED:
2384
      return "Client finished";
2385
    case SSL2_MT_SERVER_HELLO:
2386
      return "Server hello";
2387
    case SSL2_MT_SERVER_VERIFY:
2388
      return "Server verify";
2389
    case SSL2_MT_SERVER_FINISHED:
2390
      return "Server finished";
2391
    case SSL2_MT_REQUEST_CERTIFICATE:
2392
      return "Request CERT";
2393
    case SSL2_MT_CLIENT_CERTIFICATE:
2394
      return "Client CERT";
2395
    }
2396
  }
2397
  else
2398
#endif
2399
0
  if(ssl_ver == SSL3_VERSION_MAJOR) {
2400
0
    switch(msg) {
2401
0
    case SSL3_MT_HELLO_REQUEST:
2402
0
      return "Hello request";
2403
0
    case SSL3_MT_CLIENT_HELLO:
2404
0
      return "Client hello";
2405
0
    case SSL3_MT_SERVER_HELLO:
2406
0
      return "Server hello";
2407
0
#ifdef SSL3_MT_NEWSESSION_TICKET
2408
0
    case SSL3_MT_NEWSESSION_TICKET:
2409
0
      return "Newsession Ticket";
2410
0
#endif
2411
0
    case SSL3_MT_CERTIFICATE:
2412
0
      return "Certificate";
2413
0
    case SSL3_MT_SERVER_KEY_EXCHANGE:
2414
0
      return "Server key exchange";
2415
0
    case SSL3_MT_CLIENT_KEY_EXCHANGE:
2416
0
      return "Client key exchange";
2417
0
    case SSL3_MT_CERTIFICATE_REQUEST:
2418
0
      return "Request CERT";
2419
0
    case SSL3_MT_SERVER_DONE:
2420
0
      return "Server finished";
2421
0
    case SSL3_MT_CERTIFICATE_VERIFY:
2422
0
      return "CERT verify";
2423
0
    case SSL3_MT_FINISHED:
2424
0
      return "Finished";
2425
0
#ifdef SSL3_MT_CERTIFICATE_STATUS
2426
0
    case SSL3_MT_CERTIFICATE_STATUS:
2427
0
      return "Certificate Status";
2428
0
#endif
2429
0
#ifdef SSL3_MT_ENCRYPTED_EXTENSIONS
2430
0
    case SSL3_MT_ENCRYPTED_EXTENSIONS:
2431
0
      return "Encrypted Extensions";
2432
0
#endif
2433
0
#ifdef SSL3_MT_SUPPLEMENTAL_DATA
2434
0
    case SSL3_MT_SUPPLEMENTAL_DATA:
2435
0
      return "Supplemental data";
2436
0
#endif
2437
0
#ifdef SSL3_MT_END_OF_EARLY_DATA
2438
0
    case SSL3_MT_END_OF_EARLY_DATA:
2439
0
      return "End of early data";
2440
0
#endif
2441
0
#ifdef SSL3_MT_KEY_UPDATE
2442
0
    case SSL3_MT_KEY_UPDATE:
2443
0
      return "Key update";
2444
0
#endif
2445
0
#ifdef SSL3_MT_NEXT_PROTO
2446
0
    case SSL3_MT_NEXT_PROTO:
2447
0
      return "Next protocol";
2448
0
#endif
2449
0
#ifdef SSL3_MT_MESSAGE_HASH
2450
0
    case SSL3_MT_MESSAGE_HASH:
2451
0
      return "Message hash";
2452
0
#endif
2453
0
    }
2454
0
  }
2455
0
  return "Unknown";
2456
0
}
2457
2458
static const char *tls_rt_type(int type)
2459
0
{
2460
0
  switch(type) {
2461
0
#ifdef SSL3_RT_HEADER
2462
0
  case SSL3_RT_HEADER:
2463
0
    return "TLS header";
2464
0
#endif
2465
0
  case SSL3_RT_CHANGE_CIPHER_SPEC:
2466
0
    return "TLS change cipher";
2467
0
  case SSL3_RT_ALERT:
2468
0
    return "TLS alert";
2469
0
  case SSL3_RT_HANDSHAKE:
2470
0
    return "TLS handshake";
2471
0
  case SSL3_RT_APPLICATION_DATA:
2472
0
    return "TLS app data";
2473
0
  default:
2474
0
    return "TLS Unknown";
2475
0
  }
2476
0
}
2477
2478
/*
2479
 * Our callback from the SSL/TLS layers.
2480
 */
2481
static void ossl_trace(int direction, int ssl_ver, int content_type,
2482
                       const void *buf, size_t len, SSL *ssl,
2483
                       void *userp)
2484
0
{
2485
0
  const char *verstr;
2486
0
  struct Curl_cfilter *cf = userp;
2487
0
  struct Curl_easy *data = NULL;
2488
0
  char unknown[32];
2489
2490
0
  if(!cf)
2491
0
    return;
2492
0
  data = CF_DATA_CURRENT(cf);
2493
0
  if(!data || !data->set.fdebug || (direction && direction != 1))
2494
0
    return;
2495
2496
0
  switch(ssl_ver) {
2497
0
#ifdef SSL2_VERSION /* removed in recent versions */
2498
0
  case SSL2_VERSION:
2499
0
    verstr = "SSLv2";
2500
0
    break;
2501
0
#endif
2502
0
#ifdef SSL3_VERSION
2503
0
  case SSL3_VERSION:
2504
0
    verstr = "SSLv3";
2505
0
    break;
2506
0
#endif
2507
0
  case TLS1_VERSION:
2508
0
    verstr = "TLSv1.0";
2509
0
    break;
2510
0
#ifdef TLS1_1_VERSION
2511
0
  case TLS1_1_VERSION:
2512
0
    verstr = "TLSv1.1";
2513
0
    break;
2514
0
#endif
2515
0
#ifdef TLS1_2_VERSION
2516
0
  case TLS1_2_VERSION:
2517
0
    verstr = "TLSv1.2";
2518
0
    break;
2519
0
#endif
2520
0
  case TLS1_3_VERSION:
2521
0
    verstr = "TLSv1.3";
2522
0
    break;
2523
0
  default:
2524
0
    curl_msnprintf(unknown, sizeof(unknown), "(%x)", ssl_ver);
2525
0
    verstr = unknown;
2526
0
    break;
2527
0
  }
2528
2529
  /* Log progress for interesting records only (like Handshake or Alert), skip
2530
   * all raw record headers (content_type == SSL3_RT_HEADER or ssl_ver == 0).
2531
   * For TLS 1.3, skip notification of the decrypted inner Content-Type.
2532
   */
2533
0
  if(ssl_ver
2534
0
#ifdef SSL3_RT_HEADER
2535
0
     && content_type != SSL3_RT_HEADER
2536
0
#endif
2537
0
#ifdef SSL3_RT_INNER_CONTENT_TYPE
2538
0
     && content_type != SSL3_RT_INNER_CONTENT_TYPE
2539
0
#endif
2540
0
    ) {
2541
0
    const char *msg_name, *tls_rt_name;
2542
0
    char ssl_buf[1024];
2543
0
    int msg_type, txt_len;
2544
2545
    /* the info given when the version is zero is not that useful for us */
2546
2547
0
    ssl_ver >>= 8; /* check the upper 8 bits only below */
2548
2549
    /* SSLv2 does not seem to have TLS record-type headers, so OpenSSL
2550
     * always pass-up content-type as 0. But the interesting message-type
2551
     * is at 'buf[0]'.
2552
     */
2553
0
    if(ssl_ver == SSL3_VERSION_MAJOR && content_type)
2554
0
      tls_rt_name = tls_rt_type(content_type);
2555
0
    else
2556
0
      tls_rt_name = "";
2557
2558
0
    if(content_type == SSL3_RT_CHANGE_CIPHER_SPEC) {
2559
0
      msg_type = *(const char *)buf;
2560
0
      msg_name = "Change cipher spec";
2561
0
    }
2562
0
    else if(content_type == SSL3_RT_ALERT) {
2563
0
      msg_type = (((const char *)buf)[0] << 8) + ((const char *)buf)[1];
2564
0
      msg_name = SSL_alert_desc_string_long(msg_type);
2565
0
    }
2566
0
    else {
2567
0
      msg_type = *(const char *)buf;
2568
0
      msg_name = ssl_msg_type(ssl_ver, msg_type);
2569
0
    }
2570
2571
0
    txt_len = curl_msnprintf(ssl_buf, sizeof(ssl_buf),
2572
0
                             "%s (%s), %s, %s (%d):\n",
2573
0
                             verstr, direction ? "OUT" : "IN",
2574
0
                             tls_rt_name, msg_name, msg_type);
2575
0
    Curl_debug(data, CURLINFO_TEXT, ssl_buf, (size_t)txt_len);
2576
0
  }
2577
2578
0
  Curl_debug(data, (direction == 1) ? CURLINFO_SSL_DATA_OUT :
2579
0
             CURLINFO_SSL_DATA_IN, (const char *)buf, len);
2580
0
  (void)ssl;
2581
0
}
2582
2583
static CURLcode ossl_set_ssl_version_min_max(struct Curl_cfilter *cf,
2584
                                             SSL_CTX *ctx,
2585
                                             unsigned int ssl_version_min)
2586
0
{
2587
0
  struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
2588
  /* first, TLS min version... */
2589
0
  long curl_ssl_version_min = (long)ssl_version_min;
2590
0
  long curl_ssl_version_max;
2591
2592
  /* convert curl min SSL version option to OpenSSL constant */
2593
#if defined(HAVE_BORINGSSL_LIKE) || defined(LIBRESSL_VERSION_NUMBER)
2594
  uint16_t ossl_ssl_version_min = 0;
2595
  uint16_t ossl_ssl_version_max = 0;
2596
#else
2597
0
  long ossl_ssl_version_min = 0;
2598
0
  long ossl_ssl_version_max = 0;
2599
0
#endif
2600
  /* it cannot be default here */
2601
0
  DEBUGASSERT(curl_ssl_version_min != CURL_SSLVERSION_DEFAULT);
2602
0
  switch(curl_ssl_version_min) {
2603
0
  case CURL_SSLVERSION_TLSv1: /* TLS 1.x */
2604
0
  case CURL_SSLVERSION_TLSv1_0:
2605
0
    ossl_ssl_version_min = TLS1_VERSION;
2606
0
    break;
2607
0
  case CURL_SSLVERSION_TLSv1_1:
2608
0
    ossl_ssl_version_min = TLS1_1_VERSION;
2609
0
    break;
2610
0
  case CURL_SSLVERSION_TLSv1_2:
2611
0
    ossl_ssl_version_min = TLS1_2_VERSION;
2612
0
    break;
2613
0
  case CURL_SSLVERSION_TLSv1_3:
2614
0
    ossl_ssl_version_min = TLS1_3_VERSION;
2615
0
    break;
2616
0
  }
2617
2618
  /* ... then, TLS max version */
2619
0
  curl_ssl_version_max = (long)conn_config->version_max;
2620
2621
  /* convert curl max SSL version option to OpenSSL constant */
2622
0
  switch(curl_ssl_version_max) {
2623
0
  case CURL_SSLVERSION_MAX_TLSv1_0:
2624
0
    ossl_ssl_version_max = TLS1_VERSION;
2625
0
    break;
2626
0
  case CURL_SSLVERSION_MAX_TLSv1_1:
2627
0
    ossl_ssl_version_max = TLS1_1_VERSION;
2628
0
    break;
2629
0
  case CURL_SSLVERSION_MAX_TLSv1_2:
2630
0
    ossl_ssl_version_max = TLS1_2_VERSION;
2631
0
    break;
2632
0
  case CURL_SSLVERSION_MAX_TLSv1_3:
2633
0
    ossl_ssl_version_max = TLS1_3_VERSION;
2634
0
    break;
2635
0
  case CURL_SSLVERSION_MAX_NONE:  /* none selected */
2636
0
  case CURL_SSLVERSION_MAX_DEFAULT:  /* max selected */
2637
0
  default:
2638
    /* SSL_CTX_set_max_proto_version states that: setting the maximum to 0
2639
       will enable protocol versions up to the highest version supported by
2640
       the library */
2641
0
    ossl_ssl_version_max = 0;
2642
0
    break;
2643
0
  }
2644
2645
0
  if(!SSL_CTX_set_min_proto_version(ctx, ossl_ssl_version_min) ||
2646
0
     !SSL_CTX_set_max_proto_version(ctx, ossl_ssl_version_max))
2647
0
    return CURLE_SSL_CONNECT_ERROR;
2648
2649
0
  return CURLE_OK;
2650
0
}
2651
2652
#ifdef HAVE_BORINGSSL_LIKE
2653
typedef uint32_t ctx_option_t;
2654
#elif defined(HAVE_OPENSSL3)
2655
typedef uint64_t ctx_option_t;
2656
#elif defined(LIBRESSL_VERSION_NUMBER)
2657
typedef long ctx_option_t;
2658
#else
2659
typedef unsigned long ctx_option_t;
2660
#endif
2661
2662
CURLcode Curl_ossl_add_session(struct Curl_cfilter *cf,
2663
                               struct Curl_easy *data,
2664
                               const char *ssl_peer_key,
2665
                               SSL_SESSION *session,
2666
                               int ietf_tls_id,
2667
                               const char *alpn,
2668
                               unsigned char *quic_tp,
2669
                               size_t quic_tp_len)
2670
0
{
2671
0
  unsigned char *der_session_buf = NULL;
2672
0
  unsigned char *qtp_clone = NULL;
2673
0
  CURLcode result = CURLE_OK;
2674
2675
0
  if(!cf || !data)
2676
0
    goto out;
2677
2678
0
  if(Curl_ssl_scache_use(cf, data)) {
2679
0
    struct Curl_ssl_session *sc_session = NULL;
2680
0
    size_t der_session_size;
2681
0
    unsigned char *der_session_ptr;
2682
0
    size_t earlydata_max = 0;
2683
2684
0
    der_session_size = i2d_SSL_SESSION(session, NULL);
2685
0
    if(der_session_size == 0) {
2686
0
      result = CURLE_OUT_OF_MEMORY;
2687
0
      goto out;
2688
0
    }
2689
2690
0
    der_session_buf = der_session_ptr = curlx_malloc(der_session_size);
2691
0
    if(!der_session_buf) {
2692
0
      result = CURLE_OUT_OF_MEMORY;
2693
0
      goto out;
2694
0
    }
2695
2696
0
    der_session_size = i2d_SSL_SESSION(session, &der_session_ptr);
2697
0
    if(der_session_size == 0) {
2698
0
      result = CURLE_OUT_OF_MEMORY;
2699
0
      goto out;
2700
0
    }
2701
2702
0
#ifdef HAVE_OPENSSL_EARLYDATA
2703
0
    earlydata_max = SSL_SESSION_get_max_early_data(session);
2704
0
#endif
2705
0
    if(quic_tp && quic_tp_len) {
2706
0
      qtp_clone = Curl_memdup0((char *)quic_tp, quic_tp_len);
2707
0
      if(!qtp_clone) {
2708
0
        result = CURLE_OUT_OF_MEMORY;
2709
0
        goto out;
2710
0
      }
2711
0
    }
2712
2713
0
    result = Curl_ssl_session_create2(der_session_buf, der_session_size,
2714
0
                                      ietf_tls_id, alpn,
2715
0
                                      (curl_off_t)time(NULL) +
2716
0
                                        SSL_SESSION_get_timeout(session),
2717
0
                                      earlydata_max, qtp_clone, quic_tp_len,
2718
0
                                      &sc_session);
2719
0
    der_session_buf = NULL;  /* took ownership of sdata */
2720
0
    if(!result) {
2721
0
      result = Curl_ssl_scache_put(cf, data, ssl_peer_key, sc_session);
2722
      /* took ownership of `sc_session` */
2723
0
    }
2724
0
  }
2725
2726
0
out:
2727
0
  curlx_free(der_session_buf);
2728
0
  return result;
2729
0
}
2730
2731
/* The "new session" callback must return zero if the session can be removed
2732
 * or non-zero if the session has been put into the session cache.
2733
 */
2734
static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
2735
0
{
2736
0
  struct Curl_cfilter *cf = (struct Curl_cfilter *)SSL_get_app_data(ssl);
2737
0
  if(cf) {
2738
0
    struct Curl_easy *data = CF_DATA_CURRENT(cf);
2739
0
    struct ssl_connect_data *connssl = cf->ctx;
2740
0
    Curl_ossl_add_session(cf, data, connssl->peer.scache_key, ssl_sessionid,
2741
0
                          SSL_version(ssl), connssl->negotiated.alpn, NULL, 0);
2742
0
  }
2743
0
  return 0;
2744
0
}
2745
2746
static CURLcode load_cacert_from_memory(X509_STORE *store,
2747
                                        const struct curl_blob *ca_info_blob)
2748
0
{
2749
  /* these need to be freed at the end */
2750
0
  BIO *cbio = NULL;
2751
0
  STACK_OF(X509_INFO) *inf = NULL;
2752
2753
  /* everything else is just a reference */
2754
0
  int i, count = 0;
2755
0
  X509_INFO *itmp = NULL;
2756
2757
0
  if(ca_info_blob->len > (size_t)INT_MAX)
2758
0
    return CURLE_SSL_CACERT_BADFILE;
2759
2760
0
  cbio = BIO_new_mem_buf(ca_info_blob->data, (int)ca_info_blob->len);
2761
0
  if(!cbio)
2762
0
    return CURLE_OUT_OF_MEMORY;
2763
2764
0
  inf = PEM_X509_INFO_read_bio(cbio, NULL, NULL, NULL);
2765
0
  if(!inf) {
2766
0
    BIO_free(cbio);
2767
0
    return CURLE_SSL_CACERT_BADFILE;
2768
0
  }
2769
2770
  /* add each entry from PEM file to x509_store */
2771
0
  for(i = 0; i < (int)sk_X509_INFO_num(inf); ++i) {
2772
0
    itmp = sk_X509_INFO_value(inf, (ossl_valsize_t)i);
2773
0
    if(itmp->x509) {
2774
0
      if(X509_STORE_add_cert(store, itmp->x509)) {
2775
0
        ++count;
2776
0
      }
2777
0
      else {
2778
        /* set count to 0 to return an error */
2779
0
        count = 0;
2780
0
        break;
2781
0
      }
2782
0
    }
2783
0
    if(itmp->crl) {
2784
0
      if(X509_STORE_add_crl(store, itmp->crl)) {
2785
0
        ++count;
2786
0
      }
2787
0
      else {
2788
        /* set count to 0 to return an error */
2789
0
        count = 0;
2790
0
        break;
2791
0
      }
2792
0
    }
2793
0
  }
2794
2795
0
#if defined(__clang__) && __clang_major__ >= 16
2796
0
#pragma clang diagnostic push
2797
0
#pragma clang diagnostic ignored "-Wcast-function-type-strict"
2798
0
#endif
2799
0
  sk_X509_INFO_pop_free(inf, X509_INFO_free);
2800
0
#if defined(__clang__) && __clang_major__ >= 16
2801
0
#pragma clang diagnostic pop
2802
0
#endif
2803
0
  BIO_free(cbio);
2804
2805
  /* if we did not end up importing anything, treat that as an error */
2806
0
  return (count > 0) ? CURLE_OK : CURLE_SSL_CACERT_BADFILE;
2807
0
}
2808
2809
#ifdef USE_WIN32_CRYPTO
2810
static CURLcode ossl_win_load_store(struct Curl_easy *data,
2811
                                    const char *win_store,
2812
                                    X509_STORE *store,
2813
                                    bool *padded)
2814
{
2815
  CURLcode result = CURLE_OK;
2816
  HCERTSTORE hStore;
2817
2818
  *padded = FALSE;
2819
2820
  hStore = CertOpenSystemStoreA(0, win_store);
2821
  if(hStore) {
2822
    PCCERT_CONTEXT pContext = NULL;
2823
    /* The array of enhanced key usage OIDs will vary per certificate and
2824
       is declared outside of the loop so that rather than malloc/free each
2825
       iteration we can grow it with realloc, when necessary. */
2826
    CERT_ENHKEY_USAGE *enhkey_usage = NULL;
2827
    DWORD enhkey_usage_size = 0;
2828
2829
    /* This loop makes a best effort to import all valid certificates from
2830
       the MS root store. If a certificate cannot be imported it is
2831
       skipped. 'result' is used to store only hard-fail conditions (such
2832
       as out of memory) that cause an early break. */
2833
    result = CURLE_OK;
2834
    for(;;) {
2835
      X509 *x509;
2836
      FILETIME now;
2837
      BYTE key_usage[2];
2838
      DWORD req_size;
2839
      const unsigned char *encoded_cert;
2840
      pContext = CertEnumCertificatesInStore(hStore, pContext);
2841
      if(!pContext)
2842
        break;
2843
2844
#if defined(DEBUGBUILD) && defined(CURLVERBOSE)
2845
      else {
2846
        char cert_name[256];
2847
        if(!CertGetNameStringA(pContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0,
2848
                               NULL, cert_name, sizeof(cert_name)))
2849
          infof(data, "SSL: unknown cert name");
2850
        else
2851
          infof(data, "SSL: Checking cert \"%s\"", cert_name);
2852
      }
2853
#endif
2854
      encoded_cert = (const unsigned char *)pContext->pbCertEncoded;
2855
      if(!encoded_cert)
2856
        continue;
2857
2858
      GetSystemTimeAsFileTime(&now);
2859
      if(CompareFileTime(&pContext->pCertInfo->NotBefore, &now) > 0 ||
2860
         CompareFileTime(&now, &pContext->pCertInfo->NotAfter) > 0)
2861
        continue;
2862
2863
      /* If key usage exists check for signing attribute */
2864
      if(CertGetIntendedKeyUsage(pContext->dwCertEncodingType,
2865
                                 pContext->pCertInfo,
2866
                                 key_usage, sizeof(key_usage))) {
2867
        if(!(key_usage[0] & CERT_KEY_CERT_SIGN_KEY_USAGE))
2868
          continue;
2869
      }
2870
      else if(GetLastError())
2871
        continue;
2872
2873
      /* If enhanced key usage exists check for server auth attribute.
2874
       *
2875
       * Note "In a Microsoft environment, a certificate might also have
2876
       * EKU extended properties that specify valid uses for the
2877
       * certificate."  The call below checks both, and behavior varies
2878
       * depending on what is found. For more details see
2879
       * CertGetEnhancedKeyUsage doc.
2880
       */
2881
      if(CertGetEnhancedKeyUsage(pContext, 0, NULL, &req_size)) {
2882
        if(req_size && req_size > enhkey_usage_size) {
2883
          void *tmp = curlx_realloc(enhkey_usage, req_size);
2884
2885
          if(!tmp) {
2886
            failf(data, "SSL: Out of memory allocating for OID list");
2887
            result = CURLE_OUT_OF_MEMORY;
2888
            break;
2889
          }
2890
2891
          enhkey_usage = (CERT_ENHKEY_USAGE *)tmp;
2892
          enhkey_usage_size = req_size;
2893
        }
2894
2895
        if(CertGetEnhancedKeyUsage(pContext, 0, enhkey_usage, &req_size)) {
2896
          if(!enhkey_usage->cUsageIdentifier) {
2897
            /* "If GetLastError returns CRYPT_E_NOT_FOUND, the certificate
2898
               is good for all uses. If it returns zero, the certificate
2899
               has no valid uses." */
2900
            if((HRESULT)GetLastError() != CRYPT_E_NOT_FOUND)
2901
              continue;
2902
          }
2903
          else {
2904
            DWORD i;
2905
            bool found = FALSE;
2906
2907
            for(i = 0; i < enhkey_usage->cUsageIdentifier; ++i) {
2908
              if(!strcmp("1.3.6.1.5.5.7.3.1" /* OID server auth */,
2909
                         enhkey_usage->rgpszUsageIdentifier[i])) {
2910
                found = TRUE;
2911
                break;
2912
              }
2913
            }
2914
2915
            if(!found)
2916
              continue;
2917
          }
2918
        }
2919
        else
2920
          continue;
2921
      }
2922
      else
2923
        continue;
2924
2925
      x509 = d2i_X509(NULL, &encoded_cert, (long)pContext->cbCertEncoded);
2926
      if(!x509)
2927
        continue;
2928
2929
      /* Try to import the certificate. This may fail for legitimate reasons
2930
         such as duplicate certificate, which is allowed by MS but not
2931
         OpenSSL. */
2932
      if(X509_STORE_add_cert(store, x509) == 1) {
2933
#ifdef DEBUGBUILD
2934
        infof(data, "SSL: Imported cert");
2935
#endif
2936
        *padded = TRUE;
2937
      }
2938
      X509_free(x509);
2939
    }
2940
2941
    curlx_free(enhkey_usage);
2942
    CertFreeCertificateContext(pContext);
2943
    CertCloseStore(hStore, 0);
2944
2945
    if(result)
2946
      return result;
2947
  }
2948
2949
  return result;
2950
}
2951
2952
static CURLcode ossl_windows_load_anchors(struct Curl_cfilter *cf,
2953
                                          struct Curl_easy *data,
2954
                                          X509_STORE *store,
2955
                                          bool *padded)
2956
{
2957
  /* Import certificates from the Windows root certificate store if
2958
     requested.
2959
     https://stackoverflow.com/questions/9507184/
2960
     https://github.com/d3x0r/SACK/blob/master/src/netlib/ssl_layer.c#L1037
2961
     https://datatracker.ietf.org/doc/html/rfc5280 */
2962
  const char *win_stores[] = {
2963
    "ROOT",   /* Trusted Root Certification Authorities */
2964
    "CA"      /* Intermediate Certification Authorities */
2965
  };
2966
  size_t i;
2967
  CURLcode result = CURLE_OK;
2968
2969
  *padded = FALSE;
2970
  for(i = 0; i < CURL_ARRAYSIZE(win_stores); ++i) {
2971
    bool store_added = FALSE;
2972
    result = ossl_win_load_store(data, win_stores[i], store, &store_added);
2973
    if(result)
2974
      return result;
2975
    if(store_added) {
2976
      CURL_TRC_CF(data, cf, "added trust anchors from Windows %s store",
2977
                  win_stores[i]);
2978
      *padded = TRUE;
2979
    }
2980
    else
2981
      infof(data, "error importing Windows %s store, continuing anyway",
2982
            win_stores[i]);
2983
  }
2984
  return result;
2985
}
2986
2987
#endif /* USE_WIN32_CRYPTO */
2988
2989
static CURLcode ossl_load_trust_anchors(struct Curl_cfilter *cf,
2990
                                        struct Curl_easy *data,
2991
                                        struct ossl_ctx *octx,
2992
                                        X509_STORE *store)
2993
0
{
2994
0
  struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
2995
0
  struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
2996
0
  CURLcode result = CURLE_OK;
2997
0
  const char * const ssl_cafile =
2998
    /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
2999
0
    (conn_config->ca_info_blob ? NULL : conn_config->CAfile);
3000
0
  const char * const ssl_capath = conn_config->CApath;
3001
0
  bool have_native_check = FALSE;
3002
3003
0
  octx->store_is_empty = TRUE;
3004
0
  if(ssl_config->native_ca_store) {
3005
#ifdef USE_WIN32_CRYPTO
3006
    bool added = FALSE;
3007
    result = ossl_windows_load_anchors(cf, data, store, &added);
3008
    if(result)
3009
      return result;
3010
    if(added) {
3011
      infof(data, "  Native: Windows System Stores ROOT+CA");
3012
      octx->store_is_empty = FALSE;
3013
    }
3014
#elif defined(USE_APPLE_SECTRUST)
3015
    infof(data, "  Native: Apple SecTrust");
3016
    have_native_check = TRUE;
3017
#endif
3018
0
  }
3019
3020
0
  if(conn_config->ca_info_blob) {
3021
0
    result = load_cacert_from_memory(store, conn_config->ca_info_blob);
3022
0
    if(result) {
3023
0
      failf(data, "error adding trust anchors from certificate blob: %d",
3024
0
            result);
3025
0
      return result;
3026
0
    }
3027
0
    infof(data, "  CA Blob from configuration");
3028
0
    octx->store_is_empty = FALSE;
3029
0
  }
3030
3031
0
  if(ssl_cafile || ssl_capath) {
3032
0
#ifdef HAVE_OPENSSL3
3033
    /* OpenSSL 3.0.0 has deprecated SSL_CTX_load_verify_locations */
3034
0
    if(ssl_cafile) {
3035
0
      if(!X509_STORE_load_file(store, ssl_cafile)) {
3036
0
        if(octx->store_is_empty && !have_native_check) {
3037
          /* Fail if we insist on successfully verifying the server. */
3038
0
          failf(data, "error adding trust anchors from file: %s", ssl_cafile);
3039
0
          return CURLE_SSL_CACERT_BADFILE;
3040
0
        }
3041
0
        else
3042
0
          infof(data, "error setting certificate file, continuing anyway");
3043
0
      }
3044
0
      infof(data, "  CAfile: %s", ssl_cafile);
3045
0
      octx->store_is_empty = FALSE;
3046
0
    }
3047
0
    if(ssl_capath) {
3048
0
      if(!X509_STORE_load_path(store, ssl_capath)) {
3049
0
        if(octx->store_is_empty && !have_native_check) {
3050
          /* Fail if we insist on successfully verifying the server. */
3051
0
          failf(data, "error adding trust anchors from path: %s", ssl_capath);
3052
0
          return CURLE_SSL_CACERT_BADFILE;
3053
0
        }
3054
0
        else
3055
0
          infof(data, "error setting certificate path, continuing anyway");
3056
0
      }
3057
0
      infof(data, "  CApath: %s", ssl_capath);
3058
0
      octx->store_is_empty = FALSE;
3059
0
    }
3060
#else
3061
    /* tell OpenSSL where to find CA certificates that are used to verify the
3062
       server's certificate. */
3063
    if(!X509_STORE_load_locations(store, ssl_cafile, ssl_capath)) {
3064
      if(octx->store_is_empty && !have_native_check) {
3065
        /* Fail if we insist on successfully verifying the server. */
3066
        failf(data, "error adding trust anchors from locations:"
3067
              "  CAfile: %s CApath: %s",
3068
              ssl_cafile ? ssl_cafile : "none",
3069
              ssl_capath ? ssl_capath : "none");
3070
        return CURLE_SSL_CACERT_BADFILE;
3071
      }
3072
      else {
3073
        infof(data, "error setting certificate verify locations,"
3074
              " continuing anyway");
3075
      }
3076
    }
3077
    if(ssl_cafile)
3078
      infof(data, "  CAfile: %s", ssl_cafile);
3079
    if(ssl_capath)
3080
      infof(data, "  CApath: %s", ssl_capath);
3081
    octx->store_is_empty = FALSE;
3082
#endif
3083
0
  }
3084
3085
#ifdef CURL_CA_FALLBACK
3086
  if(octx->store_is_empty) {
3087
    /* verifying the peer without any CA certificates will not
3088
       work so use OpenSSL's built-in default as fallback */
3089
    X509_STORE_set_default_paths(store);
3090
    infof(data, "  OpenSSL default paths (fallback)");
3091
    octx->store_is_empty = FALSE;
3092
  }
3093
#endif
3094
0
  if(octx->store_is_empty && !have_native_check)
3095
0
    infof(data, "  no trust anchors configured");
3096
3097
0
  return result;
3098
0
}
3099
3100
static CURLcode ossl_populate_x509_store(struct Curl_cfilter *cf,
3101
                                         struct Curl_easy *data,
3102
                                         struct ossl_ctx *octx,
3103
                                         X509_STORE *store)
3104
0
{
3105
0
  struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
3106
0
  struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
3107
0
  CURLcode result = CURLE_OK;
3108
0
  X509_LOOKUP *lookup = NULL;
3109
0
  const char * const ssl_crlfile = ssl_config->primary.CRLfile;
3110
0
  unsigned long x509flags = 0;
3111
3112
0
  CURL_TRC_CF(data, cf, "configuring OpenSSL's x509 trust store");
3113
0
  if(!store)
3114
0
    return CURLE_OUT_OF_MEMORY;
3115
3116
0
  if(!conn_config->verifypeer) {
3117
0
    infof(data, "SSL Trust: peer verification disabled");
3118
0
    return CURLE_OK;
3119
0
  }
3120
3121
0
  infof(data, "SSL Trust Anchors:");
3122
0
  result = ossl_load_trust_anchors(cf, data, octx, store);
3123
0
  if(result)
3124
0
    return result;
3125
3126
  /* Does not make sense to load a CRL file without peer verification */
3127
0
  if(ssl_crlfile) {
3128
    /* tell OpenSSL where to find CRL file that is used to check certificate
3129
     * revocation */
3130
0
    lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
3131
0
    if(!lookup ||
3132
0
       (!X509_load_crl_file(lookup, ssl_crlfile, X509_FILETYPE_PEM))) {
3133
0
      failf(data, "error loading CRL file: %s", ssl_crlfile);
3134
0
      return CURLE_SSL_CRL_BADFILE;
3135
0
    }
3136
0
    x509flags = X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL;
3137
0
    infof(data, " CRLfile: %s", ssl_crlfile);
3138
0
  }
3139
3140
  /* Try building a chain using issuers in the trusted store first to avoid
3141
     problems with server-sent legacy intermediates. Newer versions of
3142
     OpenSSL do alternate chain checking by default but we do not know how to
3143
     determine that in a reliable manner.
3144
     https://web.archive.org/web/20190422050538/rt.openssl.org/Ticket/Display.html?id=3621
3145
  */
3146
0
  x509flags |= X509_V_FLAG_TRUSTED_FIRST;
3147
3148
0
  if(!ssl_config->no_partialchain && !ssl_crlfile) {
3149
    /* Have intermediate certificates in the trust store be treated as
3150
       trust-anchors, in the same way as self-signed root CA certificates are.
3151
       This allows users to verify servers using the intermediate cert only,
3152
       instead of needing the whole chain.
3153
3154
       Due to OpenSSL bug https://github.com/openssl/openssl/issues/5081 we
3155
       cannot do partial chains with a CRL check.
3156
    */
3157
0
    x509flags |= X509_V_FLAG_PARTIAL_CHAIN;
3158
0
  }
3159
0
  (void)X509_STORE_set_flags(store, x509flags);
3160
3161
0
  return result;
3162
0
}
3163
3164
/* key to use at `multi->proto_hash` */
3165
0
#define MPROTO_OSSL_X509_KEY  "tls:ossl:x509:share"
3166
3167
struct ossl_x509_share {
3168
  char *CAfile;         /* CAfile path used to generate X509 store */
3169
  X509_STORE *store;    /* cached X509 store or NULL if none */
3170
  struct curltime time; /* when the cached store was created */
3171
  BIT(store_is_empty);  /* no certs/paths/blobs are in the store */
3172
  BIT(no_partialchain); /* keep partial chain state */
3173
};
3174
3175
static void oss_x509_share_free(void *key, size_t key_len, void *p)
3176
0
{
3177
0
  struct ossl_x509_share *share = p;
3178
0
  DEBUGASSERT(key_len == (sizeof(MPROTO_OSSL_X509_KEY) - 1));
3179
0
  DEBUGASSERT(!memcmp(MPROTO_OSSL_X509_KEY, key, key_len));
3180
0
  (void)key;
3181
0
  (void)key_len;
3182
0
  if(share->store) {
3183
0
    X509_STORE_free(share->store);
3184
0
  }
3185
0
  curlx_free(share->CAfile);
3186
0
  curlx_free(share);
3187
0
}
3188
3189
static bool ossl_cached_x509_store_expired(struct Curl_easy *data,
3190
                                           const struct ossl_x509_share *mb)
3191
0
{
3192
0
  const struct ssl_general_config *cfg = &data->set.general_ssl;
3193
0
  if(cfg->ca_cache_timeout < 0)
3194
0
    return FALSE;
3195
0
  else {
3196
0
    timediff_t elapsed_ms = curlx_ptimediff_ms(Curl_pgrs_now(data), &mb->time);
3197
0
    timediff_t timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000;
3198
3199
0
    return elapsed_ms >= timeout_ms;
3200
0
  }
3201
0
}
3202
3203
static bool ossl_cached_x509_store_different(struct Curl_cfilter *cf,
3204
                                             const struct Curl_easy *data,
3205
                                             const struct ossl_x509_share *mb)
3206
0
{
3207
0
  struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
3208
0
  struct ssl_config_data *ssl_config =
3209
0
    Curl_ssl_cf_get_config(cf, CURL_UNCONST(data));
3210
0
  if(mb->no_partialchain != ssl_config->no_partialchain)
3211
0
    return TRUE;
3212
0
  if(!mb->CAfile || !conn_config->CAfile)
3213
0
    return mb->CAfile != conn_config->CAfile;
3214
0
  return strcmp(mb->CAfile, conn_config->CAfile);
3215
0
}
3216
3217
static X509_STORE *ossl_get_cached_x509_store(struct Curl_cfilter *cf,
3218
                                              struct Curl_easy *data,
3219
                                              bool *pempty)
3220
0
{
3221
0
  struct Curl_multi *multi = data->multi;
3222
0
  struct ossl_x509_share *share;
3223
0
  X509_STORE *store = NULL;
3224
3225
0
  DEBUGASSERT(multi);
3226
0
  *pempty = TRUE;
3227
0
  share = multi ? Curl_hash_pick(&multi->proto_hash,
3228
0
                                 CURL_UNCONST(MPROTO_OSSL_X509_KEY),
3229
0
                                 sizeof(MPROTO_OSSL_X509_KEY) - 1) : NULL;
3230
0
  if(share && share->store &&
3231
0
     !ossl_cached_x509_store_expired(data, share) &&
3232
0
     !ossl_cached_x509_store_different(cf, data, share)) {
3233
0
    store = share->store;
3234
0
    *pempty = (bool)share->store_is_empty;
3235
0
  }
3236
3237
0
  return store;
3238
0
}
3239
3240
static void ossl_set_cached_x509_store(struct Curl_cfilter *cf,
3241
                                       struct Curl_easy *data,
3242
                                       X509_STORE *store,
3243
                                       bool is_empty)
3244
0
{
3245
0
  struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
3246
0
  struct Curl_multi *multi = data->multi;
3247
0
  struct ossl_x509_share *share;
3248
3249
0
  DEBUGASSERT(multi);
3250
0
  if(!multi)
3251
0
    return;
3252
0
  share = Curl_hash_pick(&multi->proto_hash,
3253
0
                         CURL_UNCONST(MPROTO_OSSL_X509_KEY),
3254
0
                         sizeof(MPROTO_OSSL_X509_KEY) - 1);
3255
3256
0
  if(!share) {
3257
0
    share = curlx_calloc(1, sizeof(*share));
3258
0
    if(!share)
3259
0
      return;
3260
0
    if(!Curl_hash_add2(&multi->proto_hash,
3261
0
                       CURL_UNCONST(MPROTO_OSSL_X509_KEY),
3262
0
                       sizeof(MPROTO_OSSL_X509_KEY) - 1,
3263
0
                       share, oss_x509_share_free)) {
3264
0
      curlx_free(share);
3265
0
      return;
3266
0
    }
3267
0
  }
3268
3269
0
  if(X509_STORE_up_ref(store)) {
3270
0
    char *CAfile = NULL;
3271
0
    struct ssl_config_data *ssl_config =
3272
0
      Curl_ssl_cf_get_config(cf, CURL_UNCONST(data));
3273
3274
0
    if(conn_config->CAfile) {
3275
0
      CAfile = curlx_strdup(conn_config->CAfile);
3276
0
      if(!CAfile) {
3277
0
        X509_STORE_free(store);
3278
0
        return;
3279
0
      }
3280
0
    }
3281
3282
0
    if(share->store) {
3283
0
      X509_STORE_free(share->store);
3284
0
      curlx_free(share->CAfile);
3285
0
    }
3286
3287
0
    share->time = *Curl_pgrs_now(data);
3288
0
    share->store = store;
3289
0
    share->store_is_empty = is_empty;
3290
0
    share->CAfile = CAfile;
3291
0
    share->no_partialchain = ssl_config->no_partialchain;
3292
0
  }
3293
0
}
3294
3295
CURLcode Curl_ssl_setup_x509_store(struct Curl_cfilter *cf,
3296
                                   struct Curl_easy *data,
3297
                                   struct ossl_ctx *octx)
3298
0
{
3299
0
  struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
3300
0
  struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
3301
0
  CURLcode result = CURLE_OK;
3302
0
  X509_STORE *cached_store;
3303
0
  bool cache_criteria_met, is_empty;
3304
3305
  /* Consider the X509 store cacheable if it comes exclusively from a CAfile,
3306
     or no source is provided and we are falling back to OpenSSL's built-in
3307
     default. */
3308
0
  cache_criteria_met = (data->set.general_ssl.ca_cache_timeout != 0) &&
3309
0
    conn_config->verifypeer &&
3310
0
    !conn_config->CApath &&
3311
0
    !conn_config->ca_info_blob &&
3312
0
    !ssl_config->primary.CRLfile &&
3313
0
    !ssl_config->native_ca_store;
3314
3315
0
  ERR_set_mark();
3316
3317
0
  cached_store = ossl_get_cached_x509_store(cf, data, &is_empty);
3318
0
  if(cached_store && cache_criteria_met && X509_STORE_up_ref(cached_store)) {
3319
0
    SSL_CTX_set_cert_store(octx->ssl_ctx, cached_store);
3320
0
    octx->store_is_empty = is_empty;
3321
0
  }
3322
0
  else {
3323
0
    X509_STORE *store = SSL_CTX_get_cert_store(octx->ssl_ctx);
3324
3325
0
    result = ossl_populate_x509_store(cf, data, octx, store);
3326
0
    if(result == CURLE_OK && cache_criteria_met) {
3327
0
      ossl_set_cached_x509_store(cf, data, store, (bool)octx->store_is_empty);
3328
0
    }
3329
0
  }
3330
3331
0
  ERR_pop_to_mark();
3332
3333
0
  return result;
3334
0
}
3335
3336
static CURLcode
3337
ossl_init_session_and_alpns(struct ossl_ctx *octx,
3338
                            struct Curl_cfilter *cf,
3339
                            struct Curl_easy *data,
3340
                            struct ssl_peer *peer,
3341
                            const struct alpn_spec *alpns_requested,
3342
                            Curl_ossl_init_session_reuse_cb *sess_reuse_cb)
3343
0
{
3344
0
  struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
3345
0
  struct ssl_primary_config *conn_cfg = Curl_ssl_cf_get_primary_config(cf);
3346
0
  struct alpn_spec alpns;
3347
0
  CURLcode result;
3348
3349
0
  Curl_alpn_copy(&alpns, alpns_requested);
3350
3351
0
  octx->reused_session = FALSE;
3352
0
  if(Curl_ssl_scache_use(cf, data) && !conn_cfg->verifystatus) {
3353
0
    struct Curl_ssl_session *scs = NULL;
3354
3355
0
    result = Curl_ssl_scache_take(cf, data, peer->scache_key, &scs);
3356
0
    if(!result && scs && scs->sdata && scs->sdata_len) {
3357
0
      const unsigned char *der_sessionid = scs->sdata;
3358
0
      size_t der_sessionid_size = scs->sdata_len;
3359
0
      SSL_SESSION *ssl_session = NULL;
3360
3361
      /* If OpenSSL does not accept the session from the cache, this
3362
       * is not an error. We just continue without it. */
3363
0
      ssl_session = d2i_SSL_SESSION(NULL, &der_sessionid,
3364
0
                                    (long)der_sessionid_size);
3365
0
      if(ssl_session) {
3366
0
        if(!SSL_set_session(octx->ssl, ssl_session)) {
3367
0
          VERBOSE(char error_buffer[256]);
3368
0
          infof(data, "SSL: SSL_set_session not accepted, "
3369
0
                "continuing without: %s",
3370
0
                ossl_strerror(ERR_get_error(), error_buffer,
3371
0
                              sizeof(error_buffer)));
3372
0
        }
3373
0
        else {
3374
0
          infof(data, "SSL reusing session with ALPN '%s'",
3375
0
                scs->alpn ? scs->alpn : "-");
3376
0
          octx->reused_session = TRUE;
3377
0
#ifdef HAVE_OPENSSL_EARLYDATA
3378
0
          if(ssl_config->earlydata && scs->alpn &&
3379
0
             SSL_SESSION_get_max_early_data(ssl_session) &&
3380
0
             !cf->conn->connect_only &&
3381
0
             (SSL_version(octx->ssl) == TLS1_3_VERSION)) {
3382
0
            bool do_early_data = FALSE;
3383
0
            if(sess_reuse_cb) {
3384
0
              result = sess_reuse_cb(cf, data, &alpns, scs, &do_early_data);
3385
0
              if(result) {
3386
0
                SSL_SESSION_free(ssl_session);
3387
0
                return result;
3388
0
              }
3389
0
            }
3390
0
            if(do_early_data) {
3391
              /* We only try the ALPN protocol the session used before,
3392
               * otherwise we might send early data for the wrong protocol */
3393
0
              Curl_alpn_restrict_to(&alpns, scs->alpn);
3394
0
            }
3395
0
          }
3396
#else
3397
          (void)ssl_config;
3398
          (void)sess_reuse_cb;
3399
#endif
3400
0
        }
3401
0
        SSL_SESSION_free(ssl_session);
3402
0
      }
3403
0
      else {
3404
0
        infof(data, "SSL session not accepted by OpenSSL, continuing without");
3405
0
      }
3406
0
    }
3407
0
    Curl_ssl_scache_return(cf, data, peer->scache_key, scs);
3408
0
  }
3409
3410
0
  if(alpns.count) {
3411
0
    struct alpn_proto_buf proto;
3412
0
    memset(&proto, 0, sizeof(proto));
3413
0
    result = Curl_alpn_to_proto_buf(&proto, &alpns);
3414
0
    if(result) {
3415
0
      failf(data, "Error determining ALPN");
3416
0
      return CURLE_SSL_CONNECT_ERROR;
3417
0
    }
3418
0
    if(SSL_set_alpn_protos(octx->ssl, proto.data, (int)proto.len)) {
3419
0
      failf(data, "Error setting ALPN");
3420
0
      return CURLE_SSL_CONNECT_ERROR;
3421
0
    }
3422
0
  }
3423
3424
0
  return CURLE_OK;
3425
0
}
3426
3427
#ifdef HAVE_SSL_SET1_ECH_CONFIG_LIST
3428
static CURLcode ossl_init_ech(struct ossl_ctx *octx,
3429
                              struct Curl_cfilter *cf,
3430
                              struct Curl_easy *data,
3431
                              struct ssl_peer *peer)
3432
{
3433
  unsigned char *ech_config = NULL;
3434
  size_t ech_config_len = 0;
3435
  char *outername = data->set.str[STRING_ECH_PUBLIC];
3436
  int trying_ech_now = 0;
3437
  CURLcode result;
3438
3439
  if(!ECH_ENABLED(data))
3440
    return CURLE_OK;
3441
3442
  if(data->set.tls_ech & CURLECH_GREASE) {
3443
    infof(data, "ECH: will GREASE ClientHello");
3444
# ifdef HAVE_BORINGSSL_LIKE
3445
    SSL_set_enable_ech_grease(octx->ssl, 1);
3446
# else
3447
    SSL_set_options(octx->ssl, SSL_OP_ECH_GREASE);
3448
# endif
3449
  }
3450
  else if(data->set.tls_ech & CURLECH_CLA_CFG) {
3451
# ifdef HAVE_BORINGSSL_LIKE
3452
    /* have to do base64 decode here for BoringSSL */
3453
    const char *b64 = data->set.str[STRING_ECH_CONFIG];
3454
3455
    if(!b64) {
3456
      infof(data, "ECH: ECHConfig from command line empty");
3457
      return CURLE_SSL_CONNECT_ERROR;
3458
    }
3459
    ech_config_len = 2 * strlen(b64);
3460
    result = curlx_base64_decode(b64, &ech_config, &ech_config_len);
3461
    if(result || !ech_config) {
3462
      infof(data, "ECH: cannot base64 decode ECHConfig from command line");
3463
      if(data->set.tls_ech & CURLECH_HARD)
3464
        return result;
3465
    }
3466
    if(SSL_set1_ech_config_list(octx->ssl, ech_config, ech_config_len) != 1) {
3467
      infof(data, "ECH: SSL_ECH_set1_ech_config_list failed");
3468
      if(data->set.tls_ech & CURLECH_HARD) {
3469
        curlx_free(ech_config);
3470
        return CURLE_SSL_CONNECT_ERROR;
3471
      }
3472
    }
3473
    curlx_free(ech_config);
3474
    trying_ech_now = 1;
3475
# else
3476
    ech_config = (unsigned char *)data->set.str[STRING_ECH_CONFIG];
3477
    if(!ech_config) {
3478
      infof(data, "ECH: ECHConfig from command line empty");
3479
      return CURLE_SSL_CONNECT_ERROR;
3480
    }
3481
    ech_config_len = strlen(data->set.str[STRING_ECH_CONFIG]);
3482
    if(SSL_set1_ech_config_list(octx->ssl, ech_config, ech_config_len) != 1) {
3483
      infof(data, "ECH: SSL_ECH_set1_ech_config_list failed");
3484
      if(data->set.tls_ech & CURLECH_HARD)
3485
        return CURLE_SSL_CONNECT_ERROR;
3486
    }
3487
    else
3488
      trying_ech_now = 1;
3489
# endif
3490
    infof(data, "ECH: ECHConfig from command line");
3491
  }
3492
  else {
3493
    struct Curl_dns_entry *dns = NULL;
3494
3495
    if(peer->hostname)
3496
      dns = Curl_dnscache_get(data, peer->hostname, peer->port,
3497
                              cf->conn->ip_version);
3498
    if(!dns) {
3499
      infof(data, "ECH: requested but no DNS info available");
3500
      if(data->set.tls_ech & CURLECH_HARD)
3501
        return CURLE_SSL_CONNECT_ERROR;
3502
    }
3503
    else {
3504
      struct Curl_https_rrinfo *rinfo = NULL;
3505
3506
      rinfo = dns->hinfo;
3507
      if(rinfo && rinfo->echconfiglist) {
3508
        unsigned char *ecl = rinfo->echconfiglist;
3509
        size_t elen = rinfo->echconfiglist_len;
3510
3511
        infof(data, "ECH: ECHConfig from DoH HTTPS RR");
3512
        if(SSL_set1_ech_config_list(octx->ssl, ecl, elen) != 1) {
3513
          infof(data, "ECH: SSL_set1_ech_config_list failed");
3514
          if(data->set.tls_ech & CURLECH_HARD)
3515
            return CURLE_SSL_CONNECT_ERROR;
3516
        }
3517
        else {
3518
          trying_ech_now = 1;
3519
          infof(data, "ECH: imported ECHConfigList of length %zu", elen);
3520
        }
3521
      }
3522
      else {
3523
        infof(data, "ECH: requested but no ECHConfig available");
3524
        if(data->set.tls_ech & CURLECH_HARD)
3525
          return CURLE_SSL_CONNECT_ERROR;
3526
      }
3527
      Curl_resolv_unlink(data, &dns);
3528
    }
3529
  }
3530
# ifdef HAVE_BORINGSSL_LIKE
3531
  if(trying_ech_now && outername) {
3532
    infof(data, "ECH: setting public_name not supported with BoringSSL");
3533
    return CURLE_SSL_CONNECT_ERROR;
3534
  }
3535
# else
3536
  if(trying_ech_now && outername) {
3537
    infof(data, "ECH: inner: '%s', outer: '%s'",
3538
          peer->hostname ? peer->hostname : "NULL", outername);
3539
    result = SSL_ech_set1_server_names(octx->ssl,
3540
                                       peer->hostname, outername,
3541
                                       0 /* do send outer */);
3542
    if(result != 1) {
3543
      infof(data, "ECH: rv failed to set server name(s) %d [ERROR]", result);
3544
      return CURLE_SSL_CONNECT_ERROR;
3545
    }
3546
  }
3547
# endif /* HAVE_BORINGSSL_LIKE */
3548
  if(trying_ech_now &&
3549
     SSL_set_min_proto_version(octx->ssl, TLS1_3_VERSION) != 1) {
3550
    infof(data, "ECH: cannot force TLSv1.3 [ERROR]");
3551
    return CURLE_SSL_CONNECT_ERROR;
3552
  }
3553
3554
  return CURLE_OK;
3555
}
3556
#endif /* HAVE_SSL_SET1_ECH_CONFIG_LIST */
3557
3558
static CURLcode ossl_init_ssl(struct ossl_ctx *octx,
3559
                              struct Curl_cfilter *cf,
3560
                              struct Curl_easy *data,
3561
                              struct ssl_peer *peer,
3562
                              const struct alpn_spec *alpns_requested,
3563
                              void *ssl_user_data,
3564
                              Curl_ossl_init_session_reuse_cb *sess_reuse_cb)
3565
0
{
3566
  /* Let's make an SSL structure */
3567
0
  if(octx->ssl)
3568
0
    SSL_free(octx->ssl);
3569
0
  octx->ssl = SSL_new(octx->ssl_ctx);
3570
0
  if(!octx->ssl) {
3571
0
    failf(data, "SSL: could not create a context (handle)");
3572
0
    return CURLE_OUT_OF_MEMORY;
3573
0
  }
3574
3575
0
  SSL_set_app_data(octx->ssl, ssl_user_data);
3576
3577
0
#ifndef OPENSSL_NO_OCSP
3578
0
  if(Curl_ssl_cf_get_primary_config(cf)->verifystatus)
3579
0
    SSL_set_tlsext_status_type(octx->ssl, TLSEXT_STATUSTYPE_ocsp);
3580
0
#endif
3581
3582
0
  SSL_set_connect_state(octx->ssl);
3583
3584
0
  if(peer->sni) {
3585
0
    if(!SSL_set_tlsext_host_name(octx->ssl, peer->sni)) {
3586
0
      failf(data, "Failed set SNI");
3587
0
      return CURLE_SSL_CONNECT_ERROR;
3588
0
    }
3589
0
  }
3590
3591
#ifdef HAVE_SSL_SET1_ECH_CONFIG_LIST
3592
  {
3593
    CURLcode result = ossl_init_ech(octx, cf, data, peer);
3594
    if(result)
3595
      return result;
3596
  }
3597
#endif /* HAVE_SSL_SET1_ECH_CONFIG_LIST */
3598
3599
0
  return ossl_init_session_and_alpns(octx, cf, data, peer,
3600
0
                                     alpns_requested, sess_reuse_cb);
3601
0
}
3602
3603
static CURLcode ossl_init_method(struct Curl_cfilter *cf,
3604
                                 struct Curl_easy *data,
3605
                                 struct ssl_peer *peer,
3606
                                 const SSL_METHOD **pmethod,
3607
                                 unsigned int *pssl_version_min)
3608
0
{
3609
0
  struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
3610
3611
0
  *pmethod = NULL;
3612
0
  *pssl_version_min = conn_config->version;
3613
0
  switch(peer->transport) {
3614
0
  case TRNSPRT_TCP:
3615
    /* check to see if we have been told to use an explicit SSL/TLS version */
3616
0
    switch(*pssl_version_min) {
3617
0
    case CURL_SSLVERSION_DEFAULT:
3618
0
    case CURL_SSLVERSION_TLSv1:
3619
0
    case CURL_SSLVERSION_TLSv1_0:
3620
0
    case CURL_SSLVERSION_TLSv1_1:
3621
0
    case CURL_SSLVERSION_TLSv1_2:
3622
0
    case CURL_SSLVERSION_TLSv1_3:
3623
      /* it will be handled later with the context options */
3624
0
      *pmethod = TLS_client_method();
3625
0
      break;
3626
0
    case CURL_SSLVERSION_SSLv2:
3627
0
      failf(data, "No SSLv2 support");
3628
0
      return CURLE_NOT_BUILT_IN;
3629
0
    case CURL_SSLVERSION_SSLv3:
3630
0
      failf(data, "No SSLv3 support");
3631
0
      return CURLE_NOT_BUILT_IN;
3632
0
    default:
3633
0
      failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
3634
0
      return CURLE_SSL_CONNECT_ERROR;
3635
0
    }
3636
0
    break;
3637
0
  case TRNSPRT_QUIC:
3638
0
    *pssl_version_min = CURL_SSLVERSION_TLSv1_3;
3639
0
    if(conn_config->version_max &&
3640
0
       (conn_config->version_max != CURL_SSLVERSION_MAX_DEFAULT) &&
3641
0
       (conn_config->version_max != CURL_SSLVERSION_MAX_TLSv1_3)) {
3642
0
      failf(data, "QUIC needs at least TLS version 1.3");
3643
0
      return CURLE_SSL_CONNECT_ERROR;
3644
0
    }
3645
3646
0
    *pmethod = TLS_method();
3647
0
    break;
3648
0
  default:
3649
0
    failf(data, "unsupported transport %d in SSL init", peer->transport);
3650
0
    return CURLE_SSL_CONNECT_ERROR;
3651
0
  }
3652
3653
0
  return *pmethod ? CURLE_OK : CURLE_SSL_CONNECT_ERROR;
3654
0
}
3655
3656
CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx,
3657
                            struct Curl_cfilter *cf,
3658
                            struct Curl_easy *data,
3659
                            struct ssl_peer *peer,
3660
                            const struct alpn_spec *alpns_requested,
3661
                            Curl_ossl_ctx_setup_cb *cb_setup,
3662
                            void *cb_user_data,
3663
                            Curl_ossl_new_session_cb *cb_new_session,
3664
                            void *ssl_user_data,
3665
                            Curl_ossl_init_session_reuse_cb *sess_reuse_cb)
3666
0
{
3667
0
  CURLcode result = CURLE_OK;
3668
0
  const char *ciphers;
3669
0
  const SSL_METHOD *req_method = NULL;
3670
0
  ctx_option_t ctx_options = 0;
3671
0
  struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
3672
0
  struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
3673
0
  char * const ssl_cert = ssl_config->primary.clientcert;
3674
0
  const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob;
3675
0
  const char * const ssl_cert_type = ssl_config->cert_type;
3676
0
  unsigned int ssl_version_min;
3677
0
  char error_buffer[256];
3678
3679
  /* Make funny stuff to get random input */
3680
0
  result = ossl_seed(data);
3681
0
  if(result)
3682
0
    return result;
3683
3684
0
  ssl_config->certverifyresult = !X509_V_OK;
3685
3686
0
  result = ossl_init_method(cf, data, peer, &req_method, &ssl_version_min);
3687
0
  if(result)
3688
0
    return result;
3689
0
  DEBUGASSERT(req_method);
3690
3691
0
  DEBUGASSERT(!octx->ssl_ctx);
3692
0
  octx->ssl_ctx =
3693
0
#ifdef OPENSSL_HAS_PROVIDERS
3694
0
    data->state.libctx ?
3695
0
    SSL_CTX_new_ex(data->state.libctx, data->state.propq, req_method):
3696
0
#endif
3697
0
    SSL_CTX_new(req_method);
3698
3699
0
  if(!octx->ssl_ctx) {
3700
0
    failf(data, "SSL: could not create a context: %s",
3701
0
          ossl_strerror(ERR_peek_error(), error_buffer, sizeof(error_buffer)));
3702
0
    return CURLE_OUT_OF_MEMORY;
3703
0
  }
3704
3705
0
  if(cb_setup) {
3706
0
    result = cb_setup(cf, data, cb_user_data);
3707
0
    if(result)
3708
0
      return result;
3709
0
  }
3710
3711
0
  if(data->set.fdebug && data->set.verbose) {
3712
    /* the SSL trace callback is only used for verbose logging */
3713
0
    SSL_CTX_set_msg_callback(octx->ssl_ctx, ossl_trace);
3714
0
    SSL_CTX_set_msg_callback_arg(octx->ssl_ctx, cf);
3715
0
  }
3716
3717
  /* OpenSSL contains code to work around lots of bugs and flaws in various
3718
     SSL-implementations. SSL_CTX_set_options() is used to enabled those
3719
     work-arounds. The man page for this option states that SSL_OP_ALL enables
3720
     all the work-arounds and that "It is usually safe to use SSL_OP_ALL to
3721
     enable the bug workaround options if compatibility with somewhat broken
3722
     implementations is desired."
3723
3724
     The "-no_ticket" option was introduced in OpenSSL 0.9.8j. it is a flag to
3725
     disable "rfc4507bis session ticket support". rfc4507bis was later turned
3726
     into the proper RFC5077: https://datatracker.ietf.org/doc/html/rfc5077
3727
3728
     The enabled extension concerns the session management. I wonder how often
3729
     libcurl stops a connection and then resumes a TLS session. Also, sending
3730
     the session data is some overhead. I suggest that you just use your
3731
     proposed patch (which explicitly disables TICKET).
3732
3733
     If someone writes an application with libcurl and OpenSSL who wants to
3734
     enable the feature, one can do this in the SSL callback.
3735
3736
     SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG option enabling allowed proper
3737
     interoperability with web server Netscape Enterprise Server 2.0.1 which
3738
     was released back in 1996.
3739
3740
     Due to CVE-2010-4180, option SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG has
3741
     become ineffective as of OpenSSL 0.9.8q and 1.0.0c. In order to mitigate
3742
     CVE-2010-4180 when using previous OpenSSL versions we no longer enable
3743
     this option regardless of OpenSSL version and SSL_OP_ALL definition.
3744
3745
     OpenSSL added a work-around for an SSL 3.0/TLS 1.0 CBC vulnerability:
3746
     https://web.archive.org/web/20240114184648/openssl.org/~bodo/tls-cbc.txt.
3747
     In 0.9.6e they added a bit to SSL_OP_ALL that _disables_ that work-around
3748
     despite the fact that SSL_OP_ALL is documented to do "rather harmless"
3749
     workarounds. In order to keep the secure work-around, the
3750
     SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS bit must not be set.
3751
  */
3752
3753
0
  ctx_options = SSL_OP_ALL | SSL_OP_NO_TICKET | SSL_OP_NO_COMPRESSION;
3754
3755
  /* mitigate CVE-2010-4180 */
3756
0
  ctx_options &= ~(ctx_option_t)SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG;
3757
3758
  /* unless the user explicitly asks to allow the protocol vulnerability we
3759
     use the work-around */
3760
0
  if(!ssl_config->enable_beast)
3761
0
    ctx_options &= ~(ctx_option_t)SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
3762
3763
0
  switch(ssl_version_min) {
3764
0
  case CURL_SSLVERSION_SSLv2:
3765
0
  case CURL_SSLVERSION_SSLv3:
3766
0
    return CURLE_NOT_BUILT_IN;
3767
3768
    /* "--tlsv<x.y>" options mean TLS >= version <x.y> */
3769
0
  case CURL_SSLVERSION_DEFAULT:
3770
0
  case CURL_SSLVERSION_TLSv1:   /* TLS >= version 1.0 */
3771
0
  case CURL_SSLVERSION_TLSv1_0: /* TLS >= version 1.0 */
3772
0
  case CURL_SSLVERSION_TLSv1_1: /* TLS >= version 1.1 */
3773
0
  case CURL_SSLVERSION_TLSv1_2: /* TLS >= version 1.2 */
3774
0
  case CURL_SSLVERSION_TLSv1_3: /* TLS >= version 1.3 */
3775
    /* asking for any TLS version as the minimum, means no SSL versions
3776
       allowed */
3777
0
    ctx_options |= SSL_OP_NO_SSLv2;
3778
0
    ctx_options |= SSL_OP_NO_SSLv3;
3779
3780
0
    result = ossl_set_ssl_version_min_max(cf, octx->ssl_ctx, ssl_version_min);
3781
0
    if(result)
3782
0
      return result;
3783
0
    break;
3784
3785
0
  default:
3786
0
    failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
3787
0
    return CURLE_SSL_CONNECT_ERROR;
3788
0
  }
3789
3790
0
  SSL_CTX_set_options(octx->ssl_ctx, ctx_options);
3791
0
  SSL_CTX_set_read_ahead(octx->ssl_ctx, 1);
3792
3793
  /* Max TLS1.2 record size 0x4000 + 0x800.
3794
     OpenSSL supports processing "jumbo TLS record" (8 TLS records) in one go
3795
     for some algorithms, so match that here.
3796
     Experimentation shows that a slightly larger buffer is needed
3797
     to avoid short reads.
3798
3799
     However using a large buffer (8 packets) actually decreases performance.
3800
     4 packets is better.
3801
   */
3802
0
#ifdef HAVE_SSL_CTX_SET_DEFAULT_READ_BUFFER_LEN
3803
0
  SSL_CTX_set_default_read_buffer_len(octx->ssl_ctx, 0x401e * 4);
3804
0
#endif
3805
3806
  /* We do retry writes sometimes from another buffer address */
3807
0
  SSL_CTX_set_mode(octx->ssl_ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
3808
3809
0
  ciphers = conn_config->cipher_list;
3810
0
  if(!ciphers && (peer->transport != TRNSPRT_QUIC))
3811
0
    ciphers = NULL;
3812
0
  if(ciphers && (ssl_version_min < CURL_SSLVERSION_TLSv1_3)) {
3813
0
    if(!SSL_CTX_set_cipher_list(octx->ssl_ctx, ciphers)) {
3814
0
      failf(data, "failed setting cipher list: %s", ciphers);
3815
0
      return CURLE_SSL_CIPHER;
3816
0
    }
3817
0
    infof(data, "Cipher selection: %s", ciphers);
3818
0
  }
3819
3820
0
#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
3821
0
  {
3822
0
    const char *ciphers13 = conn_config->cipher_list13;
3823
0
    if(ciphers13 &&
3824
0
       (!conn_config->version_max ||
3825
0
        (conn_config->version_max == CURL_SSLVERSION_MAX_DEFAULT) ||
3826
0
        (conn_config->version_max >= CURL_SSLVERSION_MAX_TLSv1_3))) {
3827
0
      if(!SSL_CTX_set_ciphersuites(octx->ssl_ctx, ciphers13)) {
3828
0
        failf(data, "failed setting TLS 1.3 cipher suite: %s", ciphers13);
3829
0
        return CURLE_SSL_CIPHER;
3830
0
      }
3831
0
      infof(data, "TLS 1.3 cipher selection: %s", ciphers13);
3832
0
    }
3833
0
  }
3834
0
#endif
3835
3836
0
  if(ssl_cert || ssl_cert_blob || ssl_cert_type) {
3837
0
    result = client_cert(data, octx->ssl_ctx,
3838
0
                         ssl_cert, ssl_cert_blob, ssl_cert_type,
3839
0
                         ssl_config->key, ssl_config->key_blob,
3840
0
                         ssl_config->key_type, ssl_config->key_passwd);
3841
0
    if(result)
3842
      /* failf() is already done in client_cert() */
3843
0
      return result;
3844
0
  }
3845
3846
0
#ifdef HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH
3847
  /* OpenSSL 1.1.1 requires clients to opt-in for PHA */
3848
0
  SSL_CTX_set_post_handshake_auth(octx->ssl_ctx, 1);
3849
0
#endif
3850
3851
0
  {
3852
0
    const char *curves = conn_config->curves;
3853
0
    if(curves) {
3854
#ifdef HAVE_BORINGSSL_LIKE
3855
#define OSSL_CURVE_CAST(x) (x)
3856
#else
3857
0
#define OSSL_CURVE_CAST(x) (char *)CURL_UNCONST(x)
3858
0
#endif
3859
0
      if(!SSL_CTX_set1_curves_list(octx->ssl_ctx, OSSL_CURVE_CAST(curves))) {
3860
0
        failf(data, "failed setting curves list: '%s'", curves);
3861
0
        return CURLE_SSL_CIPHER;
3862
0
      }
3863
0
    }
3864
0
  }
3865
3866
0
#ifdef HAVE_SSL_CTX_SET1_SIGALGS
3867
0
#define OSSL_SIGALG_CAST(x) OSSL_CURVE_CAST(x)
3868
0
  {
3869
0
    const char *signature_algorithms = conn_config->signature_algorithms;
3870
0
    if(signature_algorithms) {
3871
0
      if(!SSL_CTX_set1_sigalgs_list(octx->ssl_ctx,
3872
0
                                    OSSL_SIGALG_CAST(signature_algorithms))) {
3873
0
        failf(data, "failed setting signature algorithms: '%s'",
3874
0
              signature_algorithms);
3875
0
        return CURLE_SSL_CIPHER;
3876
0
      }
3877
0
    }
3878
0
  }
3879
0
#endif
3880
3881
0
#if defined(HAVE_OPENSSL_SRP) && defined(USE_TLS_SRP)
3882
0
  if(ssl_config->primary.username && Curl_auth_allowed_to_host(data)) {
3883
0
    char * const ssl_username = ssl_config->primary.username;
3884
0
    char * const ssl_password = ssl_config->primary.password;
3885
0
    infof(data, "Using TLS-SRP username: %s", ssl_username);
3886
3887
0
    if(!SSL_CTX_set_srp_username(octx->ssl_ctx, ssl_username)) {
3888
0
      failf(data, "Unable to set SRP username");
3889
0
      return CURLE_BAD_FUNCTION_ARGUMENT;
3890
0
    }
3891
0
    if(!SSL_CTX_set_srp_password(octx->ssl_ctx, ssl_password)) {
3892
0
      failf(data, "failed setting SRP password");
3893
0
      return CURLE_BAD_FUNCTION_ARGUMENT;
3894
0
    }
3895
0
    if(!conn_config->cipher_list) {
3896
0
      infof(data, "Setting cipher list SRP");
3897
3898
0
      if(!SSL_CTX_set_cipher_list(octx->ssl_ctx, "SRP")) {
3899
0
        failf(data, "failed setting SRP cipher list");
3900
0
        return CURLE_SSL_CIPHER;
3901
0
      }
3902
0
    }
3903
0
  }
3904
0
#endif /* HAVE_OPENSSL_SRP && USE_TLS_SRP */
3905
3906
  /* OpenSSL always tries to verify the peer. By setting the failure mode
3907
   * to NONE, we allow the connect to complete, regardless of the outcome.
3908
   * We then explicitly check the result and may try alternatives like
3909
   * Apple's SecTrust for verification. */
3910
0
  SSL_CTX_set_verify(octx->ssl_ctx, SSL_VERIFY_NONE, NULL);
3911
3912
  /* Enable logging of secrets to the file specified in env SSLKEYLOGFILE. */
3913
0
#ifdef HAVE_KEYLOG_CALLBACK
3914
0
  if(Curl_tls_keylog_enabled()) {
3915
0
    SSL_CTX_set_keylog_callback(octx->ssl_ctx, ossl_keylog_callback);
3916
0
  }
3917
0
#endif
3918
3919
0
  if(cb_new_session) {
3920
    /* Enable the session cache because it is a prerequisite for the
3921
     * "new session" callback. Use the "external storage" mode to prevent
3922
     * OpenSSL from creating an internal session cache.
3923
     */
3924
0
    SSL_CTX_set_session_cache_mode(octx->ssl_ctx,
3925
0
                                   SSL_SESS_CACHE_CLIENT |
3926
0
                                   SSL_SESS_CACHE_NO_INTERNAL);
3927
0
    SSL_CTX_sess_set_new_cb(octx->ssl_ctx, cb_new_session);
3928
0
  }
3929
3930
  /* give application a chance to interfere with SSL set up. */
3931
0
  if(data->set.ssl.fsslctx) {
3932
    /* When a user callback is installed to modify the SSL_CTX,
3933
     * we need to do the full initialization before calling it.
3934
     * See: #11800 */
3935
0
    if(!octx->x509_store_setup) {
3936
0
      result = Curl_ssl_setup_x509_store(cf, data, octx);
3937
0
      if(result)
3938
0
        return result;
3939
0
      octx->x509_store_setup = TRUE;
3940
0
    }
3941
0
    Curl_set_in_callback(data, TRUE);
3942
0
    result = (*data->set.ssl.fsslctx)(data, octx->ssl_ctx,
3943
0
                                      data->set.ssl.fsslctxp);
3944
0
    Curl_set_in_callback(data, FALSE);
3945
0
    if(result) {
3946
0
      failf(data, "error signaled by ssl ctx callback");
3947
0
      return result;
3948
0
    }
3949
0
  }
3950
3951
0
  return ossl_init_ssl(octx, cf, data, peer, alpns_requested,
3952
0
                       ssl_user_data, sess_reuse_cb);
3953
0
}
3954
3955
static CURLcode ossl_on_session_reuse(struct Curl_cfilter *cf,
3956
                                      struct Curl_easy *data,
3957
                                      struct alpn_spec *alpns,
3958
                                      struct Curl_ssl_session *scs,
3959
                                      bool *do_early_data)
3960
0
{
3961
0
  struct ssl_connect_data *connssl = cf->ctx;
3962
0
  CURLcode result = CURLE_OK;
3963
3964
0
  *do_early_data = FALSE;
3965
0
  connssl->earlydata_max = scs->earlydata_max;
3966
0
  if(!connssl->earlydata_max) {
3967
0
    CURL_TRC_CF(data, cf, "SSL session does not allow earlydata");
3968
0
  }
3969
0
  else if(!Curl_alpn_contains_proto(alpns, scs->alpn)) {
3970
0
    CURL_TRC_CF(data, cf, "SSL session has different ALPN, no early data");
3971
0
  }
3972
0
  else {
3973
0
    infof(data, "SSL session allows %zu bytes of early data, "
3974
0
          "reusing ALPN '%s'", connssl->earlydata_max, scs->alpn);
3975
0
    connssl->earlydata_state = ssl_earlydata_await;
3976
0
    connssl->state = ssl_connection_deferred;
3977
0
    result = Curl_alpn_set_negotiated(cf, data, connssl,
3978
0
                                      (const unsigned char *)scs->alpn,
3979
0
                                      scs->alpn ? strlen(scs->alpn) : 0);
3980
0
    *do_early_data = !result;
3981
0
  }
3982
0
  return result;
3983
0
}
3984
3985
void Curl_ossl_report_handshake(struct Curl_easy *data, struct ossl_ctx *octx)
3986
0
{
3987
0
#ifdef CURLVERBOSE
3988
0
  if(Curl_trc_is_verbose(data)) {
3989
0
    int psigtype_nid = NID_undef;
3990
0
    const char *negotiated_group_name = NULL;
3991
3992
0
#ifdef HAVE_OPENSSL3
3993
0
    SSL_get_peer_signature_type_nid(octx->ssl, &psigtype_nid);
3994
0
#if OPENSSL_VERSION_NUMBER >= 0x30200000L
3995
0
    negotiated_group_name = SSL_get0_group_name(octx->ssl);
3996
#else
3997
    negotiated_group_name =
3998
      OBJ_nid2sn(SSL_get_negotiated_group(octx->ssl) & 0x0000FFFF);
3999
#endif
4000
0
#endif
4001
4002
    /* Informational message */
4003
0
    infof(data, "SSL connection using %s / %s / %s / %s",
4004
0
          SSL_get_version(octx->ssl),
4005
0
          SSL_get_cipher(octx->ssl),
4006
0
          negotiated_group_name ? negotiated_group_name : "[blank]",
4007
0
          OBJ_nid2sn(psigtype_nid));
4008
0
  }
4009
#else
4010
  (void)data;
4011
  (void)octx;
4012
#endif /* CURLVERBOSE */
4013
0
}
4014
4015
static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
4016
                                   struct Curl_easy *data)
4017
0
{
4018
0
  struct ssl_connect_data *connssl = cf->ctx;
4019
0
  struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
4020
0
  BIO *bio;
4021
0
  CURLcode result;
4022
4023
0
  DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
4024
0
  DEBUGASSERT(octx);
4025
4026
0
  result = Curl_ossl_ctx_init(octx, cf, data, &connssl->peer,
4027
0
                              connssl->alpn, NULL, NULL,
4028
0
                              ossl_new_session_cb, cf,
4029
0
                              ossl_on_session_reuse);
4030
0
  if(result)
4031
0
    return result;
4032
4033
0
  octx->bio_method = ossl_bio_cf_method_create();
4034
0
  if(!octx->bio_method)
4035
0
    return CURLE_OUT_OF_MEMORY;
4036
0
  bio = BIO_new(octx->bio_method);
4037
0
  if(!bio)
4038
0
    return CURLE_OUT_OF_MEMORY;
4039
4040
0
  BIO_set_data(bio, cf);
4041
0
#ifdef HAVE_SSL_SET0_WBIO
4042
  /* with OpenSSL v1.1.1 we get an alternative to SSL_set_bio() that works
4043
   * without backward compat quirks. Every call takes one reference, so we
4044
   * up it and pass. SSL* then owns it and will free.
4045
   * We check on the function in configure, since LibreSSL and friends
4046
   * each have their own versions to add support for this. */
4047
0
  BIO_up_ref(bio);
4048
0
  SSL_set0_rbio(octx->ssl, bio);
4049
0
  SSL_set0_wbio(octx->ssl, bio);
4050
#else
4051
  SSL_set_bio(octx->ssl, bio, bio);
4052
#endif
4053
4054
0
  if(connssl->alpn && (connssl->state != ssl_connection_deferred)) {
4055
0
    struct alpn_proto_buf proto;
4056
0
    memset(&proto, 0, sizeof(proto));
4057
0
    Curl_alpn_to_proto_str(&proto, connssl->alpn);
4058
0
    infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
4059
0
  }
4060
4061
0
  connssl->connecting_state = ssl_connect_2;
4062
0
  return CURLE_OK;
4063
0
}
4064
4065
#ifdef HAVE_SSL_SET1_ECH_CONFIG_LIST
4066
/* If we have retry configs, then trace those out */
4067
static void ossl_trace_ech_retry_configs(struct Curl_easy *data, SSL *ssl,
4068
                                         int reason)
4069
{
4070
  CURLcode result = CURLE_OK;
4071
  size_t rcl = 0;
4072
  int rv = 1;
4073
# ifndef HAVE_BORINGSSL_LIKE
4074
  char *inner = NULL;
4075
  uint8_t *rcs = NULL;
4076
  char *outer = NULL;
4077
# else
4078
  const char *inner = NULL;
4079
  const uint8_t *rcs = NULL;
4080
  const char *outer = NULL;
4081
  size_t out_name_len = 0;
4082
  int servername_type = 0;
4083
# endif
4084
4085
  /* nothing to trace if not doing ECH */
4086
  if(!ECH_ENABLED(data))
4087
    return;
4088
# ifndef HAVE_BORINGSSL_LIKE
4089
  rv = SSL_ech_get1_retry_config(ssl, &rcs, &rcl);
4090
# else
4091
  SSL_get0_ech_retry_configs(ssl, &rcs, &rcl);
4092
  rv = (int)rcl;
4093
# endif
4094
4095
  if(rv && rcs) {
4096
    char *b64str = NULL;
4097
    size_t blen = 0;
4098
4099
    result = curlx_base64_encode(rcs, rcl, &b64str, &blen);
4100
    if(!result && b64str) {
4101
      infof(data, "ECH: retry_configs %s", b64str);
4102
      curlx_free(b64str);
4103
#ifndef HAVE_BORINGSSL_LIKE
4104
      rv = SSL_ech_get1_status(ssl, &inner, &outer);
4105
      infof(data, "ECH: retry_configs for %s from %s, %d %d",
4106
            inner ? inner : "NULL", outer ? outer : "NULL", reason, rv);
4107
#else
4108
      rv = SSL_ech_accepted(ssl);
4109
      servername_type = SSL_get_servername_type(ssl);
4110
      inner = SSL_get_servername(ssl, servername_type);
4111
      SSL_get0_ech_name_override(ssl, &outer, &out_name_len);
4112
      infof(data, "ECH: retry_configs for %s from %s, %d %d",
4113
            inner ? inner : "NULL", outer ? outer : "NULL", reason, rv);
4114
#endif
4115
    }
4116
  }
4117
  else
4118
    infof(data, "ECH: no retry_configs (rv = %d)", rv);
4119
# ifndef HAVE_BORINGSSL_LIKE
4120
  OPENSSL_free((void *)rcs);
4121
# endif
4122
  return;
4123
}
4124
4125
#endif
4126
4127
static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
4128
                                   struct Curl_easy *data)
4129
0
{
4130
0
  int err;
4131
0
  struct ssl_connect_data *connssl = cf->ctx;
4132
0
  struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
4133
0
  struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
4134
0
  DEBUGASSERT(ssl_connect_2 == connssl->connecting_state);
4135
0
  DEBUGASSERT(octx);
4136
4137
0
  connssl->io_need = CURL_SSL_IO_NEED_NONE;
4138
0
  ERR_clear_error();
4139
4140
0
  err = SSL_connect(octx->ssl);
4141
4142
0
  if(!octx->x509_store_setup) {
4143
    /* After having send off the ClientHello, we prepare the x509
4144
     * store to verify the coming certificate from the server */
4145
0
    CURLcode result = Curl_ssl_setup_x509_store(cf, data, octx);
4146
0
    if(result)
4147
0
      return result;
4148
0
    octx->x509_store_setup = TRUE;
4149
0
  }
4150
4151
#ifndef HAVE_KEYLOG_CALLBACK
4152
  /* If key logging is enabled, wait for the handshake to complete and then
4153
   * proceed with logging secrets (for TLS 1.2 or older).
4154
   */
4155
  if(Curl_tls_keylog_enabled() && !octx->keylog_done)
4156
    ossl_log_tls12_secret(octx->ssl, &octx->keylog_done);
4157
#endif
4158
4159
  /* 1  is fine
4160
     0  is "not successful but was shut down controlled"
4161
     <0 is "handshake was not successful, because a fatal error occurred" */
4162
0
  if(err != 1) {
4163
0
    int detail = SSL_get_error(octx->ssl, err);
4164
0
    CURL_TRC_CF(data, cf, "SSL_connect() -> err=%d, detail=%d", err, detail);
4165
4166
0
    if(SSL_ERROR_WANT_READ == detail) {
4167
0
      CURL_TRC_CF(data, cf, "SSL_connect() -> want recv");
4168
0
      connssl->io_need = CURL_SSL_IO_NEED_RECV;
4169
0
      return CURLE_AGAIN;
4170
0
    }
4171
0
    if(SSL_ERROR_WANT_WRITE == detail) {
4172
0
      CURL_TRC_CF(data, cf, "SSL_connect() -> want send");
4173
0
      connssl->io_need = CURL_SSL_IO_NEED_SEND;
4174
0
      return CURLE_AGAIN;
4175
0
    }
4176
0
#ifdef SSL_ERROR_WANT_ASYNC
4177
0
    if(SSL_ERROR_WANT_ASYNC == detail) {
4178
0
      CURL_TRC_CF(data, cf, "SSL_connect() -> want async");
4179
0
      connssl->io_need = CURL_SSL_IO_NEED_RECV;
4180
0
      return CURLE_AGAIN;
4181
0
    }
4182
0
#endif
4183
0
#ifdef SSL_ERROR_WANT_RETRY_VERIFY
4184
0
    if(SSL_ERROR_WANT_RETRY_VERIFY == detail) {
4185
0
      CURL_TRC_CF(data, cf, "SSL_connect() -> want retry_verify");
4186
0
      Curl_xfer_pause_recv(data, TRUE);
4187
0
      return CURLE_AGAIN;
4188
0
    }
4189
0
#endif
4190
0
    else {
4191
      /* untreated error */
4192
0
      sslerr_t errdetail;
4193
0
      char error_buffer[256] = "";
4194
0
      CURLcode result;
4195
0
      long lerr;
4196
0
      int lib;
4197
0
      int reason;
4198
4199
      /* the connection failed, we are not waiting for anything else. */
4200
0
      connssl->connecting_state = ssl_connect_2;
4201
4202
      /* Get the earliest error code from the thread's error queue and remove
4203
         the entry. */
4204
0
      errdetail = ERR_get_error();
4205
4206
      /* Extract which lib and reason */
4207
0
      lib = ERR_GET_LIB(errdetail);
4208
0
      reason = ERR_GET_REASON(errdetail);
4209
4210
0
      if((lib == ERR_LIB_SSL) &&
4211
0
         ((reason == SSL_R_CERTIFICATE_VERIFY_FAILED) ||
4212
0
          (reason == SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED))) {
4213
0
        result = CURLE_PEER_FAILED_VERIFICATION;
4214
4215
0
        lerr = SSL_get_verify_result(octx->ssl);
4216
0
        if(lerr != X509_V_OK) {
4217
0
          ssl_config->certverifyresult = lerr;
4218
0
          failf(data, "SSL certificate problem: %s",
4219
0
                X509_verify_cert_error_string(lerr));
4220
0
        }
4221
0
        else
4222
0
          failf(data, "%s", "SSL certificate verification failed");
4223
0
      }
4224
0
#ifdef SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED
4225
      /* SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED is only available on
4226
         OpenSSL version above v1.1.1, not LibreSSL, BoringSSL, or AWS-LC */
4227
0
      else if((lib == ERR_LIB_SSL) &&
4228
0
              (reason == SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED)) {
4229
        /* If client certificate is required, communicate the
4230
           error to client */
4231
0
        result = CURLE_SSL_CLIENTCERT;
4232
0
        failf(data, "TLS cert problem: %s",
4233
0
              ossl_strerror(errdetail, error_buffer, sizeof(error_buffer)));
4234
0
      }
4235
0
#endif
4236
#ifdef HAVE_SSL_SET1_ECH_CONFIG_LIST
4237
      else if((lib == ERR_LIB_SSL) &&
4238
# ifndef HAVE_BORINGSSL_LIKE
4239
              (reason == SSL_R_ECH_REQUIRED)) {
4240
# else
4241
              (reason == SSL_R_ECH_REJECTED)) {
4242
# endif
4243
4244
        /* trace retry_configs if we got some */
4245
        ossl_trace_ech_retry_configs(data, octx->ssl, reason);
4246
4247
        result = CURLE_ECH_REQUIRED;
4248
        failf(data, "ECH required: %s",
4249
              ossl_strerror(errdetail, error_buffer, sizeof(error_buffer)));
4250
      }
4251
#endif
4252
0
      else {
4253
0
        result = CURLE_SSL_CONNECT_ERROR;
4254
0
        failf(data, "TLS connect error: %s",
4255
0
              ossl_strerror(errdetail, error_buffer, sizeof(error_buffer)));
4256
0
      }
4257
4258
      /* detail is already set to the SSL error above */
4259
4260
      /* If we e.g. use SSLv2 request-method and the server does not like us
4261
       * (RST connection, etc.), OpenSSL gives no explanation whatsoever and
4262
       * the SO_ERROR is also lost.
4263
       */
4264
0
      if(CURLE_SSL_CONNECT_ERROR == result && errdetail == 0) {
4265
0
        char extramsg[80] = "";
4266
0
        int sockerr = SOCKERRNO;
4267
4268
0
        if(sockerr && detail == SSL_ERROR_SYSCALL)
4269
0
          curlx_strerror(sockerr, extramsg, sizeof(extramsg));
4270
0
        failf(data, OSSL_PACKAGE " SSL_connect: %s in connection to %s:%d ",
4271
0
              extramsg[0] ? extramsg : SSL_ERROR_to_str(detail),
4272
0
              connssl->peer.hostname, connssl->peer.port);
4273
0
      }
4274
4275
0
      return result;
4276
0
    }
4277
0
  }
4278
0
  else {
4279
    /* we connected fine, we are not waiting for anything else. */
4280
0
    connssl->connecting_state = ssl_connect_3;
4281
0
    Curl_ossl_report_handshake(data, octx);
4282
4283
#if defined(HAVE_SSL_SET1_ECH_CONFIG_LIST) && !defined(HAVE_BORINGSSL_LIKE)
4284
    if(ECH_ENABLED(data)) {
4285
      char *inner = NULL, *outer = NULL;
4286
      const char *status = NULL;
4287
      int rv;
4288
4289
      rv = SSL_ech_get1_status(octx->ssl, &inner, &outer);
4290
      switch(rv) {
4291
      case SSL_ECH_STATUS_SUCCESS:
4292
        status = "succeeded";
4293
        break;
4294
      case SSL_ECH_STATUS_GREASE_ECH:
4295
        status = "sent GREASE, got retry-configs";
4296
        break;
4297
      case SSL_ECH_STATUS_GREASE:
4298
        status = "sent GREASE";
4299
        break;
4300
      case SSL_ECH_STATUS_NOT_TRIED:
4301
        status = "not attempted";
4302
        break;
4303
      case SSL_ECH_STATUS_NOT_CONFIGURED:
4304
        status = "not configured";
4305
        break;
4306
      case SSL_ECH_STATUS_BACKEND:
4307
        status = "backend (unexpected)";
4308
        break;
4309
      case SSL_ECH_STATUS_FAILED:
4310
        status = "failed";
4311
        break;
4312
      case SSL_ECH_STATUS_BAD_CALL:
4313
        status = "bad call (unexpected)";
4314
        break;
4315
      case SSL_ECH_STATUS_BAD_NAME:
4316
        status = "bad name (unexpected)";
4317
        break;
4318
      default:
4319
        status = "unexpected status";
4320
        infof(data, "ECH: unexpected status %d", rv);
4321
      }
4322
      infof(data, "ECH: result: status is %s, inner is %s, outer is %s",
4323
            (status ? status : "NULL"),
4324
            (inner ? inner : "NULL"),
4325
            (outer ? outer : "NULL"));
4326
      OPENSSL_free(inner);
4327
      OPENSSL_free(outer);
4328
      if(rv == SSL_ECH_STATUS_GREASE_ECH) {
4329
        /* trace retry_configs if we got some */
4330
        ossl_trace_ech_retry_configs(data, octx->ssl, 0);
4331
      }
4332
      if(rv != SSL_ECH_STATUS_SUCCESS && (data->set.tls_ech & CURLECH_HARD)) {
4333
        infof(data, "ECH: ech-hard failed");
4334
        return CURLE_SSL_CONNECT_ERROR;
4335
      }
4336
    }
4337
    else {
4338
      infof(data, "ECH: result: status is not attempted");
4339
    }
4340
#endif /* HAVE_SSL_SET1_ECH_CONFIG_LIST && !HAVE_BORINGSSL_LIKE */
4341
4342
    /* Sets data and len to negotiated protocol, len is 0 if no protocol was
4343
     * negotiated
4344
     */
4345
0
    if(connssl->alpn) {
4346
0
      const unsigned char *neg_protocol;
4347
0
      unsigned int len;
4348
0
      SSL_get0_alpn_selected(octx->ssl, &neg_protocol, &len);
4349
4350
0
      return Curl_alpn_set_negotiated(cf, data, connssl, neg_protocol, len);
4351
0
    }
4352
4353
0
    return CURLE_OK;
4354
0
  }
4355
0
}
4356
4357
/*
4358
 * Heavily modified from:
4359
 * https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning#OpenSSL
4360
 */
4361
static CURLcode ossl_pkp_pin_peer_pubkey(struct Curl_easy *data, X509 *cert,
4362
                                         const char *pinnedpubkey)
4363
0
{
4364
  /* Scratch */
4365
0
  int len1 = 0, len2 = 0;
4366
0
  unsigned char *buff1 = NULL, *temp = NULL;
4367
4368
  /* Result is returned to caller */
4369
0
  CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
4370
4371
  /* if a path was not specified, do not pin */
4372
0
  if(!pinnedpubkey)
4373
0
    return CURLE_OK;
4374
4375
0
  if(!cert)
4376
0
    return result;
4377
4378
0
  do {
4379
    /* Get the subjectPublicKeyInfo */
4380
    /* https://groups.google.com/group/mailing.openssl.users/browse_thread/thread/d61858dae102c6c7 */
4381
0
    len1 = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), NULL);
4382
0
    if(len1 < 1)
4383
0
      break; /* failed */
4384
4385
0
    buff1 = temp = curlx_malloc(len1);
4386
0
    if(!buff1)
4387
0
      break; /* failed */
4388
4389
    /* https://docs.openssl.org/master/man3/d2i_X509/ */
4390
0
    len2 = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), &temp);
4391
4392
    /*
4393
     * These checks are verifying we got back the same values as when we
4394
     * sized the buffer. it is pretty weak since they should always be the
4395
     * same. But it gives us something to test.
4396
     */
4397
0
    if((len1 != len2) || !temp || ((temp - buff1) != len1))
4398
0
      break; /* failed */
4399
4400
    /* End Gyrations */
4401
4402
    /* The one good exit point */
4403
0
    result = Curl_pin_peer_pubkey(data, pinnedpubkey, buff1, len1);
4404
0
  } while(0);
4405
4406
0
  if(buff1)
4407
0
    curlx_free(buff1);
4408
4409
0
  return result;
4410
0
}
4411
4412
#if !(defined(LIBRESSL_VERSION_NUMBER) && \
4413
  LIBRESSL_VERSION_NUMBER < 0x3060000fL) && \
4414
  !defined(HAVE_BORINGSSL_LIKE) && defined(CURLVERBOSE)
4415
static void infof_certstack(struct Curl_easy *data, const SSL *ssl)
4416
0
{
4417
0
  STACK_OF(X509) *certstack;
4418
0
  long verify_result;
4419
0
  int num_cert_levels;
4420
0
  int cert_level;
4421
4422
0
  if(!Curl_trc_is_verbose(data))
4423
0
    return;
4424
4425
0
  verify_result = SSL_get_verify_result(ssl);
4426
0
  if(verify_result != X509_V_OK)
4427
0
    certstack = SSL_get_peer_cert_chain(ssl);
4428
0
  else
4429
0
    certstack = SSL_get0_verified_chain(ssl);
4430
0
  if(!certstack)
4431
0
    return;
4432
0
  num_cert_levels = sk_X509_num(certstack);
4433
4434
0
  for(cert_level = 0; cert_level < num_cert_levels; cert_level++) {
4435
0
    char cert_algorithm[80] = "";
4436
0
    char group_name_final[80] = "";
4437
0
    const X509_ALGOR *palg_cert = NULL;
4438
0
    const ASN1_OBJECT *paobj_cert = NULL;
4439
0
    X509 *current_cert;
4440
0
    EVP_PKEY *current_pkey;
4441
0
    int key_bits;
4442
0
    int key_sec_bits;
4443
0
    int get_group_name;
4444
0
    const char *type_name;
4445
4446
0
    current_cert = sk_X509_value(certstack, cert_level);
4447
0
    if(!current_cert)
4448
0
      continue;
4449
4450
0
    current_pkey = X509_get0_pubkey(current_cert);
4451
0
    if(!current_pkey)
4452
0
      continue;
4453
4454
0
    X509_get0_signature(NULL, &palg_cert, current_cert);
4455
0
    X509_ALGOR_get0(&paobj_cert, NULL, NULL, palg_cert);
4456
0
    OBJ_obj2txt(cert_algorithm, sizeof(cert_algorithm), paobj_cert, 0);
4457
4458
0
    key_bits = EVP_PKEY_bits(current_pkey);
4459
#ifndef HAVE_OPENSSL3
4460
#define EVP_PKEY_get_security_bits EVP_PKEY_security_bits
4461
#endif
4462
0
    key_sec_bits = EVP_PKEY_get_security_bits(current_pkey);
4463
0
#ifdef HAVE_OPENSSL3
4464
0
    {
4465
0
      char group_name[80] = "";
4466
0
      get_group_name = EVP_PKEY_get_group_name(current_pkey, group_name,
4467
0
                                               sizeof(group_name), NULL);
4468
0
      curl_msnprintf(group_name_final, sizeof(group_name_final), "/%s",
4469
0
                     group_name);
4470
0
    }
4471
0
    type_name = EVP_PKEY_get0_type_name(current_pkey);
4472
#else
4473
    get_group_name = 0;
4474
    type_name = NULL;
4475
#endif
4476
4477
0
    infof(data, "  Certificate level %d: "
4478
0
          "Public key type %s%s (%d/%d Bits/secBits), signed using %s",
4479
0
          cert_level, type_name ? type_name : "?",
4480
0
          get_group_name == 0 ? "" : group_name_final,
4481
0
          key_bits, key_sec_bits, cert_algorithm);
4482
0
  }
4483
0
}
4484
#else
4485
#define infof_certstack(data, ssl)
4486
#endif
4487
4488
static CURLcode ossl_check_issuer(struct Curl_cfilter *cf,
4489
                                  struct Curl_easy *data,
4490
                                  X509 *server_cert)
4491
0
{
4492
0
  struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
4493
0
  X509 *issuer = NULL;
4494
0
  BIO *fp = NULL;
4495
0
  char err_buf[256] = "";
4496
0
  bool verify_enabled = (conn_config->verifypeer || conn_config->verifyhost);
4497
0
  CURLcode result = CURLE_OK;
4498
4499
  /* e.g. match issuer name with provided issuer certificate */
4500
0
  if(conn_config->issuercert_blob) {
4501
0
    fp = BIO_new_mem_buf(conn_config->issuercert_blob->data,
4502
0
                         (int)conn_config->issuercert_blob->len);
4503
0
    if(!fp) {
4504
0
      failf(data, "BIO_new_mem_buf NULL, " OSSL_PACKAGE " error %s",
4505
0
            ossl_strerror(ERR_get_error(), err_buf, sizeof(err_buf)));
4506
0
      result = CURLE_OUT_OF_MEMORY;
4507
0
      goto out;
4508
0
    }
4509
0
  }
4510
0
  else if(conn_config->issuercert) {
4511
0
    fp = BIO_new(BIO_s_file());
4512
0
    if(!fp) {
4513
0
      failf(data, "BIO_new return NULL, " OSSL_PACKAGE " error %s",
4514
0
            ossl_strerror(ERR_get_error(), err_buf, sizeof(err_buf)));
4515
0
      result = CURLE_OUT_OF_MEMORY;
4516
0
      goto out;
4517
0
    }
4518
4519
0
    if(BIO_read_filename(fp, conn_config->issuercert) <= 0) {
4520
0
      if(verify_enabled)
4521
0
        failf(data, "SSL: Unable to open issuer cert (%s)",
4522
0
              conn_config->issuercert);
4523
0
      result = CURLE_SSL_ISSUER_ERROR;
4524
0
      goto out;
4525
0
    }
4526
0
  }
4527
4528
0
  if(fp) {
4529
0
    issuer = PEM_read_bio_X509(fp, NULL, ZERO_NULL, NULL);
4530
0
    if(!issuer) {
4531
0
      if(verify_enabled)
4532
0
        failf(data, "SSL: Unable to read issuer cert (%s)",
4533
0
              conn_config->issuercert);
4534
0
      result = CURLE_SSL_ISSUER_ERROR;
4535
0
      goto out;
4536
0
    }
4537
4538
0
    if(X509_check_issued(issuer, server_cert) != X509_V_OK) {
4539
0
      if(verify_enabled)
4540
0
        failf(data, "SSL: Certificate issuer check failed (%s)",
4541
0
              conn_config->issuercert);
4542
0
      result = CURLE_SSL_ISSUER_ERROR;
4543
0
      goto out;
4544
0
    }
4545
4546
0
    infof(data, " SSL certificate issuer check ok (%s)",
4547
0
          conn_config->issuercert);
4548
0
  }
4549
4550
0
out:
4551
0
  if(fp)
4552
0
    BIO_free(fp);
4553
0
  if(issuer)
4554
0
    X509_free(issuer);
4555
0
  return result;
4556
0
}
4557
4558
static CURLcode ossl_check_pinned_key(struct Curl_cfilter *cf,
4559
                                      struct Curl_easy *data,
4560
                                      X509 *server_cert)
4561
0
{
4562
0
  const char *ptr;
4563
0
  CURLcode result = CURLE_OK;
4564
4565
0
  (void)cf;
4566
0
#ifndef CURL_DISABLE_PROXY
4567
0
  ptr = Curl_ssl_cf_is_proxy(cf) ?
4568
0
    data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
4569
0
    data->set.str[STRING_SSL_PINNEDPUBLICKEY];
4570
#else
4571
  ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
4572
#endif
4573
0
  if(ptr) {
4574
0
    result = ossl_pkp_pin_peer_pubkey(data, server_cert, ptr);
4575
0
    if(result)
4576
0
      failf(data, "SSL: public key does not match pinned public key");
4577
0
  }
4578
0
  return result;
4579
0
}
4580
4581
#ifdef CURLVERBOSE
4582
0
#define MAX_CERT_NAME_LENGTH 2048
4583
static CURLcode ossl_infof_cert(struct Curl_cfilter *cf,
4584
                                struct Curl_easy *data,
4585
                                X509 *server_cert)
4586
0
{
4587
0
  BIO *mem = NULL;
4588
0
  struct dynbuf dname;
4589
0
  char err_buf[256] = "";
4590
0
  char *buf;
4591
0
  long len;
4592
0
  CURLcode result = CURLE_OK;
4593
4594
0
  if(!Curl_trc_is_verbose(data))
4595
0
    return CURLE_OK;
4596
4597
0
  curlx_dyn_init(&dname, MAX_CERT_NAME_LENGTH);
4598
0
  mem = BIO_new(BIO_s_mem());
4599
0
  if(!mem) {
4600
0
    failf(data, "BIO_new return NULL, " OSSL_PACKAGE " error %s",
4601
0
          ossl_strerror(ERR_get_error(), err_buf, sizeof(err_buf)));
4602
0
    result = CURLE_OUT_OF_MEMORY;
4603
0
    goto out;
4604
0
  }
4605
4606
0
  infof(data, "%s certificate:", Curl_ssl_cf_is_proxy(cf) ?
4607
0
        "Proxy" : "Server");
4608
4609
0
  result = x509_name_oneline(X509_get_subject_name(server_cert), &dname);
4610
0
  infof(data, "  subject: %s", result ? "[NONE]" : curlx_dyn_ptr(&dname));
4611
4612
0
  ASN1_TIME_print(mem, X509_get0_notBefore(server_cert));
4613
0
  len = BIO_get_mem_data(mem, (char **)&buf);
4614
0
  infof(data, "  start date: %.*s", (int)len, buf);
4615
0
  (void)BIO_reset(mem);
4616
4617
0
  ASN1_TIME_print(mem, X509_get0_notAfter(server_cert));
4618
0
  len = BIO_get_mem_data(mem, (char **)&buf);
4619
0
  infof(data, "  expire date: %.*s", (int)len, buf);
4620
0
  (void)BIO_reset(mem);
4621
4622
0
  result = x509_name_oneline(X509_get_issuer_name(server_cert), &dname);
4623
0
  if(result) /* should be only fatal stuff like OOM */
4624
0
    goto out;
4625
0
  infof(data, "  issuer: %s", curlx_dyn_ptr(&dname));
4626
4627
0
out:
4628
0
  BIO_free(mem);
4629
0
  curlx_dyn_free(&dname);
4630
0
  return result;
4631
0
}
4632
#endif /* CURLVERBOSE */
4633
4634
#ifdef USE_APPLE_SECTRUST
4635
struct ossl_certs_ctx {
4636
  STACK_OF(X509) *sk;
4637
  size_t num_certs;
4638
};
4639
4640
static CURLcode ossl_chain_get_der(struct Curl_cfilter *cf,
4641
                                   struct Curl_easy *data,
4642
                                   void *user_data,
4643
                                   size_t i,
4644
                                   unsigned char **pder,
4645
                                   size_t *pder_len)
4646
{
4647
  struct ossl_certs_ctx *chain = user_data;
4648
  X509 *cert;
4649
  int der_len;
4650
4651
  (void)cf;
4652
  (void)data;
4653
  *pder_len = 0;
4654
  *pder = NULL;
4655
4656
  if(i >= chain->num_certs)
4657
    return CURLE_TOO_LARGE;
4658
  cert = sk_X509_value(chain->sk, (int)i);
4659
  if(!cert)
4660
    return CURLE_FAILED_INIT;
4661
  der_len = i2d_X509(cert, pder);
4662
  if(der_len < 0)
4663
    return CURLE_FAILED_INIT;
4664
  *pder_len = (size_t)der_len;
4665
  return CURLE_OK;
4666
}
4667
4668
static CURLcode ossl_apple_verify(struct Curl_cfilter *cf,
4669
                                  struct Curl_easy *data,
4670
                                  struct ossl_ctx *octx,
4671
                                  struct ssl_peer *peer,
4672
                                  bool *pverified)
4673
{
4674
  struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
4675
  struct ossl_certs_ctx chain;
4676
  CURLcode result;
4677
4678
  memset(&chain, 0, sizeof(chain));
4679
  chain.sk = SSL_get_peer_cert_chain(octx->ssl);
4680
  chain.num_certs = chain.sk ? sk_X509_num(chain.sk) : 0;
4681
4682
  if(!chain.num_certs &&
4683
     (conn_config->verifypeer || conn_config->verifyhost)) {
4684
    failf(data, "SSL: could not get peer certificate");
4685
    result = CURLE_PEER_FAILED_VERIFICATION;
4686
  }
4687
  else {
4688
#ifdef HAVE_BORINGSSL_LIKE
4689
    const uint8_t *ocsp_data = NULL;
4690
#else
4691
    unsigned char *ocsp_data = NULL;
4692
#endif
4693
    long ocsp_len = 0;
4694
    if(conn_config->verifystatus && !octx->reused_session)
4695
      ocsp_len = (long)SSL_get_tlsext_status_ocsp_resp(octx->ssl, &ocsp_data);
4696
4697
    /* SSL_get_tlsext_status_ocsp_resp() returns the length of the OCSP
4698
       response data or -1 if there is no OCSP response data. */
4699
    if(ocsp_len < 0)
4700
      ocsp_len = 0; /* no data available */
4701
    result = Curl_vtls_apple_verify(cf, data, peer, chain.num_certs,
4702
                                    ossl_chain_get_der, &chain,
4703
                                    ocsp_data, ocsp_len);
4704
  }
4705
  *pverified = !result;
4706
  return result;
4707
}
4708
#endif /* USE_APPLE_SECTRUST */
4709
4710
CURLcode Curl_ossl_check_peer_cert(struct Curl_cfilter *cf,
4711
                                   struct Curl_easy *data,
4712
                                   struct ossl_ctx *octx,
4713
                                   struct ssl_peer *peer)
4714
0
{
4715
0
  struct connectdata *conn = cf->conn;
4716
0
  struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
4717
0
  struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
4718
0
  CURLcode result = CURLE_OK;
4719
0
  long ossl_verify;
4720
0
  X509 *server_cert;
4721
0
  bool verified = FALSE;
4722
#if !defined(OPENSSL_NO_OCSP) && defined(USE_APPLE_SECTRUST)
4723
  bool sectrust_verified = FALSE;
4724
#endif
4725
4726
0
  if(data->set.ssl.certinfo && !octx->reused_session) {
4727
    /* asked to gather certificate info. Reused sessions do not have cert
4728
       chains */
4729
0
    result = ossl_certchain(data, octx->ssl);
4730
0
    if(result)
4731
0
      return result;
4732
0
  }
4733
4734
0
  server_cert = SSL_get1_peer_certificate(octx->ssl);
4735
0
  if(!server_cert) {
4736
    /* no verification at all, this maybe acceptable */
4737
0
    if(!(conn_config->verifypeer || conn_config->verifyhost))
4738
0
      goto out;
4739
4740
0
    failf(data, "SSL: could not get peer certificate");
4741
0
    result = CURLE_PEER_FAILED_VERIFICATION;
4742
0
    goto out;
4743
0
  }
4744
4745
0
#ifdef CURLVERBOSE
4746
0
  result = ossl_infof_cert(cf, data, server_cert);
4747
0
  if(result)
4748
0
    goto out;
4749
0
  infof_certstack(data, octx->ssl);
4750
0
#endif
4751
4752
0
  if(conn_config->verifyhost) {
4753
0
    result = ossl_verifyhost(data, conn, peer, server_cert);
4754
0
    if(result)
4755
0
      goto out;
4756
0
  }
4757
  /* `verifyhost` is either OK or not requested from here on */
4758
4759
0
  ossl_verify = SSL_get_verify_result(octx->ssl);
4760
0
  ssl_config->certverifyresult = ossl_verify;
4761
4762
0
  verified = (ossl_verify == X509_V_OK);
4763
0
  if(verified)
4764
0
    infof(data, "SSL certificate verified via OpenSSL.");
4765
4766
#ifdef USE_APPLE_SECTRUST
4767
  if(!verified && conn_config->verifypeer && ssl_config->native_ca_store) {
4768
    /* we verify using Apple SecTrust *unless* OpenSSL already verified.
4769
     * This may happen if the application intercepted the OpenSSL callback
4770
     * and installed its own. */
4771
    result = ossl_apple_verify(cf, data, octx, peer, &verified);
4772
    if(result && (result != CURLE_PEER_FAILED_VERIFICATION))
4773
      goto out; /* unexpected error */
4774
    if(verified) {
4775
      infof(data, "SSL certificate verified via Apple SecTrust.");
4776
      ssl_config->certverifyresult = X509_V_OK;
4777
#ifndef OPENSSL_NO_OCSP
4778
      sectrust_verified = TRUE;
4779
#endif
4780
    }
4781
  }
4782
#endif
4783
4784
0
  if(!verified) {
4785
    /* no trust established, report the OpenSSL status */
4786
0
    if(conn_config->verifypeer) {
4787
0
      failf(data, "SSL certificate OpenSSL verify result: %s (%ld)",
4788
0
            X509_verify_cert_error_string(ossl_verify), ossl_verify);
4789
0
      result = CURLE_PEER_FAILED_VERIFICATION;
4790
0
      goto out;
4791
0
    }
4792
0
    infof(data, " SSL certificate verification failed, continuing anyway!");
4793
0
  }
4794
4795
0
#ifndef OPENSSL_NO_OCSP
4796
0
  if(conn_config->verifystatus &&
4797
#ifdef USE_APPLE_SECTRUST
4798
     !sectrust_verified && /* already verified via apple sectrust, cannot
4799
                            * verifystate via OpenSSL in that case as it
4800
                            * does not have the trust anchors */
4801
#endif
4802
0
     !octx->reused_session) {
4803
    /* do not do this after Session ID reuse */
4804
0
    result = verifystatus(cf, data, octx);
4805
0
    if(result)
4806
0
      goto out;
4807
0
  }
4808
0
#endif
4809
4810
0
  result = ossl_check_issuer(cf, data, server_cert);
4811
0
  if(result)
4812
0
    goto out;
4813
4814
0
  result = ossl_check_pinned_key(cf, data, server_cert);
4815
4816
0
out:
4817
0
  X509_free(server_cert);
4818
0
  return result;
4819
0
}
4820
4821
static CURLcode ossl_connect_step3(struct Curl_cfilter *cf,
4822
                                   struct Curl_easy *data)
4823
0
{
4824
0
  CURLcode result = CURLE_OK;
4825
0
  struct ssl_connect_data *connssl = cf->ctx;
4826
0
  struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
4827
4828
0
  DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
4829
4830
  /*
4831
   * We check certificates to authenticate the server; otherwise we risk
4832
   * man-in-the-middle attack; NEVERTHELESS, if we are told explicitly not to
4833
   * verify the peer, ignore faults and failures from the server cert
4834
   * operations.
4835
   */
4836
4837
0
  result = Curl_ossl_check_peer_cert(cf, data, octx, &connssl->peer);
4838
0
  if(result)
4839
    /* on error, remove sessions we might have in the pool */
4840
0
    Curl_ssl_scache_remove_all(cf, data, connssl->peer.scache_key);
4841
4842
0
  return result;
4843
0
}
4844
4845
#ifdef HAVE_OPENSSL_EARLYDATA
4846
static CURLcode ossl_send_earlydata(struct Curl_cfilter *cf,
4847
                                    struct Curl_easy *data)
4848
0
{
4849
0
  struct ssl_connect_data *connssl = cf->ctx;
4850
0
  struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
4851
0
  CURLcode result = CURLE_OK;
4852
0
  const unsigned char *buf;
4853
0
  size_t blen, nwritten;
4854
0
  int rc;
4855
4856
0
  DEBUGASSERT(connssl->earlydata_state == ssl_earlydata_sending);
4857
0
  octx->io_result = CURLE_OK;
4858
0
  while(Curl_bufq_peek(&connssl->earlydata, &buf, &blen)) {
4859
0
    nwritten = 0;
4860
0
    rc = SSL_write_early_data(octx->ssl, buf, blen, &nwritten);
4861
0
    CURL_TRC_CF(data, cf, "SSL_write_early_data(len=%zu) -> %d, %zu",
4862
0
                blen, rc, nwritten);
4863
0
    if(rc <= 0) {
4864
0
      long sslerror;
4865
0
      char error_buffer[256];
4866
0
      int err = SSL_get_error(octx->ssl, rc);
4867
4868
0
      switch(err) {
4869
0
      case SSL_ERROR_WANT_READ:
4870
0
        connssl->io_need = CURL_SSL_IO_NEED_RECV;
4871
0
        result = CURLE_AGAIN;
4872
0
        goto out;
4873
0
      case SSL_ERROR_WANT_WRITE:
4874
0
        connssl->io_need = CURL_SSL_IO_NEED_SEND;
4875
0
        result = CURLE_AGAIN;
4876
0
        goto out;
4877
0
      case SSL_ERROR_SYSCALL: {
4878
0
        int sockerr = SOCKERRNO;
4879
4880
0
        if(octx->io_result == CURLE_AGAIN) {
4881
0
          result = CURLE_AGAIN;
4882
0
          goto out;
4883
0
        }
4884
0
        sslerror = ERR_get_error();
4885
0
        if(sslerror)
4886
0
          ossl_strerror(sslerror, error_buffer, sizeof(error_buffer));
4887
0
        else if(sockerr)
4888
0
          curlx_strerror(sockerr, error_buffer, sizeof(error_buffer));
4889
0
        else
4890
0
          curl_msnprintf(error_buffer, sizeof(error_buffer), "%s",
4891
0
                         SSL_ERROR_to_str(err));
4892
4893
0
        failf(data, OSSL_PACKAGE " SSL_write:early_data: %s, errno %d",
4894
0
              error_buffer, sockerr);
4895
0
        result = CURLE_SEND_ERROR;
4896
0
        goto out;
4897
0
      }
4898
0
      case SSL_ERROR_SSL: {
4899
        /*  A failure in the SSL library occurred, usually a protocol error.
4900
            The OpenSSL error queue contains more information on the error. */
4901
0
        sslerror = ERR_get_error();
4902
0
        failf(data, "SSL_write_early_data() error: %s",
4903
0
              ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)));
4904
0
        result = CURLE_SEND_ERROR;
4905
0
        goto out;
4906
0
      }
4907
0
      default:
4908
        /* a true error */
4909
0
        failf(data, OSSL_PACKAGE " SSL_write_early_data: %s, errno %d",
4910
0
              SSL_ERROR_to_str(err), SOCKERRNO);
4911
0
        result = CURLE_SEND_ERROR;
4912
0
        goto out;
4913
0
      }
4914
0
    }
4915
0
    Curl_bufq_skip(&connssl->earlydata, nwritten);
4916
0
  }
4917
  /* sent everything there was */
4918
0
  infof(data, "SSL sending %zu bytes of early data", connssl->earlydata_skip);
4919
0
out:
4920
0
  return result;
4921
0
}
4922
#endif /* HAVE_OPENSSL_EARLYDATA */
4923
4924
static CURLcode ossl_connect(struct Curl_cfilter *cf,
4925
                             struct Curl_easy *data,
4926
                             bool *done)
4927
0
{
4928
0
  CURLcode result = CURLE_OK;
4929
0
  struct ssl_connect_data *connssl = cf->ctx;
4930
4931
  /* check if the connection has already been established */
4932
0
  if(ssl_connection_complete == connssl->state) {
4933
0
    *done = TRUE;
4934
0
    return CURLE_OK;
4935
0
  }
4936
4937
0
  *done = FALSE;
4938
0
  connssl->io_need = CURL_SSL_IO_NEED_NONE;
4939
4940
0
  if(ssl_connect_1 == connssl->connecting_state) {
4941
0
    CURL_TRC_CF(data, cf, "ossl_connect, step1");
4942
0
    result = ossl_connect_step1(cf, data);
4943
0
    if(result)
4944
0
      goto out;
4945
0
  }
4946
4947
0
  if(ssl_connect_2 == connssl->connecting_state) {
4948
0
    CURL_TRC_CF(data, cf, "ossl_connect, step2");
4949
0
#ifdef HAVE_OPENSSL_EARLYDATA
4950
0
    if(connssl->earlydata_state == ssl_earlydata_await) {
4951
0
      goto out;
4952
0
    }
4953
0
    else if(connssl->earlydata_state == ssl_earlydata_sending) {
4954
0
      result = ossl_send_earlydata(cf, data);
4955
0
      if(result)
4956
0
        goto out;
4957
0
      connssl->earlydata_state = ssl_earlydata_sent;
4958
0
    }
4959
0
#endif
4960
0
    DEBUGASSERT((connssl->earlydata_state == ssl_earlydata_none) ||
4961
0
                (connssl->earlydata_state == ssl_earlydata_sent));
4962
4963
0
    result = ossl_connect_step2(cf, data);
4964
0
    if(result)
4965
0
      goto out;
4966
0
  }
4967
4968
0
  if(ssl_connect_3 == connssl->connecting_state) {
4969
0
    CURL_TRC_CF(data, cf, "ossl_connect, step3");
4970
0
    result = ossl_connect_step3(cf, data);
4971
0
    if(result)
4972
0
      goto out;
4973
0
    connssl->connecting_state = ssl_connect_done;
4974
0
#ifdef HAVE_OPENSSL_EARLYDATA
4975
0
    if(connssl->earlydata_state > ssl_earlydata_none) {
4976
0
      struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
4977
      /* We should be in this state by now */
4978
0
      DEBUGASSERT(connssl->earlydata_state == ssl_earlydata_sent);
4979
0
      connssl->earlydata_state =
4980
0
        (SSL_get_early_data_status(octx->ssl) == SSL_EARLY_DATA_ACCEPTED) ?
4981
0
        ssl_earlydata_accepted : ssl_earlydata_rejected;
4982
0
    }
4983
0
#endif
4984
0
  }
4985
4986
0
  if(ssl_connect_done == connssl->connecting_state) {
4987
0
    CURL_TRC_CF(data, cf, "ossl_connect, done");
4988
0
    connssl->state = ssl_connection_complete;
4989
0
  }
4990
4991
0
out:
4992
0
  if(result == CURLE_AGAIN) {
4993
0
    *done = FALSE;
4994
0
    return CURLE_OK;
4995
0
  }
4996
0
  *done = ((connssl->state == ssl_connection_complete) ||
4997
0
           (connssl->state == ssl_connection_deferred));
4998
0
  return result;
4999
0
}
5000
5001
static bool ossl_data_pending(struct Curl_cfilter *cf,
5002
                              const struct Curl_easy *data)
5003
0
{
5004
0
  struct ssl_connect_data *connssl = cf->ctx;
5005
0
  (void)data;
5006
0
  return (bool)connssl->input_pending;
5007
0
}
5008
5009
static CURLcode ossl_send(struct Curl_cfilter *cf,
5010
                          struct Curl_easy *data,
5011
                          const void *mem,
5012
                          size_t len,
5013
                          size_t *pnwritten)
5014
0
{
5015
  /* SSL_write() is said to return 'int' while write() and send() returns
5016
     'size_t' */
5017
0
  int err;
5018
0
  char error_buffer[256];
5019
0
  sslerr_t sslerror;
5020
0
  int memlen;
5021
0
  struct ssl_connect_data *connssl = cf->ctx;
5022
0
  struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
5023
0
  CURLcode result = CURLE_OK;
5024
0
  int nwritten;
5025
5026
0
  DEBUGASSERT(octx);
5027
0
  *pnwritten = 0;
5028
0
  ERR_clear_error();
5029
5030
0
  connssl->io_need = CURL_SSL_IO_NEED_NONE;
5031
0
  memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
5032
0
  if(octx->blocked_ssl_write_len && (octx->blocked_ssl_write_len != memlen)) {
5033
    /* The previous SSL_write() call was blocked, using that length.
5034
     * We need to use that again or OpenSSL will freak out. A shorter
5035
     * length should not happen and is a bug in libcurl. */
5036
0
    if(octx->blocked_ssl_write_len > memlen) {
5037
0
      DEBUGASSERT(0);
5038
0
      return CURLE_BAD_FUNCTION_ARGUMENT;
5039
0
    }
5040
0
    memlen = octx->blocked_ssl_write_len;
5041
0
  }
5042
0
  octx->blocked_ssl_write_len = 0;
5043
0
  nwritten = SSL_write(octx->ssl, mem, memlen);
5044
5045
0
  if(nwritten > 0)
5046
0
    *pnwritten = (size_t)nwritten;
5047
0
  else {
5048
0
    err = SSL_get_error(octx->ssl, nwritten);
5049
5050
0
    switch(err) {
5051
0
    case SSL_ERROR_WANT_READ:
5052
0
      connssl->io_need = CURL_SSL_IO_NEED_RECV;
5053
0
      octx->blocked_ssl_write_len = memlen;
5054
0
      result = CURLE_AGAIN;
5055
0
      goto out;
5056
0
    case SSL_ERROR_WANT_WRITE:
5057
0
      result = CURLE_AGAIN;
5058
0
      octx->blocked_ssl_write_len = memlen;
5059
0
      goto out;
5060
0
    case SSL_ERROR_SYSCALL: {
5061
0
      int sockerr = SOCKERRNO;
5062
5063
0
      if(octx->io_result == CURLE_AGAIN) {
5064
0
        octx->blocked_ssl_write_len = memlen;
5065
0
        result = CURLE_AGAIN;
5066
0
        goto out;
5067
0
      }
5068
0
      sslerror = ERR_get_error();
5069
0
      if(sslerror)
5070
0
        ossl_strerror(sslerror, error_buffer, sizeof(error_buffer));
5071
0
      else if(sockerr)
5072
0
        curlx_strerror(sockerr, error_buffer, sizeof(error_buffer));
5073
0
      else
5074
0
        curl_msnprintf(error_buffer, sizeof(error_buffer), "%s",
5075
0
                       SSL_ERROR_to_str(err));
5076
5077
0
      failf(data, OSSL_PACKAGE " SSL_write: %s, errno %d",
5078
0
            error_buffer, sockerr);
5079
0
      result = CURLE_SEND_ERROR;
5080
0
      goto out;
5081
0
    }
5082
0
    case SSL_ERROR_SSL: {
5083
      /*  A failure in the SSL library occurred, usually a protocol error.
5084
          The OpenSSL error queue contains more information on the error. */
5085
0
      sslerror = ERR_get_error();
5086
0
      failf(data, "SSL_write() error: %s",
5087
0
            ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)));
5088
0
      result = CURLE_SEND_ERROR;
5089
0
      goto out;
5090
0
    }
5091
0
    default:
5092
      /* a true error */
5093
0
      failf(data, OSSL_PACKAGE " SSL_write: %s, errno %d",
5094
0
            SSL_ERROR_to_str(err), SOCKERRNO);
5095
0
      result = CURLE_SEND_ERROR;
5096
0
      goto out;
5097
0
    }
5098
0
  }
5099
5100
0
out:
5101
0
  return result;
5102
0
}
5103
5104
static CURLcode ossl_recv(struct Curl_cfilter *cf,
5105
                          struct Curl_easy *data,   /* transfer */
5106
                          char *buf,                /* store read data here */
5107
                          size_t buffersize,        /* max amount to read */
5108
                          size_t *pnread)
5109
0
{
5110
0
  char error_buffer[256];
5111
0
  unsigned long sslerror;
5112
0
  int buffsize;
5113
0
  struct ssl_connect_data *connssl = cf->ctx;
5114
0
  struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
5115
0
  CURLcode result = CURLE_OK;
5116
0
  int nread;
5117
5118
0
  DEBUGASSERT(octx);
5119
5120
0
  *pnread = 0;
5121
0
  ERR_clear_error();
5122
5123
0
  connssl->io_need = CURL_SSL_IO_NEED_NONE;
5124
0
  buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
5125
0
  nread = SSL_read(octx->ssl, buf, buffsize);
5126
5127
0
  if(nread > 0)
5128
0
    *pnread = (size_t)nread;
5129
0
  else {
5130
    /* failed SSL_read */
5131
0
    int err = SSL_get_error(octx->ssl, (int)nread);
5132
5133
0
    switch(err) {
5134
0
    case SSL_ERROR_NONE: /* this is not an error */
5135
0
      break;
5136
0
    case SSL_ERROR_ZERO_RETURN: /* no more data */
5137
      /* close_notify alert */
5138
0
      if(cf->sockindex == FIRSTSOCKET)
5139
        /* mark the connection for close if it is indeed the control
5140
           connection */
5141
0
        CURL_TRC_CF(data, cf, "TLS close_notify");
5142
0
      break;
5143
0
    case SSL_ERROR_WANT_READ:
5144
0
      connssl->io_need = CURL_SSL_IO_NEED_RECV;
5145
0
      result = CURLE_AGAIN;
5146
0
      goto out;
5147
0
    case SSL_ERROR_WANT_WRITE:
5148
0
      connssl->io_need = CURL_SSL_IO_NEED_SEND;
5149
0
      result = CURLE_AGAIN;
5150
0
      goto out;
5151
0
    default:
5152
      /* openssl/ssl.h for SSL_ERROR_SYSCALL says "look at error stack/return
5153
         value/errno" */
5154
      /* https://docs.openssl.org/master/man3/ERR_get_error/ */
5155
0
      if(octx->io_result == CURLE_AGAIN) {
5156
0
        result = CURLE_AGAIN;
5157
0
        goto out;
5158
0
      }
5159
0
      sslerror = ERR_get_error();
5160
0
      if((nread < 0) || sslerror) {
5161
        /* If the return code was negative or there actually is an error in the
5162
           queue */
5163
0
        int sockerr = SOCKERRNO;
5164
0
        if(sslerror)
5165
0
          ossl_strerror(sslerror, error_buffer, sizeof(error_buffer));
5166
0
        else if(sockerr && err == SSL_ERROR_SYSCALL)
5167
0
          curlx_strerror(sockerr, error_buffer, sizeof(error_buffer));
5168
0
        else
5169
0
          curl_msnprintf(error_buffer, sizeof(error_buffer), "%s",
5170
0
                         SSL_ERROR_to_str(err));
5171
0
        failf(data, OSSL_PACKAGE " SSL_read: %s, errno %d",
5172
0
              error_buffer, sockerr);
5173
0
        result = CURLE_RECV_ERROR;
5174
0
        goto out;
5175
0
      }
5176
0
      else if(err == SSL_ERROR_SYSCALL) {
5177
0
        if(octx->io_result) {
5178
          /* logging handling in underlying filter already */
5179
0
          result = octx->io_result;
5180
0
        }
5181
0
        else if(connssl->peer_closed) {
5182
0
          failf(data, "Connection closed abruptly");
5183
0
          result = CURLE_RECV_ERROR;
5184
0
        }
5185
0
        else {
5186
          /* We should no longer get here nowadays. But handle
5187
           * the error in case of some weirdness in the OSSL stack */
5188
0
          int sockerr = SOCKERRNO;
5189
0
          if(sockerr)
5190
0
            curlx_strerror(sockerr, error_buffer, sizeof(error_buffer));
5191
0
          else {
5192
0
            curl_msnprintf(error_buffer, sizeof(error_buffer),
5193
0
                           "Connection closed abruptly");
5194
0
          }
5195
0
          failf(data, OSSL_PACKAGE " SSL_read: %s, errno %d",
5196
0
                error_buffer, sockerr);
5197
0
          result = CURLE_RECV_ERROR;
5198
0
        }
5199
0
        goto out;
5200
0
      }
5201
0
    }
5202
0
  }
5203
5204
0
out:
5205
0
  if((!result && !*pnread) || (result == CURLE_AGAIN)) {
5206
    /* This happens when:
5207
     * - we read an EOF
5208
     * - OpenSSLs buffers are empty, there is no more data
5209
     * - OpenSSL read is blocked on writing something first
5210
     * - an incomplete TLS packet is buffered that cannot be read
5211
     *   until more data arrives */
5212
0
    connssl->input_pending = FALSE;
5213
0
  }
5214
0
  CURL_TRC_CF(data, cf, "ossl_recv(len=%zu) -> %d, %zu (in_pending=%d)",
5215
0
              buffersize, result, *pnread, connssl->input_pending);
5216
0
  return result;
5217
0
}
5218
5219
static CURLcode ossl_get_channel_binding(struct Curl_easy *data, int sockindex,
5220
                                         struct dynbuf *binding)
5221
0
{
5222
0
  X509 *cert;
5223
0
  int algo_nid;
5224
0
  const EVP_MD *algo_type;
5225
0
  const char *algo_name;
5226
0
  unsigned int length;
5227
0
  unsigned char buf[EVP_MAX_MD_SIZE];
5228
5229
0
  const char prefix[] = "tls-server-end-point:";
5230
0
  struct connectdata *conn = data->conn;
5231
0
  struct Curl_cfilter *cf = conn->cfilter[sockindex];
5232
0
  struct ossl_ctx *octx = NULL;
5233
0
  CURLcode result = CURLE_OK;
5234
5235
0
  do {
5236
0
    const struct Curl_cftype *cft = cf->cft;
5237
0
    struct ssl_connect_data *connssl = cf->ctx;
5238
5239
0
    if(cft->name && !strcmp(cft->name, "SSL")) {
5240
0
      octx = (struct ossl_ctx *)connssl->backend;
5241
0
      break;
5242
0
    }
5243
5244
0
    cf = cf->next;
5245
0
  } while(cf);
5246
5247
0
  if(!octx) {
5248
0
    failf(data, "Failed to find the SSL filter");
5249
0
    return CURLE_BAD_FUNCTION_ARGUMENT;
5250
0
  }
5251
5252
0
  cert = SSL_get1_peer_certificate(octx->ssl);
5253
0
  if(!cert)
5254
    /* No server certificate, do not do channel binding */
5255
0
    return CURLE_OK;
5256
5257
0
  if(!OBJ_find_sigid_algs(X509_get_signature_nid(cert), &algo_nid, NULL)) {
5258
0
    failf(data,
5259
0
          "Unable to find digest NID for certificate signature algorithm");
5260
0
    result = CURLE_SSL_INVALIDCERTSTATUS;
5261
0
    goto error;
5262
0
  }
5263
5264
  /* https://datatracker.ietf.org/doc/html/rfc5929#section-4.1 */
5265
0
  if(algo_nid == NID_md5 || algo_nid == NID_sha1) {
5266
0
    algo_type = EVP_sha256();
5267
0
  }
5268
0
  else {
5269
0
    algo_type = EVP_get_digestbynid(algo_nid);
5270
0
    if(!algo_type) {
5271
0
      algo_name = OBJ_nid2sn(algo_nid);
5272
0
      failf(data, "Could not find digest algorithm %s (NID %d)",
5273
0
            algo_name ? algo_name : "(null)", algo_nid);
5274
0
      result = CURLE_SSL_INVALIDCERTSTATUS;
5275
0
      goto error;
5276
0
    }
5277
0
  }
5278
5279
0
  if(!X509_digest(cert, algo_type, buf, &length)) {
5280
0
    failf(data, "X509_digest() failed");
5281
0
    result = CURLE_SSL_INVALIDCERTSTATUS;
5282
0
    goto error;
5283
0
  }
5284
5285
  /* Append "tls-server-end-point:" */
5286
0
  result = curlx_dyn_addn(binding, prefix, sizeof(prefix) - 1);
5287
0
  if(result)
5288
0
    goto error;
5289
5290
  /* Append digest */
5291
0
  result = curlx_dyn_addn(binding, buf, length);
5292
5293
0
error:
5294
0
  X509_free(cert);
5295
0
  return result;
5296
0
}
5297
5298
size_t Curl_ossl_version(char *buffer, size_t size)
5299
0
{
5300
#ifdef LIBRESSL_VERSION_NUMBER
5301
  char *p;
5302
  size_t count;
5303
  const char *ver = OpenSSL_version(OPENSSL_VERSION);
5304
  const char expected[] = OSSL_PACKAGE " "; /* ie "LibreSSL " */
5305
  if(curl_strnequal(ver, expected, sizeof(expected) - 1)) {
5306
    ver += sizeof(expected) - 1;
5307
  }
5308
  count = curl_msnprintf(buffer, size, "%s/%s", OSSL_PACKAGE, ver);
5309
  for(p = buffer; *p; ++p) {
5310
    if(ISBLANK(*p))
5311
      *p = '_';
5312
  }
5313
  return count;
5314
#elif defined(OPENSSL_IS_BORINGSSL)
5315
#ifdef CURL_BORINGSSL_VERSION
5316
  return curl_msnprintf(buffer, size, "%s/%s",
5317
                        OSSL_PACKAGE, CURL_BORINGSSL_VERSION);
5318
#else
5319
  return curl_msnprintf(buffer, size, OSSL_PACKAGE);
5320
#endif
5321
#elif defined(OPENSSL_IS_AWSLC)
5322
  return curl_msnprintf(buffer, size, "%s/%s",
5323
                        OSSL_PACKAGE, AWSLC_VERSION_NUMBER_STRING);
5324
#else /* OpenSSL 3+ */
5325
0
  return curl_msnprintf(buffer, size, "%s/%s",
5326
0
                        OSSL_PACKAGE, OpenSSL_version(OPENSSL_VERSION_STRING));
5327
0
#endif
5328
0
}
5329
5330
/* can be called with data == NULL */
5331
static CURLcode ossl_random(struct Curl_easy *data,
5332
                            unsigned char *entropy, size_t length)
5333
0
{
5334
0
  int rc;
5335
0
  if(data) {
5336
0
    if(ossl_seed(data)) /* Initiate the seed if not already done */
5337
0
      return CURLE_FAILED_INIT; /* could not seed for some reason */
5338
0
  }
5339
0
  else {
5340
0
    if(!rand_enough())
5341
0
      return CURLE_FAILED_INIT;
5342
0
  }
5343
  /* RAND_bytes() returns 1 on success, 0 otherwise.  */
5344
0
  rc = RAND_bytes(entropy, (ossl_valsize_t)curlx_uztosi(length));
5345
0
  return rc == 1 ? CURLE_OK : CURLE_FAILED_INIT;
5346
0
}
5347
5348
static CURLcode ossl_sha256sum(const unsigned char *tmp, /* input */
5349
                               size_t tmplen,
5350
                               unsigned char *sha256sum /* output */,
5351
                               size_t unused)
5352
0
{
5353
0
  EVP_MD_CTX *mdctx;
5354
0
  unsigned int len = 0;
5355
0
  (void)unused;
5356
5357
0
  mdctx = EVP_MD_CTX_create();
5358
0
  if(!mdctx)
5359
0
    return CURLE_OUT_OF_MEMORY;
5360
0
  if(!EVP_DigestInit(mdctx, EVP_sha256())) {
5361
0
    EVP_MD_CTX_destroy(mdctx);
5362
0
    return CURLE_FAILED_INIT;
5363
0
  }
5364
0
  EVP_DigestUpdate(mdctx, tmp, tmplen);
5365
0
  EVP_DigestFinal_ex(mdctx, sha256sum, &len);
5366
0
  EVP_MD_CTX_destroy(mdctx);
5367
0
  return CURLE_OK;
5368
0
}
5369
5370
static bool ossl_cert_status_request(void)
5371
0
{
5372
0
#ifndef OPENSSL_NO_OCSP
5373
0
  return TRUE;
5374
#else
5375
  return FALSE;
5376
#endif
5377
0
}
5378
5379
static void *ossl_get_internals(struct ssl_connect_data *connssl,
5380
                                CURLINFO info)
5381
0
{
5382
  /* Legacy: CURLINFO_TLS_SESSION must return an SSL_CTX pointer. */
5383
0
  struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend;
5384
0
  DEBUGASSERT(octx);
5385
0
  return info == CURLINFO_TLS_SESSION ?
5386
0
    (void *)octx->ssl_ctx : (void *)octx->ssl;
5387
0
}
5388
5389
const struct Curl_ssl Curl_ssl_openssl = {
5390
  { CURLSSLBACKEND_OPENSSL, "openssl" }, /* info */
5391
5392
  SSLSUPP_CA_PATH |
5393
  SSLSUPP_CAINFO_BLOB |
5394
  SSLSUPP_CERTINFO |
5395
  SSLSUPP_PINNEDPUBKEY |
5396
  SSLSUPP_SSL_CTX |
5397
#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
5398
  SSLSUPP_TLS13_CIPHERSUITES |
5399
#endif
5400
#ifdef HAVE_SSL_CTX_SET1_SIGALGS
5401
  SSLSUPP_SIGNATURE_ALGORITHMS |
5402
#endif
5403
#ifdef HAVE_SSL_SET1_ECH_CONFIG_LIST
5404
  SSLSUPP_ECH |
5405
#endif
5406
  SSLSUPP_CA_CACHE |
5407
  SSLSUPP_HTTPS_PROXY |
5408
  SSLSUPP_CIPHER_LIST |
5409
  SSLSUPP_ISSUERCERT |
5410
  SSLSUPP_ISSUERCERT_BLOB |
5411
  SSLSUPP_SSL_EC_CURVES |
5412
  SSLSUPP_CRLFILE,
5413
5414
  sizeof(struct ossl_ctx),
5415
5416
  ossl_init,                /* init */
5417
  ossl_cleanup,             /* cleanup */
5418
  Curl_ossl_version,        /* version */
5419
  ossl_shutdown,            /* shutdown */
5420
  ossl_data_pending,        /* data_pending */
5421
  ossl_random,              /* random */
5422
  ossl_cert_status_request, /* cert_status_request */
5423
  ossl_connect,             /* connect */
5424
  Curl_ssl_adjust_pollset,  /* adjust_pollset */
5425
  ossl_get_internals,       /* get_internals */
5426
  ossl_close,               /* close_one */
5427
  ossl_close_all,           /* close_all */
5428
  ossl_set_engine,          /* set_engine or provider */
5429
  ossl_set_engine_default,  /* set_engine_default */
5430
  ossl_engines_list,        /* engines_list */
5431
  ossl_sha256sum,           /* sha256sum */
5432
  ossl_recv,                /* recv decrypted data */
5433
  ossl_send,                /* send data to encrypt */
5434
  ossl_get_channel_binding  /* get_channel_binding */
5435
};
5436
5437
#endif /* USE_OPENSSL */