GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: crypto/crypto_util.cc Lines: 292 345 84.6 %
Date: 2022-11-04 03:21:42 Branches: 122 244 50.0 %

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
34332
MUST_USE_RESULT CSPRNGResult CSPRNG(void* buffer, size_t length) {
64
  do {
65
34332
    if (1 == RAND_status())
66
34332
      if (1 == RAND_bytes(static_cast<unsigned char*>(buffer), length))
67
34332
        return {true};
68
  } while (1 == RAND_poll());
69
70
  return {false};
71
}
72
73
112
int PasswordCallback(char* buf, int size, int rwflag, void* u) {
74
112
  const ByteSource* passphrase = *static_cast<const ByteSource**>(u);
75
112
  if (passphrase != nullptr) {
76
92
    size_t buflen = static_cast<size_t>(size);
77
92
    size_t len = passphrase->size();
78
92
    if (buflen < len)
79
2
      return -1;
80
90
    memcpy(buf, passphrase->data(), len);
81
90
    return len;
82
  }
83
84
20
  return -1;
85
}
86
87
// This callback is used to avoid the default passphrase callback in OpenSSL
88
// which will typically prompt for the passphrase. The prompting is designed
89
// for the OpenSSL CLI, but works poorly for Node.js because it involves
90
// synchronous interaction with the controlling terminal, something we never
91
// want, and use this function to avoid it.
92
int NoPasswordCallback(char* buf, int size, int rwflag, void* u) {
93
  return 0;
94
}
95
96
5601
bool ProcessFipsOptions() {
97
  /* Override FIPS settings in configuration file, if needed. */
98

11201
  if (per_process::cli_options->enable_fips_crypto ||
99
5600
      per_process::cli_options->force_fips_crypto) {
100
#if OPENSSL_VERSION_MAJOR >= 3
101
2
    OSSL_PROVIDER* fips_provider = OSSL_PROVIDER_load(nullptr, "fips");
102
2
    if (fips_provider == nullptr)
103
2
      return false;
104
    OSSL_PROVIDER_unload(fips_provider);
105
106
    return EVP_default_properties_enable_fips(nullptr, 1) &&
107
           EVP_default_properties_is_fips_enabled(nullptr);
108
#else
109
    return FIPS_mode() == 0 && FIPS_mode_set(1);
110
#endif
111
  }
112
5599
  return true;
113
}
114
115
6362
bool InitCryptoOnce(Isolate* isolate) {
116
  static uv_once_t init_once = UV_ONCE_INIT;
117
12724
  TryCatch try_catch{isolate};
118
6362
  uv_once(&init_once, InitCryptoOnce);
119

6362
  if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
120
    try_catch.ReThrow();
121
    return false;
122
  }
123
6362
  return true;
