Coverage Report

Created: 2025-12-10 07:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/node/src/crypto/crypto_context.cc
Line
Count
Source
1
#include "crypto/crypto_context.h"
2
#include "base_object-inl.h"
3
#include "crypto/crypto_bio.h"
4
#include "crypto/crypto_common.h"
5
#include "crypto/crypto_util.h"
6
#include "env-inl.h"
7
#include "memory_tracker-inl.h"
8
#include "ncrypto.h"
9
#include "node.h"
10
#include "node_buffer.h"
11
#include "node_options.h"
12
#include "util.h"
13
#include "v8.h"
14
15
#include <openssl/x509.h>
16
#include <openssl/pkcs12.h>
17
#include <openssl/rand.h>
18
#ifndef OPENSSL_NO_ENGINE
19
#include <openssl/engine.h>
20
#endif  // !OPENSSL_NO_ENGINE
21
#ifdef __APPLE__
22
#include <Security/Security.h>
23
#endif
24
25
#ifdef _WIN32
26
#include <Windows.h>
27
#include <wincrypt.h>
28
#endif
29
30
#include <set>
31
32
namespace node {
33
34
using ncrypto::BignumPointer;
35
using ncrypto::BIOPointer;
36
using ncrypto::Cipher;
37
using ncrypto::ClearErrorOnReturn;
38
using ncrypto::CryptoErrorList;
39
using ncrypto::DHPointer;
40
using ncrypto::Digest;
41
#ifndef OPENSSL_NO_ENGINE
42
using ncrypto::EnginePointer;
43
#endif  // !OPENSSL_NO_ENGINE
44
using ncrypto::EVPKeyPointer;
45
using ncrypto::MarkPopErrorOnReturn;
46
using ncrypto::SSLPointer;
47
using ncrypto::StackOfX509;
48
using ncrypto::X509Pointer;
49
using ncrypto::X509View;
50
using v8::Array;
51
using v8::ArrayBufferView;
52
using v8::Boolean;
53
using v8::Context;
54
using v8::DontDelete;
55
using v8::EscapableHandleScope;
56
using v8::Exception;
57
using v8::External;
58
using v8::FunctionCallbackInfo;
59
using v8::FunctionTemplate;
60
using v8::HandleScope;
61
using v8::Int32;
62
using v8::Integer;
63
using v8::Isolate;
64
using v8::JustVoid;
65
using v8::Local;
66
using v8::LocalVector;
67
using v8::Maybe;
68
using v8::MaybeLocal;
69
using v8::Nothing;
70
using v8::Object;
71
using v8::PropertyAttribute;
72
using v8::ReadOnly;
73
using v8::Signature;
74
using v8::String;
75
using v8::Value;
76
77
namespace crypto {
78
static const char* const root_certs[] = {
79
#include "node_root_certs.h"  // NOLINT(build/include_order)
80
};
81
82
static std::string extra_root_certs_file;  // NOLINT(runtime/string)
83
84
static std::atomic<bool> has_cached_bundled_root_certs{false};
85
static std::atomic<bool> has_cached_system_root_certs{false};
86
static std::atomic<bool> has_cached_extra_root_certs{false};
87
88
// Used for sets of X509.
89
struct X509Less {
90
0
  bool operator()(const X509* lhs, const X509* rhs) const noexcept {
91
0
    return X509_cmp(const_cast<X509*>(lhs), const_cast<X509*>(rhs)) < 0;
92
0
  }
93
};
94
using X509Set = std::set<X509*, X509Less>;
95
96
// Per-thread root cert store. See NewRootCertStore() on what it contains.
97
static thread_local X509_STORE* root_cert_store = nullptr;
98
// If the user calls tls.setDefaultCACertificates() this will be used
99
// to hold the user-provided certificates, the root_cert_store and any new
100
// copy generated by NewRootCertStore() will then contain the certificates
101
// from this set.
102
static thread_local std::unique_ptr<X509Set> root_certs_from_users;
103
104
0
X509_STORE* GetOrCreateRootCertStore() {
105
0
  if (root_cert_store != nullptr) {
106
0
    return root_cert_store;
107
0
  }
108
0
  root_cert_store = NewRootCertStore();
109
0
  return root_cert_store;
110
0
}
111
112
// Takes a string or buffer and loads it into a BIO.
113
// Caller responsible for BIO_free_all-ing the returned object.
114
0
BIOPointer LoadBIO(Environment* env, Local<Value> v) {
115
0
  if (v->IsString() || v->IsArrayBufferView()) {
116
0
    auto bio = BIOPointer::NewSecMem();
117
0
    if (!bio) return {};
118
0
    ByteSource bsrc = ByteSource::FromStringOrBuffer(env, v);
119
0
    if (bsrc.size() > INT_MAX) return {};
120
0
    int written = BIOPointer::Write(
121
0
        &bio, std::string_view(bsrc.data<char>(), bsrc.size()));
122
0
    if (written < 0) return {};
123
0
    if (static_cast<size_t>(written) != bsrc.size()) return {};
124
0
    return bio;
125
0
  }
126
0
  return {};
127
0
}
128
129
namespace {
130
int SSL_CTX_use_certificate_chain(SSL_CTX* ctx,
131
                                  X509Pointer&& x,
132
                                  STACK_OF(X509)* extra_certs,
133
                                  X509Pointer* cert,
134
0
                                  X509Pointer* issuer_) {
135
0
  CHECK(!*issuer_);
136
0
  CHECK(!*cert);
137
0
  X509* issuer = nullptr;
138
139
0
  int ret = SSL_CTX_use_certificate(ctx, x.get());
140
141
0
  if (ret) {
142
    // If we could set up our certificate, now proceed to
143
    // the CA certificates.
144
0
    SSL_CTX_clear_extra_chain_certs(ctx);
145
146
0
    for (int i = 0; i < sk_X509_num(extra_certs); i++) {
147
0
      X509* ca = sk_X509_value(extra_certs, i);
148
149
      // NOTE: Increments reference count on `ca`
150
0
      if (!SSL_CTX_add1_chain_cert(ctx, ca)) {
151
0
        ret = 0;
152
0
        issuer = nullptr;
153
0
        break;
154
0
      }
155
      // Note that we must not free r if it was successfully
156
      // added to the chain (while we must free the main
157
      // certificate, since its reference count is increased
158
      // by SSL_CTX_use_certificate).
159
160
      // Find issuer
161
0
      if (issuer != nullptr || X509_check_issued(ca, x.get()) != X509_V_OK)
162
0
        continue;
163
164
0
      issuer = ca;
165
0
    }
166
0
  }
167
168
  // Try getting issuer from a cert store
169
0
  if (ret) {
170
0
    if (issuer == nullptr) {
171
      // TODO(tniessen): SSL_CTX_get_issuer does not allow the caller to
172
      // distinguish between a failed operation and an empty result. Fix that
173
      // and then handle the potential error properly here (set ret to 0).
174
0
      *issuer_ = X509Pointer::IssuerFrom(ctx, x.view());
175
      // NOTE: get_cert_store doesn't increment reference count,
176
      // no need to free `store`
177
0
    } else {
178
      // Increment issuer reference count
179
0
      issuer_->reset(X509_dup(issuer));
180
0
      if (!*issuer_) {
181
0
        ret = 0;
182
0
      }
183
0
    }
184
0
  }
185
186
0
  if (ret && x != nullptr) {
187
0
    cert->reset(X509_dup(x.get()));
188
0
    if (!*cert)
189
0
      ret = 0;
190
0
  }
191
0
  return ret;
192
0
}
193
194
}  // namespace
195
196
// Read a file that contains our certificate in "PEM" format,
197
// possibly followed by a sequence of CA certificates that should be
198
// sent to the peer in the Certificate message.
199
//
200
// Taken from OpenSSL - edited for style.
201
int SSL_CTX_use_certificate_chain(SSL_CTX* ctx,
202
                                  BIOPointer&& in,
203
                                  X509Pointer* cert,
204
0
                                  X509Pointer* issuer) {
205
  // Just to ensure that `ERR_peek_last_error` below will return only errors
206
  // that we are interested in
207
0
  ERR_clear_error();
208
209
0
  X509Pointer x(
210
0
      PEM_read_bio_X509_AUX(in.get(), nullptr, NoPasswordCallback, nullptr));
211
212
0
  if (!x)
213
0
    return 0;
214
215
0
  unsigned long err = 0;  // NOLINT(runtime/int)
216
217
0
  StackOfX509 extra_certs(sk_X509_new_null());
218
0
  if (!extra_certs)
219
0
    return 0;
220
221
0
  while (X509Pointer extra {PEM_read_bio_X509(in.get(),
222
0
                                    nullptr,
223
0
                                    NoPasswordCallback,
224
0
                                    nullptr)}) {
225
0
    if (sk_X509_push(extra_certs.get(), extra.get())) {
226
0
      extra.release();
227
0
      continue;
228
0
    }
229
230
0
    return 0;
231
0
  }
232
233
  // When the while loop ends, it's usually just EOF.
234
0
  err = ERR_peek_last_error();
235
0
  if (ERR_GET_LIB(err) == ERR_LIB_PEM &&
236
0
      ERR_GET_REASON(err) == PEM_R_NO_START_LINE) {
237
0
    ERR_clear_error();
238
0
  } else {
239
    // some real error
240
0
    return 0;
241
0
  }
242
243
0
  return SSL_CTX_use_certificate_chain(ctx,
244
0
                                       std::move(x),
245
0
                                       extra_certs.get(),
246
0
                                       cert,
247
0
                                       issuer);
248
0
}
249
250
static unsigned long LoadCertsFromBIO(  // NOLINT(runtime/int)
251
    std::vector<X509*>* certs,
252
0
    BIOPointer bio) {
253
0
  MarkPopErrorOnReturn mark_pop_error_on_return;
254
255
0
  while (X509* x509 = PEM_read_bio_X509(
256
0
             bio.get(), nullptr, NoPasswordCallback, nullptr)) {
257
0
    certs->push_back(x509);
258
0
  }
259
260
0
  unsigned long err = ERR_peek_last_error();  // NOLINT(runtime/int)
261
  // Ignore error if its EOF/no start line found.
262
0
  if (ERR_GET_LIB(err) == ERR_LIB_PEM &&
263
0
      ERR_GET_REASON(err) == PEM_R_NO_START_LINE) {
264
0
    return 0;
265
0
  } else {
266
0
    return err;
267
0
  }
268
0
}
269
270
static unsigned long LoadCertsFromFile(  // NOLINT(runtime/int)
271
    std::vector<X509*>* certs,
272
0
    const char* file) {
273
0
  MarkPopErrorOnReturn mark_pop_error_on_return;
274
275
0
  auto bio = BIOPointer::NewFile(file, "r");
276
0
  if (!bio) return ERR_get_error();
277
278
0
  return LoadCertsFromBIO(certs, std::move(bio));
279
0
}
280
281
// Indicates the trust status of a certificate.
282
enum class TrustStatus {
283
  // Trust status is unknown / uninitialized.
284
  UNKNOWN,
285
  // Certificate inherits trust value from its issuer. If the certificate is the
286
  // root of the chain, this implies distrust.
287
  UNSPECIFIED,
288
  // Certificate is a trust anchor.
289
  TRUSTED,
290
  // Certificate is blocked / explicitly distrusted.
291
  DISTRUSTED
292
};
293
294
0
bool isSelfIssued(X509* cert) {
295
0
  auto subject = X509_get_subject_name(cert);
296
0
  auto issuer = X509_get_issuer_name(cert);
297
298
0
  return X509_NAME_cmp(subject, issuer) == 0;
299
0
}
300
301
// The following code is loosely based on
302
// https://github.com/chromium/chromium/blob/54bd8e3/net/cert/internal/trust_store_mac.cc
303
// and
304
// https://github.com/chromium/chromium/blob/0192587/net/cert/internal/trust_store_win.cc
305
// Copyright 2015 The Chromium Authors
306
// Licensed under a BSD-style license
307
// See https://chromium.googlesource.com/chromium/src/+/HEAD/LICENSE for
308
// details.
309
#ifdef __APPLE__
310
TrustStatus IsTrustDictionaryTrustedForPolicy(CFDictionaryRef trust_dict,
311
                                              bool is_self_issued) {
312
  // Trust settings may be scoped to a single application
313
  // skip as this is not supported
314
  if (CFDictionaryContainsKey(trust_dict, kSecTrustSettingsApplication)) {
315
    return TrustStatus::UNSPECIFIED;
316
  }
317
318
  // Trust settings may be scoped using policy-specific constraints. For
319
  // example, SSL trust settings might be scoped to a single hostname, or EAP
320
  // settings specific to a particular WiFi network.
321
  // As this is not presently supported, skip any policy-specific trust
322
  // settings.
323
  if (CFDictionaryContainsKey(trust_dict, kSecTrustSettingsPolicyString)) {
324
    return TrustStatus::UNSPECIFIED;
325
  }
326
327
  // If the trust settings are scoped to a specific policy (via
328
  // kSecTrustSettingsPolicy), ensure that the policy is the same policy as
329
  // |kSecPolicyAppleSSL|. If there is no kSecTrustSettingsPolicy key, it's
330
  // considered a match for all policies.
331
  if (CFDictionaryContainsKey(trust_dict, kSecTrustSettingsPolicy)) {
332
    SecPolicyRef policy_ref = reinterpret_cast<SecPolicyRef>(const_cast<void*>(
333
        CFDictionaryGetValue(trust_dict, kSecTrustSettingsPolicy)));
334
335
    if (!policy_ref) {
336
      return TrustStatus::UNSPECIFIED;
337
    }
338
339
    CFDictionaryRef policy_dict(SecPolicyCopyProperties(policy_ref));
340
341
    // kSecPolicyOid is guaranteed to be present in the policy dictionary.
342
    CFStringRef policy_oid = reinterpret_cast<CFStringRef>(
343
        const_cast<void*>(CFDictionaryGetValue(policy_dict, kSecPolicyOid)));
344
345
    if (!CFEqual(policy_oid, kSecPolicyAppleSSL)) {
346
      return TrustStatus::UNSPECIFIED;
347
    }
348
  }
349
350
  int trust_settings_result = kSecTrustSettingsResultTrustRoot;
351
  if (CFDictionaryContainsKey(trust_dict, kSecTrustSettingsResult)) {
352
    CFNumberRef trust_settings_result_ref =
353
        reinterpret_cast<CFNumberRef>(const_cast<void*>(
354
            CFDictionaryGetValue(trust_dict, kSecTrustSettingsResult)));
355
356
    if (!trust_settings_result_ref ||
357
        !CFNumberGetValue(trust_settings_result_ref,
358
                          kCFNumberIntType,
359
                          &trust_settings_result)) {
360
      return TrustStatus::UNSPECIFIED;
361
    }
362
363
    if (trust_settings_result == kSecTrustSettingsResultDeny) {
364
      return TrustStatus::DISTRUSTED;
365
    }
366
367
    // This is a bit of a hack: if the cert is self-issued allow either
368
    // kSecTrustSettingsResultTrustRoot or kSecTrustSettingsResultTrustAsRoot on
369
    // the basis that SecTrustSetTrustSettings should not allow creating an
370
    // invalid trust record in the first place. (The spec is that
371
    // kSecTrustSettingsResultTrustRoot can only be applied to root(self-signed)
372
    // certs and kSecTrustSettingsResultTrustAsRoot is used for other certs.)
373
    // This hack avoids having to check the signature on the cert which is slow
374
    // if using the platform APIs, and may require supporting MD5 signature
375
    // algorithms on some older OSX versions or locally added roots, which is
376
    // undesirable in the built-in signature verifier.
377
    if (is_self_issued) {
378
      return trust_settings_result == kSecTrustSettingsResultTrustRoot ||
379
                     trust_settings_result == kSecTrustSettingsResultTrustAsRoot
380
                 ? TrustStatus::TRUSTED
381
                 : TrustStatus::UNSPECIFIED;
382
    }
383
384
    // kSecTrustSettingsResultTrustAsRoot can only be applied to non-root certs.
385
    return (trust_settings_result == kSecTrustSettingsResultTrustAsRoot)
386
               ? TrustStatus::TRUSTED
387
               : TrustStatus::UNSPECIFIED;
388
  }
389
390
  return TrustStatus::UNSPECIFIED;
391
}
392
393
TrustStatus IsTrustSettingsTrustedForPolicy(CFArrayRef trust_settings,
394
                                            bool is_self_issued) {
395
  // The trust_settings parameter can return a valid but empty CFArrayRef.
396
  // This empty trust-settings array means “always trust this certificate”
397
  // with an overall trust setting for the certificate of
398
  // kSecTrustSettingsResultTrustRoot
399
  if (CFArrayGetCount(trust_settings) == 0) {
400
    return is_self_issued ? TrustStatus::TRUSTED : TrustStatus::UNSPECIFIED;
401
  }
402
403
  for (CFIndex i = 0; i < CFArrayGetCount(trust_settings); ++i) {
404
    CFDictionaryRef trust_dict = reinterpret_cast<CFDictionaryRef>(
405
        const_cast<void*>(CFArrayGetValueAtIndex(trust_settings, i)));
406
407
    TrustStatus trust =
408
        IsTrustDictionaryTrustedForPolicy(trust_dict, is_self_issued);
409
410
    if (trust == TrustStatus::DISTRUSTED || trust == TrustStatus::TRUSTED) {
411
      return trust;
412
    }
413
  }
414
  return TrustStatus::UNSPECIFIED;
415
}
416
417
bool IsCertificateTrustValid(SecCertificateRef ref) {
418
  SecTrustRef sec_trust = nullptr;
419
  CFMutableArrayRef subj_certs =
420
      CFArrayCreateMutable(nullptr, 1, &kCFTypeArrayCallBacks);
421
  CFArraySetValueAtIndex(subj_certs, 0, ref);
422
423
  SecPolicyRef policy = SecPolicyCreateSSL(false, nullptr);
424
  OSStatus ortn =
425
      SecTrustCreateWithCertificates(subj_certs, policy, &sec_trust);
426
  bool result = false;
427
  if (ortn) {
428
    /* should never happen */
429
  } else {
430
    result = SecTrustEvaluateWithError(sec_trust, nullptr);
431
  }
432
433
  if (policy) {
434
    CFRelease(policy);
435
  }
436
  if (sec_trust) {
437
    CFRelease(sec_trust);
438
  }
439
  if (subj_certs) {
440
    CFRelease(subj_certs);
441
  }
442
  return result;
443
}
444
445
bool IsCertificateTrustedForPolicy(X509* cert, SecCertificateRef ref) {
446
  OSStatus err;
447
448
  bool trust_evaluated = false;
449
  bool is_self_issued = isSelfIssued(cert);
450
451
  // Evaluate user trust domain, then admin. User settings can override
452
  // admin (and both override the system domain, but we don't check that).
453
  for (const auto& trust_domain :
454
       {kSecTrustSettingsDomainUser, kSecTrustSettingsDomainAdmin}) {
455
    CFArrayRef trust_settings = nullptr;
456
    err = SecTrustSettingsCopyTrustSettings(ref, trust_domain, &trust_settings);
457
458
    if (err != errSecSuccess && err != errSecItemNotFound) {
459
      fprintf(stderr,
460
              "ERROR: failed to copy trust settings of system certificate%d\n",
461
              err);
462
      continue;
463
    }
464
465
    if (err == errSecSuccess && trust_settings != nullptr) {
466
      TrustStatus result =
467
          IsTrustSettingsTrustedForPolicy(trust_settings, is_self_issued);
468
      if (result != TrustStatus::UNSPECIFIED) {
469
        CFRelease(trust_settings);
470
        return result == TrustStatus::TRUSTED;
471
      }
472
    }
473
474
    // An empty trust settings array isn’t the same as no trust settings,
475
    // where the trust_settings parameter returns NULL.
476
    // No trust-settings array means
477
    // “this certificate must be verifiable using a known trusted certificate”.
478
    if (trust_settings == nullptr && !trust_evaluated) {
479
      bool result = IsCertificateTrustValid(ref);
480
      if (result) {
481
        return true;
482
      }
483
      // no point re-evaluating this in the admin domain
484
      trust_evaluated = true;
485
    } else if (trust_settings) {
486
      CFRelease(trust_settings);
487
    }
488
  }
489
  return false;
490
}
491
492
void ReadMacOSKeychainCertificates(
493
    std::vector<X509*>* system_root_certificates_X509) {
494
  CFTypeRef search_keys[] = {kSecClass, kSecMatchLimit, kSecReturnRef};
495
  CFTypeRef search_values[] = {
496
      kSecClassCertificate, kSecMatchLimitAll, kCFBooleanTrue};
497
  CFDictionaryRef search = CFDictionaryCreate(kCFAllocatorDefault,
498
                                              search_keys,
499
                                              search_values,
500
                                              3,
501
                                              &kCFTypeDictionaryKeyCallBacks,
502
                                              &kCFTypeDictionaryValueCallBacks);
503
504
  CFArrayRef curr_anchors = nullptr;
505
  OSStatus ortn =
506
      SecItemCopyMatching(search, reinterpret_cast<CFTypeRef*>(&curr_anchors));
507
  CFRelease(search);
508
509
  if (ortn) {
510
    per_process::Debug(DebugCategory::CRYPTO,
511
                       "Cannot read certificates from system because "
512
                       "SecItemCopyMatching failed %d\n",
513
                       ortn);
514
    return;
515
  }
516
517
  CFIndex count = CFArrayGetCount(curr_anchors);
518
519
  for (int i = 0; i < count; ++i) {
520
    SecCertificateRef cert_ref = reinterpret_cast<SecCertificateRef>(
521
        const_cast<void*>(CFArrayGetValueAtIndex(curr_anchors, i)));
522
523
    CFDataRef der_data = SecCertificateCopyData(cert_ref);
524
    if (!der_data) {
525
      per_process::Debug(DebugCategory::CRYPTO,
526
                         "Skipping read of a system certificate "
527
                         "because SecCertificateCopyData failed\n");
528
      continue;
529
    }
530
    auto data_buffer_pointer = CFDataGetBytePtr(der_data);
531
532
    X509* cert =
533
        d2i_X509(nullptr, &data_buffer_pointer, CFDataGetLength(der_data));
534
    CFRelease(der_data);
535
536
    if (cert == nullptr) {
537
      per_process::Debug(DebugCategory::CRYPTO,
538
                         "Skipping read of a system certificate "
539
                         "because decoding failed\n");
540
      continue;
541
    }
542
543
    bool is_valid = IsCertificateTrustedForPolicy(cert, cert_ref);
544
    if (is_valid) {
545
      system_root_certificates_X509->emplace_back(cert);
546
    } else {
547
      X509_free(cert);
548
    }
549
  }
550
  CFRelease(curr_anchors);
551
}
552
#endif  // __APPLE__
553
554
#ifdef _WIN32
555
556
// Returns true if the cert can be used for server authentication, based on
557
// certificate properties.
558
//
559
// While there are a variety of certificate properties that can affect how
560
// trust is computed, the main property is CERT_ENHKEY_USAGE_PROP_ID, which
561
// is intersected with the certificate's EKU extension (if present).
562
// The intersection is documented in the Remarks section of
563
// CertGetEnhancedKeyUsage, and is as follows:
564
// - No EKU property, and no EKU extension = Trusted for all purpose
565
// - Either an EKU property, or EKU extension, but not both = Trusted only
566
//   for the listed purposes
567
// - Both an EKU property and an EKU extension = Trusted for the set
568
//   intersection of the listed purposes
569
// CertGetEnhancedKeyUsage handles this logic, and if an empty set is
570
// returned, the distinction between the first and third case can be
571
// determined by GetLastError() returning CRYPT_E_NOT_FOUND.
572
//
573
// See:
574
// https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-certgetenhancedkeyusage
575
//
576
// If we run into any errors reading the certificate properties, we fail
577
// closed.
578
bool IsCertTrustedForServerAuth(PCCERT_CONTEXT cert) {
579
  DWORD usage_size = 0;
580
581
  if (!CertGetEnhancedKeyUsage(cert, 0, nullptr, &usage_size)) {
582
    return false;
583
  }
584
585
  std::vector<BYTE> usage_bytes(usage_size);
586
  CERT_ENHKEY_USAGE* usage =
587
      reinterpret_cast<CERT_ENHKEY_USAGE*>(usage_bytes.data());
588
  if (!CertGetEnhancedKeyUsage(cert, 0, usage, &usage_size)) {
589
    return false;
590
  }
591
592
  if (usage->cUsageIdentifier == 0) {
593
    // check GetLastError
594
    HRESULT error_code = GetLastError();
595
596
    switch (error_code) {
597
      case CRYPT_E_NOT_FOUND:
598
        return true;
599
      case S_OK:
600
        return false;
601
      default:
602
        return false;
603
    }
604
  }
605
606
  // SAFETY: `usage->rgpszUsageIdentifier` is an array of LPSTR (pointer to null
607
  // terminated string) of length `usage->cUsageIdentifier`.
608
  for (DWORD i = 0; i < usage->cUsageIdentifier; ++i) {
609
    std::string_view eku(usage->rgpszUsageIdentifier[i]);
610
    if ((eku == szOID_PKIX_KP_SERVER_AUTH) ||
611
        (eku == szOID_ANY_ENHANCED_KEY_USAGE)) {
612
      return true;
613
    }
614
  }
615
616
  return false;
617
}
618
619
void GatherCertsForLocation(std::vector<X509*>* vector,
620
                            DWORD location,
621
                            LPCWSTR store_name) {
622
  if (!(location == CERT_SYSTEM_STORE_LOCAL_MACHINE ||
623
        location == CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY ||
624
        location == CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE ||
625
        location == CERT_SYSTEM_STORE_CURRENT_USER ||
626
        location == CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY)) {
627
    return;
628
  }
629
630
  DWORD flags =
631
      location | CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG;
632
633
  HCERTSTORE opened_store(
634
      CertOpenStore(CERT_STORE_PROV_SYSTEM,
635
                    0,
636
                    // The Windows API only accepts NULL for hCryptProv.
637
                    NULL, /* NOLINT (readability/null_usage) */
638
                    flags,
639
                    store_name));
640
  if (!opened_store) {
641
    return;
642
  }
643
644
  auto cleanup = OnScopeLeave(
645
      [opened_store]() { CHECK_EQ(CertCloseStore(opened_store, 0), TRUE); });
646
647
  PCCERT_CONTEXT cert_from_store = nullptr;
648
  while ((cert_from_store = CertEnumCertificatesInStore(
649
              opened_store, cert_from_store)) != nullptr) {
650
    if (!IsCertTrustedForServerAuth(cert_from_store)) {
651
      continue;
652
    }
653
    const unsigned char* cert_data =
654
        reinterpret_cast<const unsigned char*>(cert_from_store->pbCertEncoded);
655
    const size_t cert_size = cert_from_store->cbCertEncoded;
656
657
    X509* x509 = d2i_X509(nullptr, &cert_data, cert_size);
658
    if (x509 == nullptr) {
659
      per_process::Debug(DebugCategory::CRYPTO,
660
                         "Skipping read of a system certificate "
661
                         "because decoding failed\n");
662
    } else {
663
      vector->emplace_back(x509);
664
    }
665
  }
666
}
667
668
void ReadWindowsCertificates(
669
    std::vector<X509*>* system_root_certificates_X509) {
670
  // TODO(joyeecheung): match Chromium's policy, collect more certificates
671
  // from user-added CAs and support disallowed (revoked) certificates.
672
673
  // Grab the user-added roots.
674
  GatherCertsForLocation(
675
      system_root_certificates_X509, CERT_SYSTEM_STORE_LOCAL_MACHINE, L"ROOT");
676
  GatherCertsForLocation(system_root_certificates_X509,
677
                         CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY,
678
                         L"ROOT");
679
  GatherCertsForLocation(system_root_certificates_X509,
680
                         CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE,
681
                         L"ROOT");
682
  GatherCertsForLocation(
683
      system_root_certificates_X509, CERT_SYSTEM_STORE_CURRENT_USER, L"ROOT");
684
  GatherCertsForLocation(system_root_certificates_X509,
685
                         CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY,
686
                         L"ROOT");
687
688
  // Grab the intermediate certs
689
  GatherCertsForLocation(
690
      system_root_certificates_X509, CERT_SYSTEM_STORE_LOCAL_MACHINE, L"CA");
691
  GatherCertsForLocation(system_root_certificates_X509,
692
                         CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY,
693
                         L"CA");
694
  GatherCertsForLocation(system_root_certificates_X509,
695
                         CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE,
696
                         L"CA");
697
  GatherCertsForLocation(
698
      system_root_certificates_X509, CERT_SYSTEM_STORE_CURRENT_USER, L"CA");
699
  GatherCertsForLocation(system_root_certificates_X509,
700
                         CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY,
701
                         L"CA");
702
703
  // Grab the user-added trusted server certs. Trusted end-entity certs are
704
  // only allowed for server auth in the "local machine" store, but not in the
705
  // "current user" store.
706
  GatherCertsForLocation(system_root_certificates_X509,
707
                         CERT_SYSTEM_STORE_LOCAL_MACHINE,
708
                         L"TrustedPeople");
709
  GatherCertsForLocation(system_root_certificates_X509,
710
                         CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY,
711
                         L"TrustedPeople");
712
  GatherCertsForLocation(system_root_certificates_X509,
713
                         CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE,
714
                         L"TrustedPeople");
715
}
716
#endif
717
718
static void LoadCertsFromDir(std::vector<X509*>* certs,
719
0
                             std::string_view cert_dir) {
720
0
  uv_fs_t dir_req;
721
0
  auto cleanup = OnScopeLeave([&dir_req]() { uv_fs_req_cleanup(&dir_req); });
722
0
  int err = uv_fs_scandir(nullptr, &dir_req, cert_dir.data(), 0, nullptr);
723
0
  if (err < 0) {
724
0
    fprintf(stderr,
725
0
            "Cannot open directory %s to load OpenSSL certificates.\n",
726
0
            cert_dir.data());
727
0
    return;
728
0
  }
729
730
0
  for (;;) {
731
0
    uv_dirent_t ent;
732
733
0
    int r = uv_fs_scandir_next(&dir_req, &ent);
734
0
    if (r == UV_EOF) {
735
0
      break;
736
0
    }
737
0
    if (r < 0) {
738
0
      char message[64];
739
0
      uv_strerror_r(r, message, sizeof(message));
740
0
      fprintf(stderr,
741
0
              "Cannot scan directory %s to load OpenSSL certificates.\n",
742
0
              cert_dir.data());
743
0
      return;
744
0
    }
745
746
0
    uv_fs_t stats_req;
747
0
    std::string file_path = std::string(cert_dir) + "/" + ent.name;
748
0
    int stats_r = uv_fs_stat(nullptr, &stats_req, file_path.c_str(), nullptr);
749
0
    if (stats_r == 0 &&
750
0
        (static_cast<uv_stat_t*>(stats_req.ptr)->st_mode & S_IFREG)) {
751
0
      LoadCertsFromFile(certs, file_path.c_str());
752
0
    }
753
0
    uv_fs_req_cleanup(&stats_req);
754
0
  }
755
0
}
756
757
// Loads CA certificates from the default certificate paths respected by
758
// OpenSSL.
759
0
void GetOpenSSLSystemCertificates(std::vector<X509*>* system_store_certs) {
760
0
  std::string cert_file;
761
  // While configurable when OpenSSL is built, this is usually SSL_CERT_FILE.
762
0
  if (!credentials::SafeGetenv(X509_get_default_cert_file_env(), &cert_file)) {
763
    // This is usually /etc/ssl/cert.pem if we are using the OpenSSL statically
764
    // linked and built with default configurations.
765
0
    cert_file = X509_get_default_cert_file();
766
0
  }
767
768
0
  std::string cert_dir;
769
  // While configurable when OpenSSL is built, this is usually SSL_CERT_DIR.
770
0
  if (!credentials::SafeGetenv(X509_get_default_cert_dir_env(), &cert_dir)) {
771
    // This is usually /etc/ssl/certs if we are using the OpenSSL statically
772
    // linked and built with default configurations.
773
0
    cert_dir = X509_get_default_cert_dir();
774
0
  }
775
776
0
  if (!cert_file.empty()) {
777
0
    LoadCertsFromFile(system_store_certs, cert_file.c_str());
778
0
  }
779
780
0
  if (!cert_dir.empty()) {
781
0
    LoadCertsFromDir(system_store_certs, cert_dir.c_str());
782
0
  }
783
0
}
784
785
0
static std::vector<X509*> InitializeBundledRootCertificates() {
786
  // Read the bundled certificates in node_root_certs.h into
787
  // bundled_root_certs_vector.
788
0
  std::vector<X509*> bundled_root_certs;
789
0
  size_t bundled_root_cert_count = arraysize(root_certs);
790
0
  bundled_root_certs.reserve(bundled_root_cert_count);
791
0
  for (size_t i = 0; i < bundled_root_cert_count; i++) {
792
0
    X509* x509 = PEM_read_bio_X509(
793
0
        NodeBIO::NewFixed(root_certs[i], strlen(root_certs[i])).get(),
794
0
        nullptr,  // no re-use of X509 structure
795
0
        NoPasswordCallback,
796
0
        nullptr);  // no callback data
797
798
    // Parse errors from the built-in roots are fatal.
799
0
    CHECK_NOT_NULL(x509);
800
801
0
    bundled_root_certs.push_back(x509);
802
0
  }
803
0
  return bundled_root_certs;
804
0
}
805
806
// TODO(joyeecheung): it is a bit excessive to do this PEM -> X509
807
// dance when we could've just pass everything around in binary. Change the
808
// root_certs to be embedded as DER so that we can save the serialization
809
// and deserialization.
810
0
static std::vector<X509*>& GetBundledRootCertificates() {
811
  // Use function-local static to guarantee thread safety.
812
0
  static std::vector<X509*> bundled_root_certs =
813
0
      InitializeBundledRootCertificates();
814
0
  has_cached_bundled_root_certs.store(true);
815
0
  return bundled_root_certs;
816
0
}
817
818
0
static std::vector<X509*> InitializeSystemStoreCertificates() {
819
0
  std::vector<X509*> system_store_certs;
820
#ifdef __APPLE__
821
  ReadMacOSKeychainCertificates(&system_store_certs);
822
#endif
823
#ifdef _WIN32
824
  ReadWindowsCertificates(&system_store_certs);
825
#endif
826
0
#if !defined(__APPLE__) && !defined(_WIN32)
827
0
  GetOpenSSLSystemCertificates(&system_store_certs);
828
0
#endif
829
0
  return system_store_certs;
830
0
}
831
832
0
static std::vector<X509*>& GetSystemStoreCACertificates() {
833
  // Use function-local static to guarantee thread safety.
834
0
  static std::vector<X509*> system_store_certs =
835
0
      InitializeSystemStoreCertificates();
836
0
  has_cached_system_root_certs.store(true);
837
0
  return system_store_certs;
838
0
}
839
840
0
static std::vector<X509*> InitializeExtraCACertificates() {
841
0
  std::vector<X509*> extra_certs;
842
0
  unsigned long err = LoadCertsFromFile(  // NOLINT(runtime/int)
843
0
      &extra_certs,
844
0
      extra_root_certs_file.c_str());
845
0
  if (err) {
846
0
    char buf[256];
847
0
    ERR_error_string_n(err, buf, sizeof(buf));
848
0
    fprintf(stderr,
849
0
            "Warning: Ignoring extra certs from `%s`, load failed: %s\n",
850
0
            extra_root_certs_file.c_str(),
851
0
            buf);
852
0
  }
853
0
  return extra_certs;
854
0
}
855
856
0
static std::vector<X509*>& GetExtraCACertificates() {
857
  // Use function-local static to guarantee thread safety.
858
0
  static std::vector<X509*> extra_certs = InitializeExtraCACertificates();
859
0
  has_cached_extra_root_certs.store(true);
860
0
  return extra_certs;
861
0
}
862
863
0
static void LoadCACertificates(void* data) {
864
0
  per_process::Debug(DebugCategory::CRYPTO,
865
0
                     "Started loading bundled root certificates off-thread\n");
866
0
  GetBundledRootCertificates();
867
868
0
  if (!extra_root_certs_file.empty()) {
869
0
    per_process::Debug(DebugCategory::CRYPTO,
870
0
                       "Started loading extra root certificates off-thread\n");
871
0
    GetExtraCACertificates();
872
0
  }
873
874
0
  {
875
0
    Mutex::ScopedLock cli_lock(node::per_process::cli_options_mutex);
876
0
    if (!per_process::cli_options->use_system_ca) {
877
0
      return;
878
0
    }
879
0
  }
880
881
0
  per_process::Debug(DebugCategory::CRYPTO,
882
0
                     "Started loading system root certificates off-thread\n");
883
0
  GetSystemStoreCACertificates();
884
0
}
885
886
static std::atomic<bool> tried_cert_loading_off_thread = false;
887
static std::atomic<bool> cert_loading_thread_started = false;
888
static Mutex start_cert_loading_thread_mutex;
889
static uv_thread_t cert_loading_thread;
890
891
void StartLoadingCertificatesOffThread(
892
0
    const FunctionCallbackInfo<Value>& args) {
893
  // Load the CA certificates eagerly off the main thread to avoid
894
  // blocking the main thread when the first TLS connection is made. We
895
  // don't need to wait for the thread to finish with code here, as
896
  // Get*CACertificates() functions has a function-local static and any
897
  // actual user of it will wait for that to complete initialization.
898
899
  // --use-openssl-ca is mutually exclusive with --use-bundled-ca and
900
  // --use-system-ca. If it's set, no need to optimize with off-thread
901
  // loading.
902
0
  {
903
0
    Mutex::ScopedLock cli_lock(node::per_process::cli_options_mutex);
904
0
    if (per_process::cli_options->ssl_openssl_cert_store) {
905
0
      return;
906
0
    }
907
0
  }
908
909
  // Only try to start the thread once. If it ever fails, we won't try again.
910
0
  if (tried_cert_loading_off_thread.load()) {
911
0
    return;
912
0
  }
913
0
  {
914
0
    Mutex::ScopedLock lock(start_cert_loading_thread_mutex);
915
    // Re-check under the lock.
916
0
    if (tried_cert_loading_off_thread.load()) {
917
0
      return;
918
0
    }
919
0
    tried_cert_loading_off_thread.store(true);
920
0
    int r = uv_thread_create(&cert_loading_thread, LoadCACertificates, nullptr);
921
0
    cert_loading_thread_started.store(r == 0);
922
0
    if (r != 0) {
923
0
      FPrintF(stderr,
924
0
              "Warning: Failed to load CA certificates off thread: %s\n",
925
0
              uv_strerror(r));
926
0
    }
927
0
  }
928
0
}
929
930
// Due to historical reasons the various options of CA certificates
931
// may invalid one another. The current rule is:
932
// 1. If the configure-time option --openssl-use-def-ca-store is NOT used
933
//    (default):
934
//    a. If the runtime option --use-openssl-ca is used, load the
935
//       CA certificates from the default locations respected by OpenSSL.
936
//    b. Otherwise, --use-bundled-ca is assumed to be the default, and we
937
//       use the bundled CA certificates.
938
// 2. If the configure-time option --openssl-use-def-ca-store IS used,
939
//    --use-openssl-ca is assumed to be the default, with the default
940
//    location set to the path specified by the configure-time option.
941
// 3. --use-openssl-ca and --use-bundled-ca are mutually exclusive.
942
// 4. --use-openssl-ca and --use-system-ca are mutually exclusive.
943
// 5. --use-bundled-ca and --use-system-ca can be used together.
944
//    The certificates can be combined.
945
// 6. Independent of all other flags, NODE_EXTRA_CA_CERTS always
946
//    adds extra certificates from the specified path, so it works
947
//    with all the other flags.
948
// 7. Certificates from --use-bundled-ca, --use-system-ca and
949
//    NODE_EXTRA_CA_CERTS are cached after first load. Certificates
950
//    from --use-system-ca are not cached and always reloaded from
951
//    disk.
952
// 8. If users have reset the root cert store by calling
953
//    tls.setDefaultCACertificates(), the store will be populated with
954
//    the certificates provided by users.
955
// TODO(joyeecheung): maybe these rules need a bit of consolidation?
956
0
X509_STORE* NewRootCertStore() {
957
0
  X509_STORE* store = X509_STORE_new();
958
0
  CHECK_NOT_NULL(store);
959
960
  // If the root cert store is already reset by users through
961
  // tls.setDefaultCACertificates(), just create a copy from the
962
  // user-provided certificates.
963
0
  if (root_certs_from_users != nullptr) {
964
0
    for (X509* cert : *root_certs_from_users) {
965
0
      CHECK_EQ(1, X509_STORE_add_cert(store, cert));
966
0
    }
967
0
    return store;
968
0
  }
969
970
0
#ifdef NODE_OPENSSL_SYSTEM_CERT_PATH
971
  if constexpr (sizeof(NODE_OPENSSL_SYSTEM_CERT_PATH) > 1) {
972
    ERR_set_mark();
973
    X509_STORE_load_locations(store, NODE_OPENSSL_SYSTEM_CERT_PATH, nullptr);
974
    ERR_pop_to_mark();
975
  }
976
0
#endif
977
978
0
  Mutex::ScopedLock cli_lock(node::per_process::cli_options_mutex);
979
0
  if (per_process::cli_options->ssl_openssl_cert_store) {
980
0
    CHECK_EQ(1, X509_STORE_set_default_paths(store));
981
0
  } else {
982
0
    for (X509* cert : GetBundledRootCertificates()) {
983
0
      CHECK_EQ(1, X509_STORE_add_cert(store, cert));
984
0
    }
985
0
    if (per_process::cli_options->use_system_ca) {
986
0
      for (X509* cert : GetSystemStoreCACertificates()) {
987
0
        CHECK_EQ(1, X509_STORE_add_cert(store, cert));
988
0
      }
989
0
    }
990
0
  }
991
992
0
  if (!extra_root_certs_file.empty()) {
993
0
    for (X509* cert : GetExtraCACertificates()) {
994
0
      CHECK_EQ(1, X509_STORE_add_cert(store, cert));
995
0
    }
996
0
  }
997
998
0
  return store;
999
0
}
1000
1001
0
void CleanupCachedRootCertificates() {
1002
0
  if (has_cached_bundled_root_certs.load()) {
1003
0
    for (X509* cert : GetBundledRootCertificates()) {
1004
0
      X509_free(cert);
1005
0
    }
1006
0
  }
1007
0
  if (has_cached_system_root_certs.load()) {
1008
0
    for (X509* cert : GetSystemStoreCACertificates()) {
1009
0
      X509_free(cert);
1010
0
    }
1011
0
  }
1012
1013
0
  if (has_cached_extra_root_certs.load()) {
1014
0
    for (X509* cert : GetExtraCACertificates()) {
1015
0
      X509_free(cert);
1016
0
    }
1017
0
  }
1018
1019
  // Serialize with starter to avoid the race window.
1020
0
  Mutex::ScopedLock lock(start_cert_loading_thread_mutex);
1021
0
  if (tried_cert_loading_off_thread.load() &&
1022
0
      cert_loading_thread_started.load()) {
1023
0
    uv_thread_join(&cert_loading_thread);
1024
0
  }
1025
0
}
1026
1027
0
void GetBundledRootCertificates(const FunctionCallbackInfo<Value>& args) {
1028
0
  Environment* env = Environment::GetCurrent(args);
1029
0
  Local<Value> result[arraysize(root_certs)];
1030
1031
0
  for (size_t i = 0; i < arraysize(root_certs); i++) {
1032
0
    if (!String::NewFromOneByte(
1033
0
            env->isolate(),
1034
0
            reinterpret_cast<const uint8_t*>(root_certs[i]))
1035
0
            .ToLocal(&result[i])) {
1036
0
      return;
1037
0
    }
1038
0
  }
1039
1040
0
  args.GetReturnValue().Set(
1041
0
      Array::New(env->isolate(), result, arraysize(root_certs)));
1042
0
}
1043
1044
bool ArrayOfStringsToX509s(Local<Context> context,
1045
                           Local<Array> cert_array,
1046
0
                           std::vector<X509*>* certs) {
1047
0
  ClearErrorOnReturn clear_error_on_return;
1048
0
  Isolate* isolate = Isolate::GetCurrent();
1049
0
  Environment* env = Environment::GetCurrent(context);
1050
0
  uint32_t array_length = cert_array->Length();
1051
1052
0
  std::vector<v8::Global<Value>> cert_items;
1053
0
  if (FromV8Array(context, cert_array, &cert_items).IsNothing()) {
1054
0
    return false;
1055
0
  }
1056
1057
0
  for (uint32_t i = 0; i < array_length; i++) {
1058
0
    Local<Value> cert_val = cert_items[i].Get(isolate);
1059
    // Parse the PEM certificate.
1060
0
    BIOPointer bio(LoadBIO(env, cert_val));
1061
0
    if (!bio) {
1062
0
      ThrowCryptoError(env, ERR_get_error(), "Failed to load certificate data");
1063
0
      return false;
1064
0
    }
1065
1066
    // Read all certificates from this PEM string
1067
0
    size_t start = certs->size();
1068
0
    auto err = LoadCertsFromBIO(certs, std::move(bio));
1069
0
    if (err != 0) {
1070
0
      size_t end = certs->size();
1071
      // Clean up any certificates we've already parsed upon failure.
1072
0
      for (size_t j = start; j < end; ++j) {
1073
0
        X509_free((*certs)[j]);
1074
0
      }
1075
0
      ThrowCryptoError(env, err, "Failed to parse certificate");
1076
0
      return false;
1077
0
    }
1078
0
  }
1079
1080
0
  return true;
1081
0
}
1082
1083
template <typename It>
1084
MaybeLocal<Array> X509sToArrayOfStrings(Environment* env,
1085
                                        It first,
1086
                                        It last,
1087
0
                                        size_t size) {
1088
0
  ClearErrorOnReturn clear_error_on_return;
1089
0
  EscapableHandleScope scope(env->isolate());
1090
1091
0
  LocalVector<Value> result(env->isolate(), size);
1092
0
  size_t i = 0;
1093
0
  for (It cur = first; cur != last; ++cur, ++i) {
1094
0
    X509View view(*cur);
1095
0
    auto pem_bio = view.toPEM();
1096
0
    if (!pem_bio) {
1097
0
      ThrowCryptoError(env, ERR_get_error(), "X509 to PEM conversion");
1098
0
      return MaybeLocal<Array>();
1099
0
    }
1100
1101
0
    char* pem_data = nullptr;
1102
0
    auto pem_size = BIO_get_mem_data(pem_bio.get(), &pem_data);
1103
0
    if (pem_size <= 0 || !pem_data) {
1104
0
      ThrowCryptoError(env, ERR_get_error(), "Reading PEM data");
1105
0
      return MaybeLocal<Array>();
1106
0
    }
1107
    // PEM is base64-encoded, so it must be one-byte.
1108
0
    if (!String::NewFromOneByte(env->isolate(),
1109
0
                                reinterpret_cast<uint8_t*>(pem_data),
1110
0
                                v8::NewStringType::kNormal,
1111
0
                                pem_size)
1112
0
             .ToLocal(&result[i])) {
1113
0
      return MaybeLocal<Array>();
1114
0
    }
1115
0
  }
1116
0
  return scope.Escape(Array::New(env->isolate(), result.data(), result.size()));
1117
0
}
Unexecuted instantiation: v8::MaybeLocal<v8::Array> node::crypto::X509sToArrayOfStrings<std::__1::__tree_const_iterator<x509_st*, std::__1::__tree_node<x509_st*, void*>*, long> >(node::Environment*, std::__1::__tree_const_iterator<x509_st*, std::__1::__tree_node<x509_st*, void*>*, long>, std::__1::__tree_const_iterator<x509_st*, std::__1::__tree_node<x509_st*, void*>*, long>, unsigned long)
Unexecuted instantiation: v8::MaybeLocal<v8::Array> node::crypto::X509sToArrayOfStrings<std::__1::__wrap_iter<x509_st**> >(node::Environment*, std::__1::__wrap_iter<x509_st**>, std::__1::__wrap_iter<x509_st**>, unsigned long)
1118
1119
0
void GetUserRootCertificates(const FunctionCallbackInfo<Value>& args) {
1120
0
  Environment* env = Environment::GetCurrent(args);
1121
0
  CHECK_NOT_NULL(root_certs_from_users);
1122
0
  Local<Array> results;
1123
0
  if (X509sToArrayOfStrings(env,
1124
0
                            root_certs_from_users->begin(),
1125
0
                            root_certs_from_users->end(),
1126
0
                            root_certs_from_users->size())
1127
0
          .ToLocal(&results)) {
1128
0
    args.GetReturnValue().Set(results);
1129
0
  }
1130
0
}
1131
1132
0
void ResetRootCertStore(const FunctionCallbackInfo<Value>& args) {
1133
0
  Local<Context> context = args.GetIsolate()->GetCurrentContext();
1134
0
  CHECK(args[0]->IsArray());
1135
0
  Local<Array> cert_array = args[0].As<Array>();
1136
1137
0
  if (cert_array->Length() == 0) {
1138
    // If the array is empty, just clear the user certs and reset the store.
1139
0
    if (root_cert_store != nullptr) {
1140
0
      X509_STORE_free(root_cert_store);
1141
0
      root_cert_store = nullptr;
1142
0
    }
1143
1144
    // Free any existing certificates in the old set.
1145
0
    if (root_certs_from_users != nullptr) {
1146
0
      for (X509* cert : *root_certs_from_users) {
1147
0
        X509_free(cert);
1148
0
      }
1149
0
    }
1150
0
    root_certs_from_users = std::make_unique<X509Set>();
1151
0
    return;
1152
0
  }
1153
1154
  // Parse certificates from the array
1155
0
  std::unique_ptr<std::vector<X509*>> certs =
1156
0
      std::make_unique<std::vector<X509*>>();
1157
0
  if (!ArrayOfStringsToX509s(context, cert_array, certs.get())) {
1158
    // Error already thrown by ArrayOfStringsToX509s
1159
0
    return;
1160
0
  }
1161
1162
0
  if (certs->empty()) {
1163
0
    Environment* env = Environment::GetCurrent(context);
1164
0
    return THROW_ERR_CRYPTO_OPERATION_FAILED(
1165
0
        env, "No valid certificates found in the provided array");
1166
0
  }
1167
1168
0
  auto new_set = std::make_unique<X509Set>();
1169
0
  for (X509* cert : *certs) {
1170
0
    auto [it, inserted] = new_set->insert(cert);
1171
0
    if (!inserted) {  // Free duplicate certificates from the vector.
1172
0
      X509_free(cert);
1173
0
    }
1174
0
  }
1175
1176
  // Free any existing certificates in the old set.
1177
0
  if (root_certs_from_users != nullptr) {
1178
0
    for (X509* cert : *root_certs_from_users) {
1179
0
      X509_free(cert);
1180
0
    }
1181
0
  }
1182
0
  std::swap(root_certs_from_users, new_set);
1183
1184
  // Reset the global root cert store and create a new one with the
1185
  // certificates.
1186
0
  if (root_cert_store != nullptr) {
1187
0
    X509_STORE_free(root_cert_store);
1188
0
  }
1189
1190
  // TODO(joyeecheung): we can probably just reset it to nullptr
1191
  // and let the next call to NewRootCertStore() create a new one.
1192
0
  root_cert_store = NewRootCertStore();
1193
0
}
1194
1195
0
void GetSystemCACertificates(const FunctionCallbackInfo<Value>& args) {
1196
0
  Environment* env = Environment::GetCurrent(args);
1197
0
  Local<Array> results;
1198
0
  std::vector<X509*>& certs = GetSystemStoreCACertificates();
1199
0
  if (X509sToArrayOfStrings(env, certs.begin(), certs.end(), certs.size())
1200
0
          .ToLocal(&results)) {
1201
0
    args.GetReturnValue().Set(results);
1202
0
  }
1203
0
}
1204
1205
0
void GetExtraCACertificates(const FunctionCallbackInfo<Value>& args) {
1206
0
  Environment* env = Environment::GetCurrent(args);
1207
0
  if (extra_root_certs_file.empty()) {
1208
0
    return args.GetReturnValue().Set(Array::New(env->isolate()));
1209
0
  }
1210
0
  Local<Array> results;
1211
0
  std::vector<X509*>& certs = GetExtraCACertificates();
1212
0
  if (X509sToArrayOfStrings(env, certs.begin(), certs.end(), certs.size())
1213
0
          .ToLocal(&results)) {
1214
0
    args.GetReturnValue().Set(results);
1215
0
  }
1216
0
}
1217
1218
0
bool SecureContext::HasInstance(Environment* env, const Local<Value>& value) {
1219
0
  return GetConstructorTemplate(env)->HasInstance(value);
1220
0
}
1221
1222
Local<FunctionTemplate> SecureContext::GetConstructorTemplate(
1223
0
    Environment* env) {
1224
0
  Local<FunctionTemplate> tmpl = env->secure_context_constructor_template();
1225
0
  if (tmpl.IsEmpty()) {
1226
0
    Isolate* isolate = env->isolate();
1227
0
    tmpl = NewFunctionTemplate(isolate, New);
1228
0
    tmpl->InstanceTemplate()->SetInternalFieldCount(
1229
0
        SecureContext::kInternalFieldCount);
1230
0
    tmpl->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "SecureContext"));
1231
1232
0
    SetProtoMethod(isolate, tmpl, "init", Init);
1233
0
    SetProtoMethod(isolate, tmpl, "setKey", SetKey);
1234
0
    SetProtoMethod(isolate, tmpl, "setCert", SetCert);
1235
0
    SetProtoMethod(isolate, tmpl, "addCACert", AddCACert);
1236
0
    SetProtoMethod(
1237
0
        isolate, tmpl, "setAllowPartialTrustChain", SetAllowPartialTrustChain);
1238
0
    SetProtoMethod(isolate, tmpl, "addCRL", AddCRL);
1239
0
    SetProtoMethod(isolate, tmpl, "addRootCerts", AddRootCerts);
1240
0
    SetProtoMethod(isolate, tmpl, "setCipherSuites", SetCipherSuites);
1241
0
    SetProtoMethod(isolate, tmpl, "setCiphers", SetCiphers);
1242
0
    SetProtoMethod(isolate, tmpl, "setSigalgs", SetSigalgs);
1243
0
    SetProtoMethod(isolate, tmpl, "setECDHCurve", SetECDHCurve);
1244
0
    SetProtoMethod(isolate, tmpl, "setDHParam", SetDHParam);
1245
0
    SetProtoMethod(isolate, tmpl, "setMaxProto", SetMaxProto);
1246
0
    SetProtoMethod(isolate, tmpl, "setMinProto", SetMinProto);
1247
0
    SetProtoMethod(isolate, tmpl, "getMaxProto", GetMaxProto);
1248
0
    SetProtoMethod(isolate, tmpl, "getMinProto", GetMinProto);
1249
0
    SetProtoMethod(isolate, tmpl, "setOptions", SetOptions);
1250
0
    SetProtoMethod(isolate, tmpl, "setSessionIdContext", SetSessionIdContext);
1251
0
    SetProtoMethod(isolate, tmpl, "setSessionTimeout", SetSessionTimeout);
1252
0
    SetProtoMethod(isolate, tmpl, "close", Close);
1253
0
    SetProtoMethod(isolate, tmpl, "loadPKCS12", LoadPKCS12);
1254
0
    SetProtoMethod(isolate, tmpl, "setTicketKeys", SetTicketKeys);
1255
0
    SetProtoMethod(
1256
0
        isolate, tmpl, "enableTicketKeyCallback", EnableTicketKeyCallback);
1257
1258
0
    SetProtoMethodNoSideEffect(isolate, tmpl, "getTicketKeys", GetTicketKeys);
1259
0
    SetProtoMethodNoSideEffect(
1260
0
        isolate, tmpl, "getCertificate", GetCertificate<true>);
1261
0
    SetProtoMethodNoSideEffect(
1262
0
        isolate, tmpl, "getIssuer", GetCertificate<false>);
1263
1264
0
#ifndef OPENSSL_NO_ENGINE
1265
0
    SetProtoMethod(isolate, tmpl, "setEngineKey", SetEngineKey);
1266
0
    SetProtoMethod(isolate, tmpl, "setClientCertEngine", SetClientCertEngine);
1267
0
#endif  // !OPENSSL_NO_ENGINE
1268
1269
0
#define SET_INTEGER_CONSTANTS(name, value)                                     \
1270
0
  tmpl->Set(FIXED_ONE_BYTE_STRING(isolate, name),                              \
1271
0
            Integer::NewFromUnsigned(isolate, value));
1272
0
    SET_INTEGER_CONSTANTS("kTicketKeyReturnIndex", kTicketKeyReturnIndex);
1273
0
    SET_INTEGER_CONSTANTS("kTicketKeyHMACIndex", kTicketKeyHMACIndex);
1274
0
    SET_INTEGER_CONSTANTS("kTicketKeyAESIndex", kTicketKeyAESIndex);
1275
0
    SET_INTEGER_CONSTANTS("kTicketKeyNameIndex", kTicketKeyNameIndex);
1276
0
    SET_INTEGER_CONSTANTS("kTicketKeyIVIndex", kTicketKeyIVIndex);
1277
0
  #undef SET_INTEGER_CONSTANTS
1278
1279
0
    Local<FunctionTemplate> ctx_getter_templ = FunctionTemplate::New(
1280
0
        isolate, CtxGetter, Local<Value>(), Signature::New(isolate, tmpl));
1281
1282
0
    tmpl->PrototypeTemplate()->SetAccessorProperty(
1283
0
        FIXED_ONE_BYTE_STRING(isolate, "_external"),
1284
0
        ctx_getter_templ,
1285
0
        Local<FunctionTemplate>(),
1286
0
        static_cast<PropertyAttribute>(ReadOnly | DontDelete));
1287
1288
0
    env->set_secure_context_constructor_template(tmpl);
1289
0
  }
1290
0
  return tmpl;
1291
0
}
1292
1293
0
void SecureContext::Initialize(Environment* env, Local<Object> target) {
1294
0
  Local<Context> context = env->context();
1295
0
  SetConstructorFunction(context,
1296
0
                         target,
1297
0
                         "SecureContext",
1298
0
                         GetConstructorTemplate(env),
1299
0
                         SetConstructorFunctionFlag::NONE);
1300
1301
0
  SetMethodNoSideEffect(context,
1302
0
                        target,
1303
0
                        "getBundledRootCertificates",
1304
0
                        GetBundledRootCertificates);
1305
0
  SetMethodNoSideEffect(
1306
0
      context, target, "getSystemCACertificates", GetSystemCACertificates);
1307
0
  SetMethodNoSideEffect(
1308
0
      context, target, "getExtraCACertificates", GetExtraCACertificates);
1309
0
  SetMethod(context, target, "resetRootCertStore", ResetRootCertStore);
1310
0
  SetMethodNoSideEffect(
1311
0
      context, target, "getUserRootCertificates", GetUserRootCertificates);
1312
0
  SetMethod(context,
1313
0
            target,
1314
0
            "startLoadingCertificatesOffThread",
1315
0
            StartLoadingCertificatesOffThread);
1316
0
}
1317
1318
void SecureContext::RegisterExternalReferences(
1319
0
    ExternalReferenceRegistry* registry) {
1320
0
  registry->Register(New);
1321
0
  registry->Register(Init);
1322
0
  registry->Register(SetKey);
1323
0
  registry->Register(SetCert);
1324
0
  registry->Register(AddCACert);
1325
0
  registry->Register(AddCRL);
1326
0
  registry->Register(AddRootCerts);
1327
0
  registry->Register(SetAllowPartialTrustChain);
1328
0
  registry->Register(SetCipherSuites);
1329
0
  registry->Register(SetCiphers);
1330
0
  registry->Register(SetSigalgs);
1331
0
  registry->Register(SetECDHCurve);
1332
0
  registry->Register(SetDHParam);
1333
0
  registry->Register(SetMaxProto);
1334
0
  registry->Register(SetMinProto);
1335
0
  registry->Register(GetMaxProto);
1336
0
  registry->Register(GetMinProto);
1337
0
  registry->Register(SetOptions);
1338
0
  registry->Register(SetSessionIdContext);
1339
0
  registry->Register(SetSessionTimeout);
1340
0
  registry->Register(Close);
1341
0
  registry->Register(LoadPKCS12);
1342
0
  registry->Register(SetTicketKeys);
1343
0
  registry->Register(EnableTicketKeyCallback);
1344
0
  registry->Register(GetTicketKeys);
1345
0
  registry->Register(GetCertificate<true>);
1346
0
  registry->Register(GetCertificate<false>);
1347
1348
0
#ifndef OPENSSL_NO_ENGINE
1349
0
  registry->Register(SetEngineKey);
1350
0
  registry->Register(SetClientCertEngine);
1351
0
#endif  // !OPENSSL_NO_ENGINE
1352
1353
0
  registry->Register(CtxGetter);
1354
1355
0
  registry->Register(GetBundledRootCertificates);
1356
0
  registry->Register(GetSystemCACertificates);
1357
0
  registry->Register(GetExtraCACertificates);
1358
0
  registry->Register(ResetRootCertStore);
1359
0
  registry->Register(GetUserRootCertificates);
1360
0
  registry->Register(StartLoadingCertificatesOffThread);
1361
0
}
1362
1363
0
SecureContext* SecureContext::Create(Environment* env) {
1364
0
  Local<Object> obj;
1365
0
  if (!GetConstructorTemplate(env)
1366
0
          ->InstanceTemplate()
1367
0
          ->NewInstance(env->context()).ToLocal(&obj)) {
1368
0
    return nullptr;
1369
0
  }
1370
1371
0
  return new SecureContext(env, obj);
1372
0
}
1373
1374
SecureContext::SecureContext(Environment* env, Local<Object> wrap)
1375
0
    : BaseObject(env, wrap) {
1376
0
  MakeWeak();
1377
0
}
1378
1379
0
inline void SecureContext::Reset() {
1380
0
  if (ctx_ != nullptr) {
1381
0
    env()->external_memory_accounter()->Decrease(env()->isolate(),
1382
0
                                                 kExternalSize);
1383
0
  }
1384
0
  ctx_.reset();
1385
0
  cert_.reset();
1386
0
  issuer_.reset();
1387
0
}
1388
1389
0
SecureContext::~SecureContext() {
1390
0
  Reset();
1391
0
}
1392
1393
0
void SecureContext::New(const FunctionCallbackInfo<Value>& args) {
1394
0
  Environment* env = Environment::GetCurrent(args);
1395
0
  new SecureContext(env, args.This());
1396
0
}
1397
1398
0
void SecureContext::Init(const FunctionCallbackInfo<Value>& args) {
1399
0
  SecureContext* sc;
1400
0
  ASSIGN_OR_RETURN_UNWRAP(&sc, args.This());
1401
0
  Environment* env = sc->env();
1402
1403
0
  CHECK_EQ(args.Length(), 3);
1404
0
  CHECK(args[1]->IsInt32());
1405
0
  CHECK(args[2]->IsInt32());
1406
1407
0
  int min_version = args[1].As<Int32>()->Value();
1408
0
  int max_version = args[2].As<Int32>()->Value();
1409
0
  const SSL_METHOD* method = TLS_method();
1410
1411
0
  if (max_version == 0)
1412
0
    max_version = kMaxSupportedVersion;
1413
1414
0
  if (args[0]->IsString()) {
1415
0
    Utf8Value sslmethod(env->isolate(), args[0]);
1416
1417
    // Note that SSLv2 and SSLv3 are disallowed but SSLv23_method and friends
1418
    // are still accepted.  They are OpenSSL's way of saying that all known
1419
    // protocols below TLS 1.3 are supported unless explicitly disabled (which
1420
    // we do below for SSLv2 and SSLv3.)
1421
0
    if (sslmethod == "SSLv2_method" ||
1422
0
        sslmethod == "SSLv2_server_method" ||
1423
0
        sslmethod == "SSLv2_client_method") {
1424
0
      THROW_ERR_TLS_INVALID_PROTOCOL_METHOD(env, "SSLv2 methods disabled");
1425
0
      return;
1426
0
    } else if (sslmethod == "SSLv3_method" ||
1427
0
               sslmethod == "SSLv3_server_method" ||
1428
0
               sslmethod == "SSLv3_client_method") {
1429
0
      THROW_ERR_TLS_INVALID_PROTOCOL_METHOD(env, "SSLv3 methods disabled");
1430
0
      return;
1431
0
    } else if (sslmethod == "SSLv23_method") {
1432
0
      max_version = TLS1_2_VERSION;
1433
0
    } else if (sslmethod == "SSLv23_server_method") {
1434
0
      max_version = TLS1_2_VERSION;
1435
0
      method = TLS_server_method();
1436
0
    } else if (sslmethod == "SSLv23_client_method") {
1437
0
      max_version = TLS1_2_VERSION;
1438
0
      method = TLS_client_method();
1439
0
    } else if (sslmethod == "TLS_method") {
1440
0
      min_version = 0;
1441
0
      max_version = kMaxSupportedVersion;
1442
0
    } else if (sslmethod == "TLS_server_method") {
1443
0
      min_version = 0;
1444
0
      max_version = kMaxSupportedVersion;
1445
0
      method = TLS_server_method();
1446
0
    } else if (sslmethod == "TLS_client_method") {
1447
0
      min_version = 0;
1448
0
      max_version = kMaxSupportedVersion;
1449
0
      method = TLS_client_method();
1450
0
    } else if (sslmethod == "TLSv1_method") {
1451
0
      min_version = TLS1_VERSION;
1452
0
      max_version = TLS1_VERSION;
1453
0
    } else if (sslmethod == "TLSv1_server_method") {
1454
0
      min_version = TLS1_VERSION;
1455
0
      max_version = TLS1_VERSION;
1456
0
      method = TLS_server_method();
1457
0
    } else if (sslmethod == "TLSv1_client_method") {
1458
0
      min_version = TLS1_VERSION;
1459
0
      max_version = TLS1_VERSION;
1460
0
      method = TLS_client_method();
1461
0
    } else if (sslmethod == "TLSv1_1_method") {
1462
0
      min_version = TLS1_1_VERSION;
1463
0
      max_version = TLS1_1_VERSION;
1464
0
    } else if (sslmethod == "TLSv1_1_server_method") {
1465
0
      min_version = TLS1_1_VERSION;
1466
0
      max_version = TLS1_1_VERSION;
1467
0
      method = TLS_server_method();
1468
0
    } else if (sslmethod == "TLSv1_1_client_method") {
1469
0
      min_version = TLS1_1_VERSION;
1470
0
      max_version = TLS1_1_VERSION;
1471
0
      method = TLS_client_method();
1472
0
    } else if (sslmethod == "TLSv1_2_method") {
1473
0
      min_version = TLS1_2_VERSION;
1474
0
      max_version = TLS1_2_VERSION;
1475
0
    } else if (sslmethod == "TLSv1_2_server_method") {
1476
0
      min_version = TLS1_2_VERSION;
1477
0
      max_version = TLS1_2_VERSION;
1478
0
      method = TLS_server_method();
1479
0
    } else if (sslmethod == "TLSv1_2_client_method") {
1480
0
      min_version = TLS1_2_VERSION;
1481
0
      max_version = TLS1_2_VERSION;
1482
0
      method = TLS_client_method();
1483
0
    } else {
1484
0
      THROW_ERR_TLS_INVALID_PROTOCOL_METHOD(
1485
0
          env, "Unknown method: %s", sslmethod);
1486
0
      return;
1487
0
    }
1488
0
  }
1489
1490
0
  sc->ctx_.reset(method);
1491
0
  if (!sc->ctx_) {
1492
0
    return ThrowCryptoError(env, ERR_get_error(), "SSL_CTX_new");
1493
0
  }
1494
1495
0
  env->external_memory_accounter()->Increase(env->isolate(), kExternalSize);
1496
0
  SSL_CTX_set_app_data(sc->ctx_.get(), sc);
1497
1498
  // Disable SSLv2 in the case when method == TLS_method() and the
1499
  // cipher list contains SSLv2 ciphers (not the default, should be rare.)
1500
  // The bundled OpenSSL doesn't have SSLv2 support but the system OpenSSL may.
1501
  // SSLv3 is disabled because it's susceptible to downgrade attacks (POODLE.)
1502
0
  SSL_CTX_set_options(sc->ctx_.get(), SSL_OP_NO_SSLv2);
1503
0
  SSL_CTX_set_options(sc->ctx_.get(), SSL_OP_NO_SSLv3);
1504
0
#if OPENSSL_VERSION_MAJOR >= 3
1505
0
  SSL_CTX_set_options(sc->ctx_.get(), SSL_OP_ALLOW_CLIENT_RENEGOTIATION);
1506
0
#endif
1507
1508
  // Enable automatic cert chaining. This is enabled by default in OpenSSL, but
1509
  // disabled by default in BoringSSL. Enable it explicitly to make the
1510
  // behavior match when Node is built with BoringSSL.
1511
0
  SSL_CTX_clear_mode(sc->ctx_.get(), SSL_MODE_NO_AUTO_CHAIN);
1512
1513
  // SSL session cache configuration
1514
0
  SSL_CTX_set_session_cache_mode(sc->ctx_.get(),
1515
0
                                 SSL_SESS_CACHE_CLIENT |
1516
0
                                 SSL_SESS_CACHE_SERVER |
1517
0
                                 SSL_SESS_CACHE_NO_INTERNAL |
1518
0
                                 SSL_SESS_CACHE_NO_AUTO_CLEAR);
1519
1520
0
  CHECK(SSL_CTX_set_min_proto_version(sc->ctx_.get(), min_version));
1521
0
  CHECK(SSL_CTX_set_max_proto_version(sc->ctx_.get(), max_version));
1522
1523
  // OpenSSL 1.1.0 changed the ticket key size, but the OpenSSL 1.0.x size was
1524
  // exposed in the public API. To retain compatibility, install a callback
1525
  // which restores the old algorithm.
1526
0
  if (!ncrypto::CSPRNG(sc->ticket_key_name_, sizeof(sc->ticket_key_name_)) ||
1527
0
      !ncrypto::CSPRNG(sc->ticket_key_hmac_, sizeof(sc->ticket_key_hmac_)) ||
1528
0
      !ncrypto::CSPRNG(sc->ticket_key_aes_, sizeof(sc->ticket_key_aes_))) {
1529
0
    return THROW_ERR_CRYPTO_OPERATION_FAILED(
1530
0
        env, "Error generating ticket keys");
1531
0
  }
1532
0
  SSL_CTX_set_tlsext_ticket_key_cb(sc->ctx_.get(), TicketCompatibilityCallback);
1533
0
}
1534
1535
0
SSLPointer SecureContext::CreateSSL() {
1536
0
  return SSLPointer(SSL_new(ctx_.get()));
1537
0
}
1538
1539
0
void SecureContext::SetNewSessionCallback(NewSessionCb cb) {
1540
0
  SSL_CTX_sess_set_new_cb(ctx_.get(), cb);
1541
0
}
1542
1543
0
void SecureContext::SetGetSessionCallback(GetSessionCb cb) {
1544
0
  SSL_CTX_sess_set_get_cb(ctx_.get(), cb);
1545
0
}
1546
1547
0
void SecureContext::SetSelectSNIContextCallback(SelectSNIContextCb cb) {
1548
0
  SSL_CTX_set_tlsext_servername_callback(ctx_.get(), cb);
1549
0
}
1550
1551
0
void SecureContext::SetKeylogCallback(KeylogCb cb) {
1552
0
  SSL_CTX_set_keylog_callback(ctx_.get(), cb);
1553
0
}
1554
1555
0
Maybe<void> SecureContext::UseKey(Environment* env, const KeyObjectData& key) {
1556
0
  if (key.GetKeyType() != KeyType::kKeyTypePrivate) {
1557
0
    THROW_ERR_CRYPTO_INVALID_KEYTYPE(env);
1558
0
    return Nothing<void>();
1559
0
  }
1560
1561
0
  ClearErrorOnReturn clear_error_on_return;
1562
0
  if (!SSL_CTX_use_PrivateKey(ctx_.get(), key.GetAsymmetricKey().get())) {
1563
0
    ThrowCryptoError(env, ERR_get_error(), "SSL_CTX_use_PrivateKey");
1564
0
    return Nothing<void>();
1565
0
  }
1566
1567
0
  return JustVoid();
1568
0
}
1569
1570
0
void SecureContext::SetKey(const FunctionCallbackInfo<Value>& args) {
1571
0
  Environment* env = Environment::GetCurrent(args);
1572
1573
0
  SecureContext* sc;
1574
0
  ASSIGN_OR_RETURN_UNWRAP(&sc, args.This());
1575
1576
0
  CHECK_GE(args.Length(), 1);  // Private key argument is mandatory
1577
1578
0
  BIOPointer bio(LoadBIO(env, args[0]));
1579
0
  if (!bio)
1580
0
    return;
1581
1582
0
  ByteSource passphrase;
1583
0
  if (args[1]->IsString())
1584
0
    passphrase = ByteSource::FromString(env, args[1].As<String>());
1585
  // This redirection is necessary because the PasswordCallback expects a
1586
  // pointer to a pointer to the passphrase ByteSource to allow passing in
1587
  // const ByteSources.
1588
0
  const ByteSource* pass_ptr = &passphrase;
1589
1590
0
  EVPKeyPointer key(
1591
0
      PEM_read_bio_PrivateKey(bio.get(),
1592
0
                              nullptr,
1593
0
                              PasswordCallback,
1594
0
                              &pass_ptr));
1595
1596
0
  if (!key)
1597
0
    return ThrowCryptoError(env, ERR_get_error(), "PEM_read_bio_PrivateKey");
1598
1599
0
  if (!SSL_CTX_use_PrivateKey(sc->ctx_.get(), key.get()))
1600
0
    return ThrowCryptoError(env, ERR_get_error(), "SSL_CTX_use_PrivateKey");
1601
0
}
1602
1603
0
void SecureContext::SetSigalgs(const FunctionCallbackInfo<Value>& args) {
1604
0
  SecureContext* sc;
1605
0
  ASSIGN_OR_RETURN_UNWRAP(&sc, args.This());
1606
0
  Environment* env = sc->env();
1607
0
  ClearErrorOnReturn clear_error_on_return;
1608
1609
0
  CHECK_EQ(args.Length(), 1);
1610
0
  CHECK(args[0]->IsString());
1611
1612
0
  const Utf8Value sigalgs(env->isolate(), args[0]);
1613
1614
0
  if (!SSL_CTX_set1_sigalgs_list(sc->ctx_.get(), *sigalgs))
1615
0
    return ThrowCryptoError(env, ERR_get_error());
1616
0
}
1617
1618
#ifndef OPENSSL_NO_ENGINE
1619
0
void SecureContext::SetEngineKey(const FunctionCallbackInfo<Value>& args) {
1620
0
  Environment* env = Environment::GetCurrent(args);
1621
1622
0
  SecureContext* sc;
1623
0
  ASSIGN_OR_RETURN_UNWRAP(&sc, args.This());
1624
1625
0
  CHECK_EQ(args.Length(), 2);
1626
1627
0
  if (env->permission()->enabled()) [[unlikely]] {
1628
0
    return THROW_ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED(
1629
0
        env,
1630
0
        "Programmatic selection of OpenSSL engines is unsupported while the "
1631
0
        "experimental permission model is enabled");
1632
0
  }
1633
1634
0
  CryptoErrorList errors;
1635
0
  Utf8Value engine_id(env->isolate(), args[1]);
1636
0
  auto engine = EnginePointer::getEngineByName(*engine_id, &errors);
1637
0
  if (!engine) {
1638
0
    Local<Value> exception;
1639
0
    if (errors.empty()) {
1640
0
      errors.add(getNodeCryptoErrorString(NodeCryptoError::ENGINE_NOT_FOUND,
1641
0
                                          *engine_id));
1642
0
    }
1643
0
    if (cryptoErrorListToException(env, errors).ToLocal(&exception))
1644
0
      env->isolate()->ThrowException(exception);
1645
0
    return;
1646
0
  }
1647
1648
0
  if (!engine.init(true /* finish on exit*/)) {
1649
0
    return THROW_ERR_CRYPTO_OPERATION_FAILED(
1650
0
        env, "Failure to initialize engine");
1651
0
  }
1652
1653
0
  Utf8Value key_name(env->isolate(), args[0]);
1654
0
  auto key = engine.loadPrivateKey(*key_name);
1655
1656
0
  if (!key)
1657
0
    return ThrowCryptoError(env, ERR_get_error(), "ENGINE_load_private_key");
1658
1659
0
  if (!SSL_CTX_use_PrivateKey(sc->ctx_.get(), key.get()))
1660
0
    return ThrowCryptoError(env, ERR_get_error(), "SSL_CTX_use_PrivateKey");
1661
1662
0
  sc->private_key_engine_ = std::move(engine);
1663
0
}
1664
#endif  // !OPENSSL_NO_ENGINE
1665
1666
0
Maybe<void> SecureContext::AddCert(Environment* env, BIOPointer&& bio) {
1667
0
  ClearErrorOnReturn clear_error_on_return;
1668
  // TODO(tniessen): this should be checked by the caller and not treated as ok
1669
0
  if (!bio) return JustVoid();
1670
0
  cert_.reset();
1671
0
  issuer_.reset();
1672
1673
  // The SSL_CTX_use_certificate_chain call here is not from openssl, this is
1674
  // the method implemented elsewhere in this file. The naming is a bit
1675
  // confusing, unfortunately.
1676
0
  if (SSL_CTX_use_certificate_chain(
1677
0
          ctx_.get(), std::move(bio), &cert_, &issuer_) == 0) {
1678
0
    ThrowCryptoError(env, ERR_get_error(), "SSL_CTX_use_certificate_chain");
1679
0
    return Nothing<void>();
1680
0
  }
1681
0
  return JustVoid();
1682
0
}
1683
1684
0
void SecureContext::SetCert(const FunctionCallbackInfo<Value>& args) {
1685
0
  Environment* env = Environment::GetCurrent(args);
1686
1687
0
  SecureContext* sc;
1688
0
  ASSIGN_OR_RETURN_UNWRAP(&sc, args.This());
1689
1690
0
  CHECK_GE(args.Length(), 1);  // Certificate argument is mandatory
1691
1692
0
  BIOPointer bio(LoadBIO(env, args[0]));
1693
0
  USE(sc->AddCert(env, std::move(bio)));
1694
0
}
1695
1696
// NOLINTNEXTLINE(runtime/int)
1697
0
void SecureContext::SetX509StoreFlag(unsigned long flags) {
1698
0
  X509_STORE* cert_store = GetCertStoreOwnedByThisSecureContext();
1699
0
  CHECK_EQ(1, X509_STORE_set_flags(cert_store, flags));
1700
0
}
1701
1702
0
X509_STORE* SecureContext::GetCertStoreOwnedByThisSecureContext() {
1703
0
  if (own_cert_store_cache_ != nullptr) return own_cert_store_cache_;
1704
1705
0
  X509_STORE* cert_store = SSL_CTX_get_cert_store(ctx_.get());
1706
0
  if (cert_store == GetOrCreateRootCertStore()) {
1707
0
    cert_store = NewRootCertStore();
1708
0
    SSL_CTX_set_cert_store(ctx_.get(), cert_store);
1709
0
  }
1710
1711
0
  return own_cert_store_cache_ = cert_store;
1712
0
}
1713
1714
void SecureContext::SetAllowPartialTrustChain(
1715
0
    const FunctionCallbackInfo<Value>& args) {
1716
0
  SecureContext* sc;
1717
0
  ASSIGN_OR_RETURN_UNWRAP(&sc, args.This());
1718
0
  sc->SetX509StoreFlag(X509_V_FLAG_PARTIAL_CHAIN);
1719
0
}
1720
1721
0
void SecureContext::SetCACert(const BIOPointer& bio) {
1722
0
  ClearErrorOnReturn clear_error_on_return;
1723
0
  if (!bio) return;
1724
0
  while (X509Pointer x509 = X509Pointer(PEM_read_bio_X509_AUX(
1725
0
             bio.get(), nullptr, NoPasswordCallback, nullptr))) {
1726
0
    CHECK_EQ(1,
1727
0
             X509_STORE_add_cert(GetCertStoreOwnedByThisSecureContext(), x509));
1728
0
    CHECK_EQ(1, SSL_CTX_add_client_CA(ctx_.get(), x509));
1729
0
  }
1730
0
}
1731
1732
0
void SecureContext::AddCACert(const FunctionCallbackInfo<Value>& args) {
1733
0
  Environment* env = Environment::GetCurrent(args);
1734
1735
0
  SecureContext* sc;
1736
0
  ASSIGN_OR_RETURN_UNWRAP(&sc, args.This());
1737
1738
0
  CHECK_GE(args.Length(), 1);  // CA certificate argument is mandatory
1739
1740
0
  BIOPointer bio(LoadBIO(env, args[0]));
1741
0
  sc->SetCACert(bio);
1742
0
}
1743
1744
0
Maybe<void> SecureContext::SetCRL(Environment* env, const BIOPointer& bio) {
1745
0
  ClearErrorOnReturn clear_error_on_return;
1746
  // TODO(tniessen): this should be checked by the caller and not treated as ok
1747
0
  if (!bio) return JustVoid();
1748
1749
0
  DeleteFnPtr<X509_CRL, X509_CRL_free> crl(
1750
0
      PEM_read_bio_X509_CRL(bio.get(), nullptr, NoPasswordCallback, nullptr));
1751
1752
0
  if (!crl) {
1753
0
    THROW_ERR_CRYPTO_OPERATION_FAILED(env, "Failed to parse CRL");
1754
0
    return Nothing<void>();
1755
0
  }
1756
1757
0
  X509_STORE* cert_store = GetCertStoreOwnedByThisSecureContext();
1758
1759
0
  CHECK_EQ(1, X509_STORE_add_crl(cert_store, crl.get()));
1760
0
  CHECK_EQ(1,
1761
0
           X509_STORE_set_flags(
1762
0
               cert_store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL));
1763
0
  return JustVoid();
1764
0
}
1765
1766
0
void SecureContext::AddCRL(const FunctionCallbackInfo<Value>& args) {
1767
0
  Environment* env = Environment::GetCurrent(args);
1768
1769
0
  SecureContext* sc;
1770
0
  ASSIGN_OR_RETURN_UNWRAP(&sc, args.This());
1771
1772
0
  CHECK_GE(args.Length(), 1);  // CRL argument is mandatory
1773
1774
0
  BIOPointer bio(LoadBIO(env, args[0]));
1775
0
  USE(sc->SetCRL(env, bio));
1776
0
}
1777
1778
0
void SecureContext::SetRootCerts() {
1779
0
  ClearErrorOnReturn clear_error_on_return;
1780
0
  auto store = GetOrCreateRootCertStore();
1781
1782
  // Increment reference count so global store is not deleted along with CTX.
1783
0
  X509_STORE_up_ref(store);
1784
0
  SSL_CTX_set_cert_store(ctx_.get(), store);
1785
0
}
1786
1787
0
void SecureContext::AddRootCerts(const FunctionCallbackInfo<Value>& args) {
1788
0
  SecureContext* sc;
1789
0
  ASSIGN_OR_RETURN_UNWRAP(&sc, args.This());
1790
0
  sc->SetRootCerts();
1791
0
}
1792
1793
0
void SecureContext::SetCipherSuites(const FunctionCallbackInfo<Value>& args) {
1794
0
  SecureContext* sc;
1795
0
  ASSIGN_OR_RETURN_UNWRAP(&sc, args.This());
1796
0
  Environment* env = sc->env();
1797
0
  ClearErrorOnReturn clear_error_on_return;
1798
1799
0
  CHECK_EQ(args.Length(), 1);
1800
0
  CHECK(args[0]->IsString());
1801
1802
0
  const Utf8Value ciphers(env->isolate(), args[0]);
1803
0
  if (!sc->ctx_.setCipherSuites(*ciphers)) {
1804
0
    return ThrowCryptoError(env, ERR_get_error(), "Failed to set ciphers");
1805
0
  }
1806
0
}
1807
1808
0
void SecureContext::SetCiphers(const FunctionCallbackInfo<Value>& args) {
1809
0
  SecureContext* sc;
1810
0
  ASSIGN_OR_RETURN_UNWRAP(&sc, args.This());
1811
0
  Environment* env = sc->env();
1812
0
  ClearErrorOnReturn clear_error_on_return;
1813
1814
0
  CHECK_EQ(args.Length(), 1);
1815
0
  CHECK(args[0]->IsString());
1816
1817
0
  Utf8Value ciphers(env->isolate(), args[0]);
1818
0
  if (!SSL_CTX_set_cipher_list(sc->ctx_.get(), *ciphers)) {
1819
0
    unsigned long err = ERR_get_error();  // NOLINT(runtime/int)
1820
1821
0
    if (strlen(*ciphers) == 0 && ERR_GET_REASON(err) == SSL_R_NO_CIPHER_MATCH) {
1822
      // TLS1.2 ciphers were deliberately cleared, so don't consider
1823
      // SSL_R_NO_CIPHER_MATCH to be an error (this is how _set_cipher_suites()
1824
      // works). If the user actually sets a value (like "no-such-cipher"), then
1825
      // that's actually an error.
1826
0
      return;
1827
0
    }
1828
0
    return ThrowCryptoError(env, err, "Failed to set ciphers");
1829
0
  }
1830
0
}
1831
1832
0
void SecureContext::SetECDHCurve(const FunctionCallbackInfo<Value>& args) {
1833
0
  SecureContext* sc;
1834
0
  ASSIGN_OR_RETURN_UNWRAP(&sc, args.This());
1835
0
  Environment* env = sc->env();
1836
1837
0
  CHECK_GE(args.Length(), 1);  // ECDH curve name argument is mandatory
1838
0
  CHECK(args[0]->IsString());
1839
1840
0
  Utf8Value curve(env->isolate(), args[0]);
1841
1842
0
  if (curve != "auto" && !SSL_CTX_set1_curves_list(sc->ctx_.get(), *curve)) {
1843
0
    return THROW_ERR_CRYPTO_OPERATION_FAILED(env, "Failed to set ECDH curve");
1844
0
  }
1845
0
}
1846
1847
0
void SecureContext::SetDHParam(const FunctionCallbackInfo<Value>& args) {
1848
0
  SecureContext* sc;
1849
0
  ASSIGN_OR_RETURN_UNWRAP(&sc, args.This());
1850
0
  Environment* env = sc->env();
1851
0
  ClearErrorOnReturn clear_error_on_return;
1852
1853
0
  CHECK_GE(args.Length(), 1);  // DH argument is mandatory
1854
1855
  // If the user specified "auto" for dhparams, the JavaScript layer will pass
1856
  // true to this function instead of the original string. Any other string
1857
  // value will be interpreted as custom DH parameters below.
1858
0
  if (args[0]->IsTrue()) {
1859
0
    CHECK(SSL_CTX_set_dh_auto(sc->ctx_.get(), true));
1860
0
    return;
1861
0
  }
1862
1863
0
  DHPointer dh;
1864
0
  {
1865
0
    BIOPointer bio(LoadBIO(env, args[0]));
1866
0
    if (!bio)
1867
0
      return;
1868
1869
0
    dh.reset(PEM_read_bio_DHparams(bio.get(), nullptr, nullptr, nullptr));
1870
0
  }
1871
1872
  // Invalid dhparam is silently discarded and DHE is no longer used.
1873
  // TODO(tniessen): don't silently discard invalid dhparam.
1874
0
  if (!dh)
1875
0
    return;
1876
1877
0
  const BIGNUM* p;
1878
0
  DH_get0_pqg(dh.get(), &p, nullptr, nullptr);
1879
0
  const int size = BignumPointer::GetBitCount(p);
1880
0
  if (size < 1024) {
1881
0
    return THROW_ERR_INVALID_ARG_VALUE(
1882
0
        env, "DH parameter is less than 1024 bits");
1883
0
  } else if (size < 2048) {
1884
0
    args.GetReturnValue().Set(FIXED_ONE_BYTE_STRING(
1885
0
        env->isolate(), "DH parameter is less than 2048 bits"));
1886
0
  }
1887
1888
0
  if (!SSL_CTX_set_tmp_dh(sc->ctx_.get(), dh.get())) {
1889
0
    return THROW_ERR_CRYPTO_OPERATION_FAILED(
1890
0
        env, "Error setting temp DH parameter");
1891
0
  }
1892
0
}
1893
1894
0
void SecureContext::SetMinProto(const FunctionCallbackInfo<Value>& args) {
1895
0
  SecureContext* sc;
1896
0
  ASSIGN_OR_RETURN_UNWRAP(&sc, args.This());
1897
1898
0
  CHECK_EQ(args.Length(), 1);
1899
0
  CHECK(args[0]->IsInt32());
1900
1901
0
  int version = args[0].As<Int32>()->Value();
1902
1903
0
  CHECK(SSL_CTX_set_min_proto_version(sc->ctx_.get(), version));
1904
0
}
1905
1906
0
void SecureContext::SetMaxProto(const FunctionCallbackInfo<Value>& args) {
1907
0
  SecureContext* sc;
1908
0
  ASSIGN_OR_RETURN_UNWRAP(&sc, args.This());
1909
1910
0
  CHECK_EQ(args.Length(), 1);
1911
0
  CHECK(args[0]->IsInt32());
1912
1913
0
  int version = args[0].As<Int32>()->Value();
1914
1915
0
  CHECK(SSL_CTX_set_max_proto_version(sc->ctx_.get(), version));
1916
0
}
1917
1918
0
void SecureContext::GetMinProto(const FunctionCallbackInfo<Value>& args) {
1919
0
  SecureContext* sc;
1920
0
  ASSIGN_OR_RETURN_UNWRAP(&sc, args.This());
1921
1922
0
  CHECK_EQ(args.Length(), 0);
1923
1924
0
  long version =  // NOLINT(runtime/int)
1925
0
    SSL_CTX_get_min_proto_version(sc->ctx_.get());
1926
0
  args.GetReturnValue().Set(static_cast<uint32_t>(version));
1927
0
}
1928
1929
0
void SecureContext::GetMaxProto(const FunctionCallbackInfo<Value>& args) {
1930
0
  SecureContext* sc;
1931
0
  ASSIGN_OR_RETURN_UNWRAP(&sc, args.This());
1932
1933
0
  CHECK_EQ(args.Length(), 0);
1934
1935
0
  long version =  // NOLINT(runtime/int)
1936
0
    SSL_CTX_get_max_proto_version(sc->ctx_.get());
1937
0
  args.GetReturnValue().Set(static_cast<uint32_t>(version));
1938
0
}
1939
1940
0
void SecureContext::SetOptions(const FunctionCallbackInfo<Value>& args) {
1941
0
  Environment* env = Environment::GetCurrent(args);
1942
0
  SecureContext* sc;
1943
0
  ASSIGN_OR_RETURN_UNWRAP(&sc, args.This());
1944
1945
0
  CHECK_GE(args.Length(), 1);
1946
0
  CHECK(args[0]->IsNumber());
1947
1948
0
  int64_t val = args[0]->IntegerValue(env->context()).FromMaybe(0);
1949
1950
0
  SSL_CTX_set_options(sc->ctx_.get(),
1951
0
                      static_cast<long>(val));  // NOLINT(runtime/int)
1952
0
}
1953
1954
void SecureContext::SetSessionIdContext(
1955
0
    const FunctionCallbackInfo<Value>& args) {
1956
0
  SecureContext* sc;
1957
0
  ASSIGN_OR_RETURN_UNWRAP(&sc, args.This());
1958
0
  Environment* env = sc->env();
1959
1960
0
  CHECK_GE(args.Length(), 1);
1961
0
  CHECK(args[0]->IsString());
1962
1963
0
  const Utf8Value sessionIdContext(env->isolate(), args[0]);
1964
0
  const unsigned char* sid_ctx =
1965
0
      reinterpret_cast<const unsigned char*>(*sessionIdContext);
1966
0
  unsigned int sid_ctx_len = sessionIdContext.length();
1967
1968
0
  if (SSL_CTX_set_session_id_context(sc->ctx_.get(), sid_ctx, sid_ctx_len) == 1)
1969
0
    return;
1970
1971
0
  Local<String> message;
1972
1973
0
  auto bio = BIOPointer::NewMem();
1974
0
  if (!bio) {
1975
0
    message = FIXED_ONE_BYTE_STRING(env->isolate(),
1976
0
                                    "SSL_CTX_set_session_id_context error");
1977
0
  } else {
1978
0
    ERR_print_errors(bio.get());
1979
0
    BUF_MEM* mem = bio;
1980
0
    message = OneByteString(env->isolate(), mem->data, mem->length);
1981
0
  }
1982
1983
0
  env->isolate()->ThrowException(Exception::TypeError(message));
1984
0
}
1985
1986
0
void SecureContext::SetSessionTimeout(const FunctionCallbackInfo<Value>& args) {
1987
0
  SecureContext* sc;
1988
0
  ASSIGN_OR_RETURN_UNWRAP(&sc, args.This());
1989
1990
0
  CHECK_GE(args.Length(), 1);
1991
0
  CHECK(args[0]->IsInt32());
1992
1993
0
  int32_t sessionTimeout = args[0].As<Int32>()->Value();
1994
0
  CHECK_GE(sessionTimeout, 0);
1995
0
  SSL_CTX_set_timeout(sc->ctx_.get(), sessionTimeout);
1996
0
}
1997
1998
0
void SecureContext::Close(const FunctionCallbackInfo<Value>& args) {
1999
0
  SecureContext* sc;
2000
0
  ASSIGN_OR_RETURN_UNWRAP(&sc, args.This());
2001
0
  sc->Reset();
2002
0
}
2003
2004
// Takes .pfx or .p12 and password in string or buffer format
2005
0
void SecureContext::LoadPKCS12(const FunctionCallbackInfo<Value>& args) {
2006
0
  Environment* env = Environment::GetCurrent(args);
2007
2008
0
  std::vector<char> pass;
2009
0
  bool ret = false;
2010
2011
0
  SecureContext* sc;
2012
0
  ASSIGN_OR_RETURN_UNWRAP(&sc, args.This());
2013
0
  ClearErrorOnReturn clear_error_on_return;
2014
2015
0
  if (args.Length() < 1) {
2016
0
    return THROW_ERR_MISSING_ARGS(env, "PFX certificate argument is mandatory");
2017
0
  }
2018
2019
0
  BIOPointer in(LoadBIO(env, args[0]));
2020
0
  if (!in) {
2021
0
    return THROW_ERR_CRYPTO_OPERATION_FAILED(
2022
0
        env, "Unable to load PFX certificate");
2023
0
  }
2024
2025
0
  if (args.Length() >= 2) {
2026
0
    THROW_AND_RETURN_IF_NOT_BUFFER(env, args[1], "Pass phrase");
2027
0
    Local<ArrayBufferView> abv = args[1].As<ArrayBufferView>();
2028
0
    size_t passlen = abv->ByteLength();
2029
0
    pass.resize(passlen + 1);
2030
0
    abv->CopyContents(pass.data(), passlen);
2031
0
    pass[passlen] = '\0';
2032
0
  }
2033
2034
  // Free previous certs
2035
0
  sc->issuer_.reset();
2036
0
  sc->cert_.reset();
2037
2038
0
  DeleteFnPtr<PKCS12, PKCS12_free> p12;
2039
0
  EVPKeyPointer pkey;
2040
0
  X509Pointer cert;
2041
0
  StackOfX509 extra_certs;
2042
2043
0
  PKCS12* p12_ptr = nullptr;
2044
0
  EVP_PKEY* pkey_ptr = nullptr;
2045
0
  X509* cert_ptr = nullptr;
2046
0
  STACK_OF(X509)* extra_certs_ptr = nullptr;
2047
2048
0
  if (!d2i_PKCS12_bio(in.get(), &p12_ptr)) {
2049
0
    goto done;
2050
0
  }
2051
2052
  // Move ownership to the smart pointer:
2053
0
  p12.reset(p12_ptr);
2054
2055
0
  if (!PKCS12_parse(
2056
0
          p12.get(), pass.data(), &pkey_ptr, &cert_ptr, &extra_certs_ptr)) {
2057
0
    goto done;
2058
0
  }
2059
2060
  // Move ownership of the parsed data:
2061
0
  pkey.reset(pkey_ptr);
2062
0
  cert.reset(cert_ptr);
2063
0
  extra_certs.reset(extra_certs_ptr);
2064
2065
0
  if (!pkey) {
2066
0
    return THROW_ERR_CRYPTO_OPERATION_FAILED(
2067
0
        env, "Unable to load private key from PFX data");
2068
0
  }
2069
2070
0
  if (!cert) {
2071
0
    return THROW_ERR_CRYPTO_OPERATION_FAILED(
2072
0
        env, "Unable to load certificate from PFX data");
2073
0
  }
2074
2075
0
  if (!SSL_CTX_use_certificate_chain(sc->ctx_.get(),
2076
0
                                     std::move(cert),
2077
0
                                     extra_certs.get(),
2078
0
                                     &sc->cert_,
2079
0
                                     &sc->issuer_)) {
2080
0
    goto done;
2081
0
  }
2082
2083
0
  if (!SSL_CTX_use_PrivateKey(sc->ctx_.get(), pkey.get())) {
2084
0
    goto done;
2085
0
  }
2086
2087
  // Add CA certs too
2088
0
  for (int i = 0; i < sk_X509_num(extra_certs.get()); i++) {
2089
0
    X509* ca = sk_X509_value(extra_certs.get(), i);
2090
2091
0
    X509_STORE_add_cert(sc->GetCertStoreOwnedByThisSecureContext(), ca);
2092
0
    CHECK_EQ(1, SSL_CTX_add_client_CA(sc->ctx_.get(), ca));
2093
0
  }
2094
0
  ret = true;
2095
2096
0
done:
2097
0
  if (!ret) {
2098
    // TODO(@jasnell): Should this use ThrowCryptoError?
2099
0
    unsigned long err = ERR_get_error();  // NOLINT(runtime/int)
2100
2101
0
#if OPENSSL_VERSION_MAJOR >= 3
2102
0
    if (ERR_GET_REASON(err) == ERR_R_UNSUPPORTED) {
2103
      // OpenSSL's "unsupported" error without any context is very
2104
      // common and not very helpful, so we override it:
2105
0
      return THROW_ERR_CRYPTO_UNSUPPORTED_OPERATION(
2106
0
          env, "Unsupported PKCS12 PFX data");
2107
0
    }
2108
0
#endif
2109
2110
0
    const char* str = ERR_reason_error_string(err);
2111
0
    str = str != nullptr ? str : "Unknown error";
2112
2113
0
    return env->ThrowError(str);
2114
0
  }
2115
0
}
2116
2117
#ifndef OPENSSL_NO_ENGINE
2118
void SecureContext::SetClientCertEngine(
2119
0
    const FunctionCallbackInfo<Value>& args) {
2120
0
  Environment* env = Environment::GetCurrent(args);
2121
0
  CHECK_EQ(args.Length(), 1);
2122
0
  CHECK(args[0]->IsString());
2123
2124
0
  SecureContext* sc;
2125
0
  ASSIGN_OR_RETURN_UNWRAP(&sc, args.This());
2126
2127
0
  MarkPopErrorOnReturn mark_pop_error_on_return;
2128
2129
  // SSL_CTX_set_client_cert_engine does not itself support multiple
2130
  // calls by cleaning up before overwriting the client_cert_engine
2131
  // internal context variable.
2132
  // Instead of trying to fix up this problem we in turn also do not
2133
  // support multiple calls to SetClientCertEngine.
2134
0
  CHECK(!sc->client_cert_engine_provided_);
2135
2136
0
  if (env->permission()->enabled()) [[unlikely]] {
2137
0
    return THROW_ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED(
2138
0
        env,
2139
0
        "Programmatic selection of OpenSSL engines is unsupported while the "
2140
0
        "experimental permission model is enabled");
2141
0
  }
2142
2143
0
  CryptoErrorList errors;
2144
0
  const Utf8Value engine_id(env->isolate(), args[0]);
2145
0
  auto engine = EnginePointer::getEngineByName(*engine_id, &errors);
2146
0
  if (!engine) {
2147
0
    Local<Value> exception;
2148
0
    if (errors.empty()) {
2149
0
      errors.add(getNodeCryptoErrorString(NodeCryptoError::ENGINE_NOT_FOUND,
2150
0
                                          *engine_id));
2151
0
    }
2152
0
    if (cryptoErrorListToException(env, errors).ToLocal(&exception))
2153
0
      env->isolate()->ThrowException(exception);
2154
0
    return;
2155
0
  }
2156
2157
  // Note that this takes another reference to `engine`.
2158
0
  if (!SSL_CTX_set_client_cert_engine(sc->ctx_.get(), engine.get()))
2159
0
    return ThrowCryptoError(env, ERR_get_error());
2160
0
  sc->client_cert_engine_provided_ = true;
2161
0
}
2162
#endif  // !OPENSSL_NO_ENGINE
2163
2164
0
void SecureContext::GetTicketKeys(const FunctionCallbackInfo<Value>& args) {
2165
0
  SecureContext* wrap;
2166
0
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.This());
2167
2168
0
  Local<Object> buff;
