Coverage Report

Created: 2026-07-30 07:03

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