Coverage Report

Created: 2026-10-15 06:19

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