2169
0
  if (!Buffer::New(wrap->env(), 48).ToLocal(&buff))
2170
0
    return;
2171
2172
0
  memcpy(Buffer::Data(buff), wrap->ticket_key_name_, 16);
2173
0
  memcpy(Buffer::Data(buff) + 16, wrap->ticket_key_hmac_, 16);
2174
0
  memcpy(Buffer::Data(buff) + 32, wrap->ticket_key_aes_, 16);
2175
2176
0
  args.GetReturnValue().Set(buff);
2177
0
}
2178
2179
0
void SecureContext::SetTicketKeys(const FunctionCallbackInfo<Value>& args) {
2180
0
  SecureContext* wrap;
2181
0
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.This());
2182
2183
0
  CHECK_GE(args.Length(), 1);  // Ticket keys argument is mandatory
2184
0
  CHECK(args[0]->IsArrayBufferView());
2185
0
  ArrayBufferViewContents<char> buf(args[0].As<ArrayBufferView>());
2186
2187
0
  CHECK_EQ(buf.length(), 48);
2188
2189
0
  memcpy(wrap->ticket_key_name_, buf.data(), 16);
2190
0
  memcpy(wrap->ticket_key_hmac_, buf.data() + 16, 16);
2191
0
  memcpy(wrap->ticket_key_aes_, buf.data() + 32, 16);
