Coverage Report

Created: 2026-09-01 06:58

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