GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: crypto/crypto_util.cc Lines: 289 339 85.3 %
Date: 2022-09-07 04:19:57 Branches: 118 238 49.6 %

Line Branch Exec Source
1
#include "crypto/crypto_util.h"
2
#include "async_wrap-inl.h"
3
#include "crypto/crypto_bio.h"
4
#include "crypto/crypto_keys.h"
5
#include "env-inl.h"
6
#include "memory_tracker-inl.h"
7
#include "node_buffer.h"
8
#include "node_options-inl.h"
9
#include "string_bytes.h"
10
#include "threadpoolwork-inl.h"
11
#include "util-inl.h"
12
#include "v8.h"
13
14
#include "math.h"
15
16
#if OPENSSL_VERSION_MAJOR >= 3
17
#include "openssl/provider.h"
18
#endif
19
20
#include <openssl/rand.h>
21
22
namespace node {
23
24
using v8::ArrayBuffer;
25
using v8::BackingStore;
26
using v8::BigInt;
27
using v8::Context;
28
using v8::Exception;
29
using v8::FunctionCallbackInfo;
30
using v8::HandleScope;
31
using v8::Isolate;
32
using v8::Just;
33
using v8::Local;
34
using v8::Maybe;
35
using v8::MaybeLocal;
36
using v8::NewStringType;
37
using v8::Nothing;
38
using v8::Object;
39
using v8::String;
40
using v8::TryCatch;
41
using v8::Uint32;
42
using v8::Uint8Array;
43
using v8::Value;
44
45
namespace crypto {
46
2248
int VerifyCallback(int preverify_ok, X509_STORE_CTX* ctx) {
47
  // From https://www.openssl.org/docs/man1.1.1/man3/SSL_verify_cb:
48
  //
49
  //   If VerifyCallback returns 1, the verification process is continued. If
50
  //   VerifyCallback always returns 1, the TLS/SSL handshake will not be
51
  //   terminated with respect to verification failures and the connection will
52
  //   be established. The calling process can however retrieve the error code
53
  //   of the last verification error using SSL_get_verify_result(3) or by
54
  //   maintaining its own error storage managed by VerifyCallback.
55
  //
56
  // Since we cannot perform I/O quickly enough with X509_STORE_CTX_ APIs in
57
  // this callback, we ignore all preverify_ok errors and let the handshake
58
  // continue. It is imperative that the user use Connection::VerifyError after
59
  // the 'secure' callback has been made.
60
2248
  return 1;
61
}
62
63
21594
void CheckEntropy() {
64
  for (;;) {
65
21594
    int status = RAND_status();
66
21594
    CHECK_GE(status, 0);  // Cannot fail.
67
21594
    if (status != 0)
68
21594
      break;
69
70
    // Give up, RAND_poll() not supported.
71
    if (RAND_poll() == 0)
72
      break;
73
  }
74
21594
}
75
76
19175
bool EntropySource(unsigned char* buffer, size_t length) {
77
  // Ensure that OpenSSL's PRNG is properly seeded.
78
19175
  CheckEntropy();
79
  // If RAND_bytes() returns 0 or -1, the data might not be random at all. In
80
  // that case, return false, which causes V8 to use its own entropy source. The
81
  // quality of V8's entropy source depends on multiple factors and we should
82
  // not assume that it is cryptographically secure (even though it often is).
83
  // However, even if RAND_bytes() fails and V8 resorts to its potentially weak
84
  // entropy source, it really does not matter much: V8 only uses the entropy
85
  // source to seed its own PRNG, which itself is not cryptographically secure.
86
  // In other words, even a cryptographically secure entropy source would not
87
  // guarantee cryptographically secure random numbers in V8.
88
19175
  return RAND_bytes(buffer, length) == 1;
89
}
90
91
111
int PasswordCallback(char* buf, int size, int rwflag, void* u) {
92
111
  const ByteSource* passphrase = *static_cast<const ByteSource**>(u);
93
111
  if (passphrase != nullptr) {
94
91
    size_t buflen = static_cast<size_t>(size);
95
91
    size_t len = passphrase->size();
96
91
    if (buflen < len)
97
2
      return -1;
98
89
    memcpy(buf, passphrase->data(), len);
99
89
    return len;
100
  }
101
102
20
  return -1;
103
}
104
105
// This callback is used to avoid the default passphrase callback in OpenSSL
106
// which will typically prompt for the passphrase. The prompting is designed
107
// for the OpenSSL CLI, but works poorly for Node.js because it involves
108
// synchronous interaction with the controlling terminal, something we never
109
// want, and use this function to avoid it.
110
int NoPasswordCallback(char* buf, int size, int rwflag, void* u) {
111
  return 0;
112
}
113
114
5488
bool ProcessFipsOptions() {
115
  /* Override FIPS settings in configuration file, if needed. */
116

10975
  if (per_process::cli_options->enable_fips_crypto ||
117
5487
      per_process::cli_options->force_fips_crypto) {
118
#if OPENSSL_VERSION_MAJOR >= 3
119
2
    OSSL_PROVIDER* fips_provider = OSSL_PROVIDER_load(nullptr, "fips");
120
2
    if (fips_provider == nullptr)
121
2
      return false;
122
    OSSL_PROVIDER_unload(fips_provider);
123
124
    return EVP_default_properties_enable_fips(nullptr, 1) &&
125
           EVP_default_properties_is_fips_enabled(nullptr);
126
#else
127
    return FIPS_mode() == 0 && FIPS_mode_set(1);
128
#endif
129
  }
130
5486
  return true;
131
}
132
133
6246
bool InitCryptoOnce(Isolate* isolate) {
134
  static uv_once_t init_once = UV_ONCE_INIT;
135
12492
  TryCatch try_catch{isolate};
136
6246
  uv_once(&init_once, InitCryptoOnce);
137

6246
  if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
138
    try_catch.ReThrow();
139
    return false;
140
  }
141
6246
  return true;
142
}
143
144
// Protect accesses to FIPS state with a mutex. This should potentially
145
// be part of a larger mutex for global OpenSSL state.
146
static Mutex fips_mutex;
147
148
5483
void InitCryptoOnce() {
149
10966
  Mutex::ScopedLock lock(per_process::cli_options_mutex);
150
10966
  Mutex::ScopedLock fips_lock(fips_mutex);
151
#ifndef OPENSSL_IS_BORINGSSL
152
5483
  OPENSSL_INIT_SETTINGS* settings = OPENSSL_INIT_new();
153
154
#if OPENSSL_VERSION_MAJOR < 3
155
  // --openssl-config=...
156
  if (!per_process::cli_options->openssl_config.empty()) {
157
    const char* conf = per_process::cli_options->openssl_config.c_str();
158
    OPENSSL_INIT_set_config_filename(settings, conf);
159
  }
160
#endif
161
162
#if OPENSSL_VERSION_MAJOR >= 3
163
  // --openssl-legacy-provider
164
5483
  if (per_process::cli_options->openssl_legacy_provider) {
165
1
    OSSL_PROVIDER* legacy_provider = OSSL_PROVIDER_load(nullptr, "legacy");
166
1
    if (legacy_provider == nullptr) {
167
      fprintf(stderr, "Unable to load legacy provider.\n");
168
    }
169
  }
170
#endif
171
172
5483
  OPENSSL_init_ssl(0, settings);
173
5483
  OPENSSL_INIT_free(settings);
174
5483
  settings = nullptr;
175
176
#ifndef _WIN32
177
5483
  if (per_process::cli_options->secure_heap != 0) {
178

1
    switch (CRYPTO_secure_malloc_init(
179
1
                per_process::cli_options->secure_heap,
180
1
                static_cast<int>(per_process::cli_options->secure_heap_min))) {
181
      case 0:
182
        fprintf(stderr, "Unable to initialize openssl secure heap.\n");
183
        break;
184
      case 2:
185
        // Not a fatal error but worthy of a warning.
186
        fprintf(stderr, "Unable to memory map openssl secure heap.\n");
187
        break;
188
1
      case 1:
189
        // OK!
190
1
        break;
191
    }
192
  }
193
#endif
194
195
#endif  // OPENSSL_IS_BORINGSSL
196
197
  // Turn off compression. Saves memory and protects against CRIME attacks.
198
  // No-op with OPENSSL_NO_COMP builds of OpenSSL.
199
5483
  sk_SSL_COMP_zero(SSL_COMP_get_compression_methods());
200
201
#ifndef OPENSSL_NO_ENGINE
202
5483
  ERR_load_ENGINE_strings();
203
5483
  ENGINE_load_builtin_engines();
204
#endif  // !OPENSSL_NO_ENGINE
205
206
5483
  NodeBIO::GetMethod();
207
5483
}
208
209
214
void GetFipsCrypto(const FunctionCallbackInfo<Value>& args) {
210
428
  Mutex::ScopedLock lock(per_process::cli_options_mutex);
211
214
  Mutex::ScopedLock fips_lock(fips_mutex);
212
213
#if OPENSSL_VERSION_MAJOR >= 3
214
428
  args.GetReturnValue().Set(EVP_default_properties_is_fips_enabled(nullptr) ?
215
      1 : 0);
216
#else
217
  args.GetReturnValue().Set(FIPS_mode() ? 1 : 0);
218
#endif
219
214
}
220
221
void SetFipsCrypto(const FunctionCallbackInfo<Value>& args) {
222
  Mutex::ScopedLock lock(per_process::cli_options_mutex);
223
  Mutex::ScopedLock fips_lock(fips_mutex);
224
225
  CHECK(!per_process::cli_options->force_fips_crypto);
226
  Environment* env = Environment::GetCurrent(args);
227
  CHECK(env->owns_process_state());
228
  bool enable = args[0]->BooleanValue(env->isolate());
229
230
#if OPENSSL_VERSION_MAJOR >= 3
231
  if (enable == EVP_default_properties_is_fips_enabled(nullptr))
232
#else
233
  if (static_cast<int>(enable) == FIPS_mode())
234
#endif
235
    return;  // No action needed.
236
237
#if OPENSSL_VERSION_MAJOR >= 3
238
  if (!EVP_default_properties_enable_fips(nullptr, enable)) {
239
#else
240
  if (!FIPS_mode_set(enable)) {
241
#endif
242
    unsigned long err = ERR_get_error();  // NOLINT(runtime/int)
243
    return ThrowCryptoError(env, err);
244
  }
245
}
246
247
5
void TestFipsCrypto(const v8::FunctionCallbackInfo<v8::Value>& args) {
248
10
  Mutex::ScopedLock lock(per_process::cli_options_mutex);
249
5
  Mutex::ScopedLock fips_lock(fips_mutex);
250
251
#ifdef OPENSSL_FIPS
252
#if OPENSSL_VERSION_MAJOR >= 3
253
  OSSL_PROVIDER* fips_provider = nullptr;
254
  if (OSSL_PROVIDER_available(nullptr, "fips")) {
255
    fips_provider = OSSL_PROVIDER_load(nullptr, "fips");
256
  }
257
  const auto enabled = fips_provider == nullptr ? 0 :
258
      OSSL_PROVIDER_self_test(fips_provider) ? 1 : 0;
259
#else
260
  const auto enabled = FIPS_selftest() ? 1 : 0;
261
#endif
262
#else  // OPENSSL_FIPS
263
5
  const auto enabled = 0;
264
#endif  // OPENSSL_FIPS
265
266
10
  args.GetReturnValue().Set(enabled);
267
5
}
268
269
1612
void CryptoErrorStore::Capture() {
270
1612
  errors_.clear();
271
1805
  while (const uint32_t err = ERR_get_error()) {
272
    char buf[256];
273
193
    ERR_error_string_n(err, buf, sizeof(buf));
274
193
    errors_.emplace_back(buf);
275
193
  }
276
1612
  std::reverse(std::begin(errors_), std::end(errors_));
277
1612
}
278
279
9578
bool CryptoErrorStore::Empty() const {
280
9578
  return errors_.empty();
281
}
282
283
404
MaybeLocal<Value> CryptoErrorStore::ToException(
284
    Environment* env,
285
    Local<String> exception_string) const {
286
404
  if (exception_string.IsEmpty()) {
287
294
    CryptoErrorStore copy(*this);
288
147
    if (copy.Empty()) {
289
      // But possibly a bug...
290
      copy.Insert(NodeCryptoError::OK);
291
    }
292
    // Use last element as the error message, everything else goes
293
    // into the .opensslErrorStack property on the exception object.
294
147
    const std::string& last_error_string = copy.errors_.back();
295
    Local<String> exception_string;
296
147
    if (!String::NewFromUtf8(
297
            env->isolate(),
298
            last_error_string.data(),
299
            NewStringType::kNormal,
300
294
            last_error_string.size()).ToLocal(&exception_string)) {
301
      return MaybeLocal<Value>();
302
    }
303
147
    copy.errors_.pop_back();
304
147
    return copy.ToException(env, exception_string);
305
  }
306
307
257
  Local<Value> exception_v = Exception::Error(exception_string);
308
257
  CHECK(!exception_v.IsEmpty());
309
310
257
  if (!Empty()) {
311
32
    CHECK(exception_v->IsObject());
312
32
    Local<Object> exception = exception_v.As<Object>();
313
    Local<Value> stack;
314
96
    if (!ToV8Value(env->context(), errors_).ToLocal(&stack) ||
315
96
        exception->Set(env->context(), env->openssl_error_stack(), stack)
316
32
            .IsNothing()) {
317
      return MaybeLocal<Value>();
318
    }
319
  }
320
321
257
  return exception_v;
322
}
323
324
33933
ByteSource::ByteSource(ByteSource&& other) noexcept
325
33933
    : data_(other.data_),
326
33933
      allocated_data_(other.allocated_data_),
327
67866
      size_(other.size_) {
328
33933
  other.allocated_data_ = nullptr;
329
33933
}
330
331
208180
ByteSource::~ByteSource() {
332
104090
  OPENSSL_clear_free(allocated_data_, size_);
333
104090
}
334
335
24697
ByteSource& ByteSource::operator=(ByteSource&& other) noexcept {
336
24697
  if (&other != this) {
337
24697
    OPENSSL_clear_free(allocated_data_, size_);
338
24697
    data_ = other.data_;
339
24697
    allocated_data_ = other.allocated_data_;
340
24697
    other.allocated_data_ = nullptr;
341
24697
    size_ = other.size_;
342
  }
343
24697
  return *this;
344
}
345
346
5651
std::unique_ptr<BackingStore> ByteSource::ReleaseToBackingStore() {
347
  // It's ok for allocated_data_ to be nullptr but
348
  // only if size_ is zero.
349

5651
  CHECK_IMPLIES(size_ > 0, allocated_data_ != nullptr);
350
  std::unique_ptr<BackingStore> ptr = ArrayBuffer::NewBackingStore(
351
      allocated_data_,
352
      size(),
353
5646
      [](void* data, size_t length, void* deleter_data) {
354
5646
        OPENSSL_clear_free(deleter_data, length);
355
5651
      }, allocated_data_);
356
5651
  CHECK(ptr);
357
5651
  allocated_data_ = nullptr;
358
5651
  data_ = nullptr;
359
5651
  size_ = 0;
360
5651
  return ptr;
361
}
362
363
5651
Local<ArrayBuffer> ByteSource::ToArrayBuffer(Environment* env) {
364
5651
  std::unique_ptr<BackingStore> store = ReleaseToBackingStore();
365
5651
  return ArrayBuffer::New(env->isolate(), std::move(store));
366
}
367
368
17
MaybeLocal<Uint8Array> ByteSource::ToBuffer(Environment* env) {
369
17
  Local<ArrayBuffer> ab = ToArrayBuffer(env);
370
17
  return Buffer::New(env, ab, 0, ab->ByteLength());
371
}
372
373
517
ByteSource ByteSource::FromBIO(const BIOPointer& bio) {
374
517
  CHECK(bio);
375
  BUF_MEM* bptr;
376
517
  BIO_get_mem_ptr(bio.get(), &bptr);
377
517
  ByteSource::Builder out(bptr->length);
378
517
  memcpy(out.data<void>(), bptr->data, bptr->length);
379
517
  return std::move(out).release();
380
}
381
382
3111
ByteSource ByteSource::FromEncodedString(Environment* env,
383
                                         Local<String> key,
384
                                         enum encoding enc) {
385
3111
  size_t length = 0;
386
3111
  ByteSource out;
387
388

6222
  if (StringBytes::Size(env->isolate(), key, enc).To(&length) && length > 0) {
389
3111
    ByteSource::Builder buf(length);
390
    size_t actual =
391
3111
        StringBytes::Write(env->isolate(), buf.data<char>(), length, key, enc);
392
3111
    out = std::move(buf).release(actual);
393
  }
394
395
3111
  return out;
396
}
397
398
2718
ByteSource ByteSource::FromStringOrBuffer(Environment* env,
399
                                          Local<Value> value) {
400
2718
  return IsAnyByteSource(value) ? FromBuffer(value)
401
2718
                                : FromString(env, value.As<String>());
402
}
403
404
24
ByteSource ByteSource::FromString(Environment* env, Local<String> str,
405
                                  bool ntc) {
406
48
  CHECK(str->IsString());
407
24
  size_t size = str->Utf8Length(env->isolate());
408
24
  size_t alloc_size = ntc ? size + 1 : size;
409
24
  ByteSource::Builder out(alloc_size);
410
24
  int opts = String::NO_OPTIONS;
411
24
  if (!ntc) opts |= String::NO_NULL_TERMINATION;
412
24
  str->WriteUtf8(env->isolate(), out.data<char>(), alloc_size, nullptr, opts);
413
24
  return std::move(out).release();
414
}
415
416
2720
ByteSource ByteSource::FromBuffer(Local<Value> buffer, bool ntc) {
417
2720
  ArrayBufferOrViewContents<char> buf(buffer);
418
2720
  return ntc ? buf.ToNullTerminatedCopy() : buf.ToByteSource();
419
}
420
421
1560
ByteSource ByteSource::FromSecretKeyBytes(
422
    Environment* env,
423
    Local<Value> value) {
424
  // A key can be passed as a string, buffer or KeyObject with type 'secret'.
425
  // If it is a string, we need to convert it to a buffer. We are not doing that
426
  // in JS to avoid creating an unprotected copy on the heap.
427

3120
  return value->IsString() || IsAnyByteSource(value) ?
428
           ByteSource::FromStringOrBuffer(env, value) :
429
1560
           ByteSource::FromSymmetricKeyObjectHandle(value);
430
}
431
432
ByteSource ByteSource::NullTerminatedCopy(Environment* env,
433
                                          Local<Value> value) {
434
  return Buffer::HasInstance(value) ? FromBuffer(value, true)
435
                                    : FromString(env, value.As<String>(), true);
436
}
437
438
15
ByteSource ByteSource::FromSymmetricKeyObjectHandle(Local<Value> handle) {
439
15
  CHECK(handle->IsObject());
440
15
  KeyObjectHandle* key = Unwrap<KeyObjectHandle>(handle.As<Object>());
441
15
  CHECK_NOT_NULL(key);
442
15
  return Foreign(key->Data()->GetSymmetricKey(),
443
30
                 key->Data()->GetSymmetricKeySize());
444
}
445
446
26190
ByteSource ByteSource::Allocated(void* data, size_t size) {
447
26190
  return ByteSource(data, data, size);
448
}
449
450
5163
ByteSource ByteSource::Foreign(const void* data, size_t size) {
451
5163
  return ByteSource(data, nullptr, size);
452
}
453
454
namespace error {
455
110
Maybe<bool> Decorate(Environment* env, Local<Object> obj,
456
              unsigned long err) {  // NOLINT(runtime/int)
457
110
  if (err == 0) return Just(true);  // No decoration necessary.
458
459
99
  const char* ls = ERR_lib_error_string(err);
460
99
  const char* fs = ERR_func_error_string(err);
461
99
  const char* rs = ERR_reason_error_string(err);
462
463
99
  Isolate* isolate = env->isolate();
464
99
  Local<Context> context = isolate->GetCurrentContext();
465
466
99
  if (ls != nullptr) {
467
198
    if (obj->Set(context, env->library_string(),
468
396
                 OneByteString(isolate, ls)).IsNothing()) {
469
1
      return Nothing<bool>();
470
    }
471
  }
472
98
  if (fs != nullptr) {
473
    if (obj->Set(context, env->function_string(),
474
                 OneByteString(isolate, fs)).IsNothing()) {
475
      return Nothing<bool>();
476
    }
477
  }
478
98
  if (rs != nullptr) {
479
196
    if (obj->Set(context, env->reason_string(),
480
392
                 OneByteString(isolate, rs)).IsNothing()) {
481
      return Nothing<bool>();
482
    }
483
484
    // SSL has no API to recover the error name from the number, so we
485
    // transform reason strings like "this error" to "ERR_SSL_THIS_ERROR",
486
    // which ends up being close to the original error macro name.
487
98
    std::string reason(rs);
488
489
1826
    for (auto& c : reason) {
490
1728
      if (c == ' ')
491
183
        c = '_';
492
      else
493
1545
        c = ToUpper(c);
494
    }
495
496
#define OSSL_ERROR_CODES_MAP(V)                                               \
497
    V(SYS)                                                                    \
498
    V(BN)                                                                     \
499
    V(RSA)                                                                    \
500
    V(DH)                                                                     \
501
    V(EVP)                                                                    \
502
    V(BUF)                                                                    \
503
    V(OBJ)                                                                    \
504
    V(PEM)                                                                    \
505
    V(DSA)                                                                    \
506
    V(X509)                                                                   \
507
    V(ASN1)                                                                   \
508
    V(CONF)                                                                   \
509
    V(CRYPTO)                                                                 \
510
    V(EC)                                                                     \
511
    V(SSL)                                                                    \
512
    V(BIO)                                                                    \
513
    V(PKCS7)                                                                  \
514
    V(X509V3)                                                                 \
515
    V(PKCS12)                                                                 \
516
    V(RAND)                                                                   \
517
    V(DSO)                                                                    \
518
    V(ENGINE)                                                                 \
519
    V(OCSP)                                                                   \
520
    V(UI)                                                                     \
521
    V(COMP)                                                                   \
522
    V(ECDSA)                                                                  \
523
    V(ECDH)                                                                   \
524
    V(OSSL_STORE)                                                             \
525
    V(FIPS)                                                                   \
526
    V(CMS)                                                                    \
527
    V(TS)                                                                     \
528
    V(HMAC)                                                                   \
529
    V(CT)                                                                     \
530
    V(ASYNC)                                                                  \
531
    V(KDF)                                                                    \
532
    V(SM2)                                                                    \
533
    V(USER)                                                                   \
534
535
#define V(name) case ERR_LIB_##name: lib = #name "_"; break;
536
98
    const char* lib = "";
537
98
    const char* prefix = "OSSL_";
538









98
    switch (ERR_GET_LIB(err)) { OSSL_ERROR_CODES_MAP(V) }
539
#undef V
540
#undef OSSL_ERROR_CODES_MAP
541
    // Don't generate codes like "ERR_OSSL_SSL_".
542

98
    if (lib && strcmp(lib, "SSL_") == 0)
543
6
      prefix = "";
544
545
    // All OpenSSL reason strings fit in a single 80-column macro definition,
546
    // all prefix lengths are <= 10, and ERR_OSSL_ is 9, so 128 is more than
547
    // sufficient.
548
    char code[128];
549
98
    snprintf(code, sizeof(code), "ERR_%s%s%s", prefix, lib, reason.c_str());
550
551
196
    if (obj->Set(env->isolate()->GetCurrentContext(),
552
             env->code_string(),
553
392
             OneByteString(env->isolate(), code)).IsNothing())
554
      return Nothing<bool>();
555
  }
556
557
98
  return Just(true);
558
}
559
}  // namespace error
560
561
110
void ThrowCryptoError(Environment* env,
562
                      unsigned long err,  // NOLINT(runtime/int)
563
                      // Default, only used if there is no SSL `err` which can
564
                      // be used to create a long-style message string.
565
                      const char* message) {
566
110
  char message_buffer[128] = {0};
567

110
  if (err != 0 || message == nullptr) {
568
99
    ERR_error_string_n(err, message_buffer, sizeof(message_buffer));
569
99
    message = message_buffer;
570
  }
571
110
  HandleScope scope(env->isolate());
572
  Local<String> exception_string;
573
  Local<Value> exception;
574
  Local<Object> obj;
575
220
  if (!String::NewFromUtf8(env->isolate(), message).ToLocal(&exception_string))
576
    return;
577
110
  CryptoErrorStore errors;
578
110
  errors.Capture();
579
110
  if (!errors.ToException(env, exception_string).ToLocal(&exception) ||
580

440
      !exception->ToObject(env->context()).ToLocal(&obj) ||
581

330
      error::Decorate(env, obj, err).IsNothing()) {
582
1
    return;
583
  }
584
109
  env->isolate()->ThrowException(exception);
585
}
586
587
#ifndef OPENSSL_NO_ENGINE
588
11
EnginePointer LoadEngineById(const char* id, CryptoErrorStore* errors) {
589
22
  MarkPopErrorOnReturn mark_pop_error_on_return;
590
591
11
  EnginePointer engine(ENGINE_by_id(id));
592
11
  if (!engine) {
593
    // Engine not found, try loading dynamically.
594
2
    engine = EnginePointer(ENGINE_by_id("dynamic"));
595
2
    if (engine) {
596

4
      if (!ENGINE_ctrl_cmd_string(engine.get(), "SO_PATH", id, 0) ||
597
2
          !ENGINE_ctrl_cmd_string(engine.get(), "LOAD", nullptr, 0)) {
598
2
        engine.reset();
599
      }
600
    }
601
  }
602
603

11
  if (!engine && errors != nullptr) {
604
    errors->Capture();
605
    if (errors->Empty()) {
606
      errors->Insert(NodeCryptoError::ENGINE_NOT_FOUND, id);
607
    }
608
  }
609
610
11
  return engine;
611
}
612
613
11
bool SetEngine(const char* id, uint32_t flags, CryptoErrorStore* errors) {
614
11
  ClearErrorOnReturn clear_error_on_return;
615
22
  EnginePointer engine = LoadEngineById(id, errors);
616
11
  if (!engine)
617
2
    return false;
618
619
9
  if (!ENGINE_set_default(engine.get(), flags)) {
620
    if (errors != nullptr)
621
      errors->Capture();
622
    return false;
623
  }
624
625
9
  return true;
626
}
627
628
11
void SetEngine(const FunctionCallbackInfo<Value>& args) {
629
11
  Environment* env = Environment::GetCurrent(args);
630

33
  CHECK(args.Length() >= 2 && args[0]->IsString());
631
  uint32_t flags;
632
22
  if (!args[1]->Uint32Value(env->context()).To(&flags)) return;
633
634
11
  const node::Utf8Value engine_id(env->isolate(), args[0]);
635
636
22
  args.GetReturnValue().Set(SetEngine(*engine_id, flags));
637
}
638
#endif  // !OPENSSL_NO_ENGINE
639
640
2593
MaybeLocal<Value> EncodeBignum(
641
    Environment* env,
642
    const BIGNUM* bn,
643
    int size,
644
    Local<Value>* error) {
645
5186
  std::vector<uint8_t> buf(size);
646
2593
  CHECK_EQ(BN_bn2binpad(bn, buf.data(), size), size);
647
  return StringBytes::Encode(
648
      env->isolate(),
649
2593
      reinterpret_cast<const char*>(buf.data()),
650
      buf.size(),
651
      BASE64URL,
652
5186
      error);
653
}
654
655
2593
Maybe<bool> SetEncodedValue(
656
    Environment* env,
657
    Local<Object> target,
658
    Local<String> name,
659
    const BIGNUM* bn,
660
    int size) {
661
  Local<Value> value;
662
  Local<Value> error;
663
2593
  CHECK_NOT_NULL(bn);
664
2593
  if (size == 0)
665
2084
    size = BN_num_bytes(bn);
666
5186
  if (!EncodeBignum(env, bn, size, &error).ToLocal(&value)) {
667
    if (!error.IsEmpty())
668
      env->isolate()->ThrowException(error);
669
    return Nothing<bool>();
670
  }
671
2593
  return target->Set(env->context(), name, value);
672
}
673
674
9440
CryptoJobMode GetCryptoJobMode(v8::Local<v8::Value> args) {
675
9440
  CHECK(args->IsUint32());
676
9440
  uint32_t mode = args.As<v8::Uint32>()->Value();
677
9440
  CHECK_LE(mode, kCryptoJobSync);
678
9440
  return static_cast<CryptoJobMode>(mode);
679
}
680
681
namespace {
682
// SecureBuffer uses OPENSSL_secure_malloc to allocate a Uint8Array.
683
// Without --secure-heap, OpenSSL's secure heap is disabled,
684
// in which case this has the same semantics as
685
// using OPENSSL_malloc. However, if the secure heap is
686
// initialized, SecureBuffer will automatically use it.
687
4
void SecureBuffer(const FunctionCallbackInfo<Value>& args) {
688
4
  CHECK(args[0]->IsUint32());
689
4
  Environment* env = Environment::GetCurrent(args);
690
8
  uint32_t len = args[0].As<Uint32>()->Value();
691
4
  void* data = OPENSSL_secure_zalloc(len);
692
4
  if (data == nullptr) {
693
    // There's no memory available for the allocation.
694
    // Return nothing.
695
    return;
696
  }
697
  std::shared_ptr<BackingStore> store =
698
4
      ArrayBuffer::NewBackingStore(
699
          data,
700
          len,
701
4
          [](void* data, size_t len, void* deleter_data) {
702
4
            OPENSSL_secure_clear_free(data, len);
703
4
          },
704
4
          data);
705
4
  Local<ArrayBuffer> buffer = ArrayBuffer::New(env->isolate(), store);
706
8
  args.GetReturnValue().Set(Uint8Array::New(buffer, 0, len));
707
}
708
709
4
void SecureHeapUsed(const FunctionCallbackInfo<Value>& args) {
710
4
  Environment* env = Environment::GetCurrent(args);
711
4
  if (CRYPTO_secure_malloc_initialized())
712
8
    args.GetReturnValue().Set(
713
4
        BigInt::New(env->isolate(), CRYPTO_secure_used()));
714
4
}
715
}  // namespace
716
717
namespace Util {
718
780
void Initialize(Environment* env, Local<Object> target) {
719
780
  Local<Context> context = env->context();
720
#ifndef OPENSSL_NO_ENGINE
721
780
  SetMethod(context, target, "setEngine", SetEngine);
722
#endif  // !OPENSSL_NO_ENGINE
723
724
780
  SetMethodNoSideEffect(context, target, "getFipsCrypto", GetFipsCrypto);
725
780
  SetMethod(context, target, "setFipsCrypto", SetFipsCrypto);
726
780
  SetMethodNoSideEffect(context, target, "testFipsCrypto", TestFipsCrypto);
727
728
2340
  NODE_DEFINE_CONSTANT(target, kCryptoJobAsync);
729
1560
  NODE_DEFINE_CONSTANT(target, kCryptoJobSync);
730
731
780
  SetMethod(context, target, "secureBuffer", SecureBuffer);
732
780
  SetMethod(context, target, "secureHeapUsed", SecureHeapUsed);
733
780
}
734
5473
void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
735
#ifndef OPENSSL_NO_ENGINE
736
5473
  registry->Register(SetEngine);
737
#endif  // !OPENSSL_NO_ENGINE
738
739
5473
  registry->Register(GetFipsCrypto);
740
5473
  registry->Register(SetFipsCrypto);
741
5473
  registry->Register(TestFipsCrypto);
742
5473
  registry->Register(SecureBuffer);
743
5473
  registry->Register(SecureHeapUsed);
744
5473
}
745
746
}  // namespace Util
747
748
}  // namespace crypto
749
}  // namespace node