2192
2193
0
  args.GetReturnValue().Set(true);
2194
0
}
2195
2196
// Currently, EnableTicketKeyCallback and TicketKeyCallback are only present for
2197
// the regression test in test/parallel/test-https-resume-after-renew.js.
2198
void SecureContext::EnableTicketKeyCallback(
2199
0
    const FunctionCallbackInfo<Value>& args) {
2200
0
  SecureContext* wrap;
2201
0
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.This());
2202
2203
0
  SSL_CTX_set_tlsext_ticket_key_cb(wrap->ctx_.get(), TicketKeyCallback);
2204
0
}
2205
2206
int SecureContext::TicketKeyCallback(SSL* ssl,
2207
                                     unsigned char* name,
2208
                                     unsigned char* iv,
2209
                                     EVP_CIPHER_CTX* ectx,
2210
                                     HMAC_CTX* hctx,
2211
0
                                     int enc) {
2212
0
  static const int kTicketPartSize = 16;
2213
2214
0
  SecureContext* sc = static_cast<SecureContext*>(
2215
0
      SSL_CTX_get_app_data(SSL_get_SSL_CTX(ssl)));
2216
2217
0
  Environment* env = sc->env();
2218
0
  HandleScope handle_scope(env->isolate());
2219
0
  Context::Scope context_scope(env->context());
2220
2221
0
  Local<Value> argv[3];
2222
2223
0
  if (!Buffer::Copy(
2224
0
          env,
2225
0
          reinterpret_cast<char*>(name),
2226
0
          kTicketPartSize).ToLocal(&argv[0]) ||
2227
0
      !Buffer::Copy(
2228
0
          env,
2229
0
          reinterpret_cast<char*>(iv),
2230
0
          kTicketPartSize).ToLocal(&argv[1])) {
2231
0
    return -1;
2232
0
  }
2233
2234
0
  argv[2] = Boolean::New(env->isolate(), enc != 0);
2235
2236
0
  Local<Value> ret;
2237
0
  if (!node::MakeCallback(
2238
0
          env->isolate(),
2239
0
          sc->object(),
2240
0
          env->ticketkeycallback_string(),
2241
0
          arraysize(argv),
2242
0
          argv,
2243
0
          {0, 0}).ToLocal(&ret) ||
2244
0
      !ret->IsArray()) {
2245
0
    return -1;
2246
0
  }
2247
0
  Local<Array> arr = ret.As<Array>();
2248
2249
0
  Local<Value> val;
2250
0
  if (!arr->Get(env->context(), kTicketKeyReturnIndex).ToLocal(&val) ||
2251
0
      !val->IsInt32()) {
2252
0
    return -1;
2253
0
  }
2254
2255
0
  int r = val.As<Int32>()->Value();
2256
0
  if (r < 0)
2257
0
    return r;
2258
2259
0
  Local<Value> hmac;
2260
0
  Local<Value> aes;
2261
2262
0
  if (!arr->Get(env->context(), kTicketKeyHMACIndex).ToLocal(&hmac) ||
2263
0
      !arr->Get(env->context(), kTicketKeyAESIndex).ToLocal(&aes) ||
2264
0
      Buffer::Length(aes) != kTicketPartSize) {
2265
0
    return -1;
2266
0
  }
2267
2268
0
  if (enc) {
2269
0
    Local<Value> name_val;
2270
0
    Local<Value> iv_val;
2271
0
    if (!arr->Get(env->context(), kTicketKeyNameIndex).ToLocal(&name_val) ||
2272
0
        !arr->Get(env->context(), kTicketKeyIVIndex).ToLocal(&iv_val) ||
2273
0
        Buffer::Length(name_val) != kTicketPartSize ||
2274
0
        Buffer::Length(iv_val) != kTicketPartSize) {
2275
0
      return -1;
2276
0
    }
2277
2278
0
    name_val.As<ArrayBufferView>()->CopyContents(name, kTicketPartSize);
2279
0
    iv_val.As<ArrayBufferView>()->CopyContents(iv, kTicketPartSize);
2280
0
  }
2281
2282
0
  ArrayBufferViewContents<unsigned char> hmac_buf(hmac);
2283
0
  HMAC_Init_ex(
2284
0
      hctx, hmac_buf.data(), hmac_buf.length(), Digest::SHA256, nullptr);
2285
2286
0
  ArrayBufferViewContents<unsigned char> aes_key(aes.As<ArrayBufferView>());
2287
0
  if (enc) {
2288
0
    EVP_EncryptInit_ex(ectx, Cipher::AES_128_CBC, nullptr, aes_key.data(), iv);
2289
0
  } else {
2290
0
    EVP_DecryptInit_ex(ectx, Cipher::AES_128_CBC, nullptr, aes_key.data(), iv);
2291
0
  }
2292
2293
0
  return r;
2294
0
}
2295
2296
int SecureContext::TicketCompatibilityCallback(SSL* ssl,
2297
                                               unsigned char* name,
2298
                                               unsigned char* iv,
2299
                                               EVP_CIPHER_CTX* ectx,
2300
                                               HMAC_CTX* hctx,
2301
0
                                               int enc) {
2302
0
  SecureContext* sc = static_cast<SecureContext*>(
2303
0
      SSL_CTX_get_app_data(SSL_get_SSL_CTX(ssl)));
2304
2305
0
  if (enc) {
2306
0
    memcpy(name, sc->ticket_key_name_, sizeof(sc->ticket_key_name_));
2307
0
    if (!ncrypto::CSPRNG(iv, 16) ||
2308
0
        EVP_EncryptInit_ex(
2309
0
            ectx, Cipher::AES_128_CBC, nullptr, sc->ticket_key_aes_, iv) <= 0 ||
2310
0
        HMAC_Init_ex(hctx,
2311
0
                     sc->ticket_key_hmac_,
2312
0
                     sizeof(sc->ticket_key_hmac_),
2313
0
                     Digest::SHA256,
2314
0
                     nullptr) <= 0) {
2315
0
      return -1;
2316
0
    }
2317
0
    return 1;
2318
0
  }
2319
2320
0
  if (memcmp(name, sc->ticket_key_name_, sizeof(sc->ticket_key_name_)) != 0) {
2321
    // The ticket key name does not match. Discard the ticket.
2322
0
    return 0;
2323
0
  }
2324
2325
0
  if (EVP_DecryptInit_ex(
2326
0
          ectx, Cipher::AES_128_CBC, nullptr, sc->ticket_key_aes_, iv) <= 0 ||
2327
0
      HMAC_Init_ex(hctx,
2328
0
                   sc->ticket_key_hmac_,
2329
0
                   sizeof(sc->ticket_key_hmac_),
2330
0
                   Digest::SHA256,
2331
0
                   nullptr) <= 0) {
2332
0
    return -1;
2333
0
  }
2334
0
  return 1;
2335
0
}
2336
2337
0
void SecureContext::CtxGetter(const FunctionCallbackInfo<Value>& info) {
2338
0
  SecureContext* sc;
2339
0
  ASSIGN_OR_RETURN_UNWRAP(&sc, info.This());
2340
0
  Local<External> ext = External::New(info.GetIsolate(), sc->ctx_.get());
2341
0
  info.GetReturnValue().Set(ext);
2342
0
}
2343
2344
template <bool primary>
2345
0
void SecureContext::GetCertificate(const FunctionCallbackInfo<Value>& args) {
2346
0
  SecureContext* wrap;
2347
0
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.This());
2348
0
  Environment* env = wrap->env();