124
}
125
126
// Protect accesses to FIPS state with a mutex. This should potentially
127
// be part of a larger mutex for global OpenSSL state.
128
static Mutex fips_mutex;
129
130
5596
void InitCryptoOnce() {
131
11192
  Mutex::ScopedLock lock(per_process::cli_options_mutex);
132
11192
  Mutex::ScopedLock fips_lock(fips_mutex);
133
#ifndef OPENSSL_IS_BORINGSSL
134
5596
  OPENSSL_INIT_SETTINGS* settings = OPENSSL_INIT_new();
135
136
#if OPENSSL_VERSION_MAJOR < 3
137
  // --openssl-config=...
138
  if (!per_process::cli_options->openssl_config.empty()) {
139
    const char* conf = per_process::cli_options->openssl_config.c_str();
140
    OPENSSL_INIT_set_config_filename(settings, conf);
141
  }
142
#endif
143
144
#if OPENSSL_VERSION_MAJOR >= 3
145
  // --openssl-legacy-provider
146
5596
  if (per_process::cli_options->openssl_legacy_provider) {
147
1
    OSSL_PROVIDER* legacy_provider = OSSL_PROVIDER_load(nullptr, "legacy");
148
1
    if (legacy_provider == nullptr) {
149
      fprintf(stderr, "Unable to load legacy provider.\n");
150
    }
151
  }
152
#endif
153
154
5596
  OPENSSL_init_ssl(0, settings);
155
5596
  OPENSSL_INIT_free(settings);
156
5596
  settings = nullptr;
157
158
#ifndef _WIN32
159
5596
  if (per_process::cli_options->secure_heap != 0) {
160

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

5654
  CHECK_IMPLIES(size_ > 0, allocated_data_ != nullptr);
332
  std::unique_ptr<BackingStore> ptr = ArrayBuffer::NewBackingStore(
333
      allocated_data_,
334
      size(),
335
5649
      [](void* data, size_t length, void* deleter_data) {
336
5649
        OPENSSL_clear_free(deleter_data, length);
337
5654
      }, allocated_data_);
338
5654
  CHECK(ptr);
339
5654
  allocated_data_ = nullptr;
340
5654
  data_ = nullptr;
341
5654
  size_ = 0;
342
5654
  return ptr;
343
}
344
345
5654
Local<ArrayBuffer> ByteSource::ToArrayBuffer(Environment* env) {
346
5654
  std::unique_ptr<BackingStore> store = ReleaseToBackingStore();
347
5654
  return ArrayBuffer::New(env->isolate(), std::move(store));
348
}
349
350
17
MaybeLocal<Uint8Array> ByteSource::ToBuffer(Environment* env) {
351
17
  Local<ArrayBuffer> ab = ToArrayBuffer(env);
352
17
  return Buffer::New(env, ab, 0, ab->ByteLength());
353
}
354
355
517
ByteSource ByteSource::FromBIO(const BIOPointer& bio) {
356
517
  CHECK(bio);
357
  BUF_MEM* bptr;
358
517
  BIO_get_mem_ptr(bio.get(), &bptr);
359
517
  ByteSource::Builder out(bptr->length);
360
517
  memcpy(out.data<void>(), bptr->data, bptr->length);
361
517
  return std::move(out).release();
362
}
363
364
3111
ByteSource ByteSource::FromEncodedString(Environment* env,
365
                                         Local<String> key,
366
                                         enum encoding enc) {
367
3111
  size_t length = 0;
368
3111
  ByteSource out;
369
370

6222
  if (StringBytes::Size(env->isolate(), key, enc).To(&length) && length > 0) {
371
3111
    ByteSource::Builder buf(length);
372
    size_t actual =
373
3111
        StringBytes::Write(env->isolate(), buf.data<char>(), length, key, enc);
374
3111
    out = std::move(buf).release(actual);
375
  }
376
377
3111
  return out;
378
}
379
380
2718
ByteSource ByteSource::FromStringOrBuffer(Environment* env,
381
                                          Local<Value> value) {
382
2718
  return IsAnyByteSource(value) ? FromBuffer(value)
383
2718
                                : FromString(env, value.As<String>());
384
}
385
386
24
ByteSource ByteSource::FromString(Environment* env, Local<String> str,
387
                                  bool ntc) {
388
48
  CHECK(str->IsString());
389
24
  size_t size = str->Utf8Length(env->isolate());
390
24
  size_t alloc_size = ntc ? size + 1 : size;
391
24
  ByteSource::Builder out(alloc_size);
392
24
  int opts = String::NO_OPTIONS;
393
24
  if (!ntc) opts |= String::NO_NULL_TERMINATION;
394
24
  str->WriteUtf8(env->isolate(), out.data<char>(), alloc_size, nullptr, opts);
395
24
  return std::move(out).release();
396
}
397
398
2720
ByteSource ByteSource::FromBuffer(Local<Value> buffer, bool ntc) {
399
2720
  ArrayBufferOrViewContents<char> buf(buffer);
400
2720
  return ntc ? buf.ToNullTerminatedCopy() : buf.ToByteSource();
401
}
402
403
1560
ByteSource ByteSource::FromSecretKeyBytes(
404
    Environment* env,
405
    Local<Value> value) {
406
  // A key can be passed as a string, buffer or KeyObject with type 'secret'.
407
  // If it is a string, we need to convert it to a buffer. We are not doing that
408
  // in JS to avoid creating an unprotected copy on the heap.
409

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









98
    switch (ERR_GET_LIB(err)) { OSSL_ERROR_CODES_MAP(V) }
521
#undef V
522
#undef OSSL_ERROR_CODES_MAP
523
    // Don't generate codes like "ERR_OSSL_SSL_".
524

98
    if (lib && strcmp(lib, "SSL_") == 0)
525
6
      prefix = "";
526
527
    // All OpenSSL reason strings fit in a single 80-column macro definition,
528
    // all prefix lengths are <= 10, and ERR_OSSL_ is 9, so 128 is more than
529
    // sufficient.
530
    char code[128];
531
98
    snprintf(code, sizeof(code), "ERR_%s%s%s", prefix, lib, reason.c_str());
532
533
196
    if (obj->Set(env->isolate()->GetCurrentContext(),
534
             env->code_string(),
535
392
             OneByteString(env->isolate(), code)).IsNothing())
536
      return Nothing<bool>();
537
  }
538
539
98
  return Just(true);
540
}
541
}  // namespace error
542
543
110
void ThrowCryptoError(Environment* env,
544
                      unsigned long err,  // NOLINT(runtime/int)
545
                      // Default, only used if there is no SSL `err` which can
546
                      // be used to create a long-style message string.
547
                      const char* message) {
548
110
  char message_buffer[128] = {0};
549

110
  if (err != 0 || message == nullptr) {
550
99
    ERR_error_string_n(err, message_buffer, sizeof(message_buffer));
551
99
    message = message_buffer;
552
  }
553
110
  HandleScope scope(env->isolate());
554
  Local<String> exception_string;
555
  Local<Value> exception;
556
  Local<Object> obj;
557
220
  if (!String::NewFromUtf8(env->isolate(), message).ToLocal(&exception_string))
558
    return;
559
110
  CryptoErrorStore errors;
560
110
  errors.Capture();
561
110
  if (!errors.ToException(env, exception_string).ToLocal(&exception) ||
562

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

330
      error::Decorate(env, obj, err).IsNothing()) {
564
1
    return;
565
  }
566
109
  env->isolate()->ThrowException(exception);
567
}
568
569
#ifndef OPENSSL_NO_ENGINE
570
11
EnginePointer LoadEngineById(const char* id, CryptoErrorStore* errors) {
571
22
  MarkPopErrorOnReturn mark_pop_error_on_return;
572
573
11
  EnginePointer engine(ENGINE_by_id(id));
574
11
  if (!engine) {
575
    // Engine not found, try loading dynamically.
576
2
    engine = EnginePointer(ENGINE_by_id("dynamic"));
577
2
    if (engine) {
578

4
      if (!ENGINE_ctrl_cmd_string(engine.get(), "SO_PATH", id, 0) ||
579
2
          !ENGINE_ctrl_cmd_string(engine.get(), "LOAD", nullptr, 0)) {
580
2
        engine.reset();
581
      }
582
    }
583
  }
584
585

11
  if (!engine && errors != nullptr) {
586
    errors->Capture();
587
    if (errors->Empty()) {
588
      errors->Insert(NodeCryptoError::ENGINE_NOT_FOUND, id);
589
    }
590
  }
591
592
11
  return engine;
593
}
594
595
11
bool SetEngine(const char* id, uint32_t flags, CryptoErrorStore* errors) {
596
11
  ClearErrorOnReturn clear_error_on_return;
597
22
  EnginePointer engine = LoadEngineById(id, errors);
598
11
  if (!engine)
599
2
    return false;
600
601
9
  if (!ENGINE_set_default(engine.get(), flags)) {
602
    if (errors != nullptr)
603
      errors->Capture();
604
    return false;
605
  }
606
607
9
  return true;
608
}
609
610
11
void SetEngine(const FunctionCallbackInfo<Value>& args) {
611
11
  Environment* env = Environment::GetCurrent(args);
612

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