GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: crypto/crypto_util.cc Lines: 291 347 83.9 %
Date: 2022-01-19 04:14:09 Branches: 120 242 49.6 %

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

9837
  if (per_process::cli_options->enable_fips_crypto ||
112
4918
      per_process::cli_options->force_fips_crypto) {
113
#if OPENSSL_VERSION_MAJOR >= 3
114
2
    OSSL_PROVIDER* fips_provider = OSSL_PROVIDER_load(nullptr, "fips");
115
2
    if (fips_provider == nullptr)
116
2
      return false;
117
    OSSL_PROVIDER_unload(fips_provider);
118
119
    return EVP_default_properties_enable_fips(nullptr, 1) &&
120
           EVP_default_properties_is_fips_enabled(nullptr);
121
#else
122
    return FIPS_mode() == 0 && FIPS_mode_set(1);
123
#endif
124
  }
125
4917
  return true;
126
}
127
128
4359
bool InitCryptoOnce(Isolate* isolate) {
129
  static uv_once_t init_once = UV_ONCE_INIT;
130
8718
  TryCatch try_catch{isolate};
131
4359
  uv_once(&init_once, InitCryptoOnce);
132

4359
  if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
133
    try_catch.ReThrow();
134
    return false;
135
  }
136
4359
  return true;
137
}
138
139
4209
void InitCryptoOnce() {
140
#ifndef OPENSSL_IS_BORINGSSL
141
4209
  OPENSSL_INIT_SETTINGS* settings = OPENSSL_INIT_new();
142
143
#if OPENSSL_VERSION_MAJOR < 3
144
  // --openssl-config=...
145
  if (!per_process::cli_options->openssl_config.empty()) {
146
    const char* conf = per_process::cli_options->openssl_config.c_str();
147
    OPENSSL_INIT_set_config_filename(settings, conf);
148
  }
149
#endif
150
151
#if OPENSSL_VERSION_MAJOR >= 3
152
  // --openssl-legacy-provider
153
4209
  if (per_process::cli_options->openssl_legacy_provider) {
154
    OSSL_PROVIDER* legacy_provider = OSSL_PROVIDER_load(nullptr, "legacy");
155
    if (legacy_provider == nullptr) {
156
      fprintf(stderr, "Unable to load legacy provider.\n");
157
    }
158
  }
159
#endif
160
161
4209
  OPENSSL_init_ssl(0, settings);
162
4209
  OPENSSL_INIT_free(settings);
163
4209
  settings = nullptr;
164
165
#ifndef _WIN32
166
4209
  if (per_process::cli_options->secure_heap != 0) {
167

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

2953
  CHECK_IMPLIES(size_ > 0, allocated_data_ != nullptr);
335
  std::unique_ptr<BackingStore> ptr = ArrayBuffer::NewBackingStore(
336
2953
      allocated_data_,
337
      size(),
338
2948
      [](void* data, size_t length, void* deleter_data) {
339
2948
        OPENSSL_clear_free(deleter_data, length);
340
2953
      }, allocated_data_);
341
2953
  CHECK(ptr);
342
2953
  allocated_data_ = nullptr;
343
2953
  data_ = nullptr;
344
2953
  size_ = 0;
345
2953
  return ptr;
346
}
347
348
2953
Local<ArrayBuffer> ByteSource::ToArrayBuffer(Environment* env) {
349
2953
  std::unique_ptr<BackingStore> store = ReleaseToBackingStore();
350
2953
  return ArrayBuffer::New(env->isolate(), std::move(store));
351
}
352
353
17
MaybeLocal<Uint8Array> ByteSource::ToBuffer(Environment* env) {
354
17
  Local<ArrayBuffer> ab = ToArrayBuffer(env);
355
17
  return Buffer::New(env, ab, 0, ab->ByteLength());
356
}
357
358
19678
const char* ByteSource::get() const {
359
19678
  return data_;
360
}
361
362
25423
size_t ByteSource::size() const {
363
25423
  return size_;
364
}
365
366
505
ByteSource ByteSource::FromBIO(const BIOPointer& bio) {
367
505
  CHECK(bio);
368
  BUF_MEM* bptr;
369
505
  BIO_get_mem_ptr(bio.get(), &bptr);
370
505
  char* data = MallocOpenSSL<char>(bptr->length);
371
505
  memcpy(data, bptr->data, bptr->length);
372
505
  return Allocated(data, bptr->length);
373
}
374
375
3111
ByteSource ByteSource::FromEncodedString(Environment* env,
376
                                         Local<String> key,
377
                                         enum encoding enc) {
378
3111
  size_t length = 0;
379
3111
  size_t actual = 0;
380
3111
  char* data = nullptr;
381
382

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

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









90
    switch (ERR_GET_LIB(err)) { OSSL_ERROR_CODES_MAP(V) }
545
#undef V
546
#undef OSSL_ERROR_CODES_MAP
547
    // Don't generate codes like "ERR_OSSL_SSL_".
548

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

102
  if (err != 0 || message == nullptr) {
574
91
    ERR_error_string_n(err, message_buffer, sizeof(message_buffer));
575
91
    message = message_buffer;
576
  }
577
102
  HandleScope scope(env->isolate());
578
  Local<String> exception_string;
579
  Local<Value> exception;
580
  Local<Object> obj;
581
204
  if (!String::NewFromUtf8(env->isolate(), message).ToLocal(&exception_string))
582
    return;
583
102
  CryptoErrorStore errors;
584
102
  errors.Capture();
585
102
  if (!errors.ToException(env, exception_string).ToLocal(&exception) ||
586

408
      !exception->ToObject(env->context()).ToLocal(&obj) ||
587

306
      error::Decorate(env, obj, err).IsNothing()) {
588
1
    return;
589
  }
590
101
  env->isolate()->ThrowException(exception);
591
}
592
593
#ifndef OPENSSL_NO_ENGINE
594
11
EnginePointer LoadEngineById(const char* id, CryptoErrorStore* errors) {
595
22
  MarkPopErrorOnReturn mark_pop_error_on_return;
596
597
11
  EnginePointer engine(ENGINE_by_id(id));
598
11
  if (!engine) {
599
    // Engine not found, try loading dynamically.
600
2
    engine = EnginePointer(ENGINE_by_id("dynamic"));
601
2
    if (engine) {
602

4
      if (!ENGINE_ctrl_cmd_string(engine.get(), "SO_PATH", id, 0) ||
603
2
          !ENGINE_ctrl_cmd_string(engine.get(), "LOAD", nullptr, 0)) {
604
2
        engine.reset();
605
      }
606
    }
607
  }
608
609

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

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