2349
0
  X509* cert;
2350
2351
0
  if (primary)
2352
0
    cert = wrap->cert_.get();
2353
0
  else
2354
0
    cert = wrap->issuer_.get();
2355
0
  if (cert == nullptr)
2356
0
    return args.GetReturnValue().SetNull();
2357
2358
0
  int size = i2d_X509(cert, nullptr);
2359
0
  Local<Object> buff;
2360
0
  if (!Buffer::New(env, size).ToLocal(&buff))
2361
0
    return;
2362
0
  unsigned char* serialized = reinterpret_cast<unsigned char*>(
2363
0
      Buffer::Data(buff));
2364
0
  i2d_X509(cert, &serialized);
2365
2366
0
  args.GetReturnValue().Set(buff);
2367
0
}
Unexecuted instantiation: void node::crypto::SecureContext::GetCertificate<true>(v8::FunctionCallbackInfo<v8::Value> const&)
Unexecuted instantiation: void node::crypto::SecureContext::GetCertificate<false>(v8::FunctionCallbackInfo<v8::Value> const&)
2368
2369
// UseExtraCaCerts is called only once at the start of the Node.js process.
2370
0
void UseExtraCaCerts(std::string_view file) {
2371
0
  extra_root_certs_file = file;
2372
0
}
2373
2374
}  // namespace crypto
2375
}  // namespace node