GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/crypto/crypto_util.cc Lines: 54 294 18.4 %
Date: 2021-02-19 04:08:54 Branches: 9 218 4.1 %

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
namespace node {
18
19
using v8::ArrayBuffer;
20
using v8::BackingStore;
21
using v8::BigInt;
22
using v8::Context;
23
using v8::Exception;
24
using v8::FunctionCallbackInfo;
25
using v8::HandleScope;
26
using v8::Isolate;
27
using v8::Just;
28
using v8::Local;
29
using v8::Maybe;
30
using v8::MaybeLocal;
31
using v8::NewStringType;
32
using v8::Nothing;
33
using v8::Object;
34
using v8::String;
35
using v8::Uint32;
36
using v8::Uint8Array;
37
using v8::Value;
38
39
namespace crypto {
40
6
int VerifyCallback(int preverify_ok, X509_STORE_CTX* ctx) {
41
  // From https://www.openssl.org/docs/man1.1.1/man3/SSL_verify_cb:
42
  //
43
  //   If VerifyCallback returns 1, the verification process is continued. If
44
  //   VerifyCallback always returns 1, the TLS/SSL handshake will not be
45
  //   terminated with respect to verification failures and the connection will
46
  //   be established. The calling process can however retrieve the error code
47
  //   of the last verification error using SSL_get_verify_result(3) or by
48
  //   maintaining its own error storage managed by VerifyCallback.
49
  //
50
  // Since we cannot perform I/O quickly enough with X509_STORE_CTX_ APIs in
51
  // this callback, we ignore all preverify_ok errors and let the handshake
52
  // continue. It is imperative that the user use Connection::VerifyError after
53
  // the 'secure' callback has been made.
54
6
  return 1;
55
}
56
57
318
void CheckEntropy() {
58
  for (;;) {
59
318
    int status = RAND_status();
60
318
    CHECK_GE(status, 0);  // Cannot fail.
61
318
    if (status != 0)
62
636
      break;
63
64
    // Give up, RAND_poll() not supported.
65
    if (RAND_poll() == 0)
66
      break;
67
  }
68
318
}
69
70
314
bool EntropySource(unsigned char* buffer, size_t length) {
71
  // Ensure that OpenSSL's PRNG is properly seeded.
72
314
  CheckEntropy();
73
  // RAND_bytes() can return 0 to indicate that the entropy data is not truly
74
  // random. That's okay, it's still better than V8's stock source of entropy,
75
  // which is /dev/urandom on UNIX platforms and the current time on Windows.
76
314
  return RAND_bytes(buffer, length) != -1;
77
}
78
79
int PasswordCallback(char* buf, int size, int rwflag, void* u) {
80
  const ByteSource* passphrase = *static_cast<const ByteSource**>(u);
81
  if (passphrase != nullptr) {
82
    size_t buflen = static_cast<size_t>(size);
83
    size_t len = passphrase->size();
84
    if (buflen < len)
85
      return -1;
86
    memcpy(buf, passphrase->get(), len);
87
    return len;
88
  }
89
90
  return -1;
91
}
92
93
// This callback is used to avoid the default passphrase callback in OpenSSL
94
// which will typically prompt for the passphrase. The prompting is designed
95
// for the OpenSSL CLI, but works poorly for Node.js because it involves
96
// synchronous interaction with the controlling terminal, something we never
97
// want, and use this function to avoid it.
98
int NoPasswordCallback(char* buf, int size, int rwflag, void* u) {
99
  return 0;
100
}
101
102
2
void InitCryptoOnce() {
103
#ifndef OPENSSL_IS_BORINGSSL
104
2
  OPENSSL_INIT_SETTINGS* settings = OPENSSL_INIT_new();
105
106
  // --openssl-config=...
107
2
  if (!per_process::cli_options->openssl_config.empty()) {
108
    const char* conf = per_process::cli_options->openssl_config.c_str();
109
    OPENSSL_INIT_set_config_filename(settings, conf);
110
  }
111
112
2
  OPENSSL_init_ssl(0, settings);
113
2
  OPENSSL_INIT_free(settings);
114
2
  settings = nullptr;
115
#endif
116
117
#ifndef _WIN32
118
2
  if (per_process::cli_options->secure_heap != 0) {
119
    switch (CRYPTO_secure_malloc_init(
120
                per_process::cli_options->secure_heap,
121
                static_cast<int>(per_process::cli_options->secure_heap_min))) {
122
      case 0:
123
        fprintf(stderr, "Unable to initialize openssl secure heap.\n");
124
        break;
125
      case 2:
126
        // Not a fatal error but worthy of a warning.
127
        fprintf(stderr, "Unable to memory map openssl secure heap.\n");
128
        break;
129
      case 1:
130
        // OK!
131
        break;
132
    }
133
  }
134
#endif
135
136
#ifdef NODE_FIPS_MODE
137
  /* Override FIPS settings in cnf file, if needed. */
138
  unsigned long err = 0;  // NOLINT(runtime/int)
139
  if (per_process::cli_options->enable_fips_crypto ||
140
      per_process::cli_options->force_fips_crypto) {
141
    if (0 == FIPS_mode() && !FIPS_mode_set(1)) {
142
      err = ERR_get_error();
143
    }
144
  }
145
  if (0 != err) {
146
    fprintf(stderr,
147
            "openssl fips failed: %s\n",
148
            ERR_error_string(err, nullptr));
149
    UNREACHABLE();
150
  }
151
#endif  // NODE_FIPS_MODE
152
153
  // Turn off compression. Saves memory and protects against CRIME attacks.
154
  // No-op with OPENSSL_NO_COMP builds of OpenSSL.
155
2
  sk_SSL_COMP_zero(SSL_COMP_get_compression_methods());
156
157
#ifndef OPENSSL_NO_ENGINE
158
2
  ERR_load_ENGINE_strings();
159
2
  ENGINE_load_builtin_engines();
160
#endif  // !OPENSSL_NO_ENGINE
161
162
2
  NodeBIO::GetMethod();
163
2
}
164
165
#ifdef NODE_FIPS_MODE
166
void GetFipsCrypto(const FunctionCallbackInfo<Value>& args) {
167
  args.GetReturnValue().Set(FIPS_mode() ? 1 : 0);
168
}
169
170
void SetFipsCrypto(const FunctionCallbackInfo<Value>& args) {
171
  CHECK(!per_process::cli_options->force_fips_crypto);
172
  Environment* env = Environment::GetCurrent(args);
173
  bool enable = args[0]->BooleanValue(env->isolate());
174
175
  if (enable == FIPS_mode())
176
    return;  // No action needed.
177
178
  if (!FIPS_mode_set(enable)) {
179
    unsigned long err = ERR_get_error();  // NOLINT(runtime/int)
180
    return ThrowCryptoError(env, err);
181
  }
182
}
183
#endif /* NODE_FIPS_MODE */
184
185
void CryptoErrorVector::Capture() {
186
  clear();
187
  while (auto err = ERR_get_error()) {
188
    char buf[256];
189
    ERR_error_string_n(err, buf, sizeof(buf));
190
    push_back(buf);
191
  }
192
  std::reverse(begin(), end());
193
}
194
195
MaybeLocal<Value> CryptoErrorVector::ToException(
196
    Environment* env,
197
    Local<String> exception_string) const {
198
  if (exception_string.IsEmpty()) {
199
    CryptoErrorVector copy(*this);
200
    if (copy.empty()) copy.push_back("no error");  // But possibly a bug...
201
    // Use last element as the error message, everything else goes
202
    // into the .opensslErrorStack property on the exception object.
203
    Local<String> exception_string;
204
    if (!String::NewFromUtf8(
205
            env->isolate(),
206
            copy.back().data(),
207
            NewStringType::kNormal,
208
            copy.back().size()).ToLocal(&exception_string)) {
209
      return MaybeLocal<Value>();
210
    }
211
    copy.pop_back();
212
    return copy.ToException(env, exception_string);
213
  }
214
215
  Local<Value> exception_v = Exception::Error(exception_string);
216
  CHECK(!exception_v.IsEmpty());
217
218
  if (!empty()) {
219
    CHECK(exception_v->IsObject());
220
    Local<Object> exception = exception_v.As<Object>();
221
    Local<Value> stack;
222
    if (!ToV8Value(env->context(), *this).ToLocal(&stack) ||
223
        exception->Set(env->context(), env->openssl_error_stack(), stack)
224
            .IsNothing()) {
225
      return MaybeLocal<Value>();
226
    }
227
  }
228
229
  return exception_v;
230
}
231
232
ByteSource::ByteSource(ByteSource&& other) noexcept
233
    : data_(other.data_),
234
      allocated_data_(other.allocated_data_),
235
      size_(other.size_) {
236
  other.allocated_data_ = nullptr;
237
}
238
239
56814
ByteSource::~ByteSource() {
240
28407
  OPENSSL_clear_free(allocated_data_, size_);
241
28407
}
242
243
void ByteSource::reset() {
244
  OPENSSL_clear_free(allocated_data_, size_);
245
  data_ = nullptr;
246
  size_ = 0;
247
}
248
249
14216
ByteSource& ByteSource::operator=(ByteSource&& other) noexcept {
250
14216
  if (&other != this) {
251
14216
    OPENSSL_clear_free(allocated_data_, size_);
252
14216
    data_ = other.data_;
253
14216
    allocated_data_ = other.allocated_data_;
254
14216
    other.allocated_data_ = nullptr;
255
14216
    size_ = other.size_;
256
  }
257
14216
  return *this;
258
}
259
260
std::unique_ptr<BackingStore> ByteSource::ReleaseToBackingStore() {
261
  // It's ok for allocated_data_ to be nullptr but
262
  // only if size_ is zero.
263
  CHECK_IMPLIES(size_ > 0, allocated_data_ != nullptr);
264
  std::unique_ptr<BackingStore> ptr = ArrayBuffer::NewBackingStore(
265
      allocated_data_,
266
      size(),
267
      [](void* data, size_t length, void* deleter_data) {
268
        OPENSSL_clear_free(deleter_data, length);
269
      }, allocated_data_);
270
  CHECK(ptr);
271
  allocated_data_ = nullptr;
272
  data_ = nullptr;
273
  size_ = 0;
274
  return ptr;
275
}
276
277
Local<ArrayBuffer> ByteSource::ToArrayBuffer(Environment* env) {
278
  std::unique_ptr<BackingStore> store = ReleaseToBackingStore();
279
  return ArrayBuffer::New(env->isolate(), std::move(store));
280
}
281
282
14224
const char* ByteSource::get() const {
283
14224
  return data_;
284
}
285
286
size_t ByteSource::size() const {
287
  return size_;
288
}
289
290
ByteSource ByteSource::FromBIO(const BIOPointer& bio) {
291
  CHECK(bio);
292
  BUF_MEM* bptr;
293
  BIO_get_mem_ptr(bio.get(), &bptr);
294
  char* data = MallocOpenSSL<char>(bptr->length);
295
  memcpy(data, bptr->data, bptr->length);
296
  return Allocated(data, bptr->length);
297
}
298
299
ByteSource ByteSource::FromEncodedString(Environment* env,
300
                                         Local<String> key,
301
                                         enum encoding enc) {
302
  size_t length = 0;
303
  size_t actual = 0;
304
  char* data = nullptr;
305
306
  if (StringBytes::Size(env->isolate(), key, enc).To(&length) && length > 0) {
307
    data = MallocOpenSSL<char>(length);
308
    actual = StringBytes::Write(env->isolate(), data, length, key, enc);
309
310
    CHECK(actual <= length);
311
312
    if (actual == 0) {
313
      OPENSSL_clear_free(data, length);
314
      data = nullptr;
315
    } else if (actual < length) {
316
      data = reinterpret_cast<char*>(OPENSSL_realloc(data, actual));
317
    }
318
  }
319
320
  return Allocated(data, actual);
321
}
322
323
ByteSource ByteSource::FromStringOrBuffer(Environment* env,
324
                                          Local<Value> value) {
325
  return IsAnyByteSource(value) ? FromBuffer(value)
326
                                : FromString(env, value.As<String>());
327
}
328
329
ByteSource ByteSource::FromString(Environment* env, Local<String> str,
330
                                  bool ntc) {
331
  CHECK(str->IsString());
332
  size_t size = str->Utf8Length(env->isolate());
333
  size_t alloc_size = ntc ? size + 1 : size;
334
  char* data = MallocOpenSSL<char>(alloc_size);
335
  int opts = String::NO_OPTIONS;
336
  if (!ntc) opts |= String::NO_NULL_TERMINATION;
337
  str->WriteUtf8(env->isolate(), data, alloc_size, nullptr, opts);
338
  return Allocated(data, size);
339
}
340
341
ByteSource ByteSource::FromBuffer(Local<Value> buffer, bool ntc) {
342
  ArrayBufferOrViewContents<char> buf(buffer);
343
  return ntc ? buf.ToNullTerminatedCopy() : buf.ToByteSource();
344
}
345
346
ByteSource ByteSource::FromSecretKeyBytes(
347
    Environment* env,
348
    Local<Value> value) {
349
  // A key can be passed as a string, buffer or KeyObject with type 'secret'.
350
  // If it is a string, we need to convert it to a buffer. We are not doing that
351
  // in JS to avoid creating an unprotected copy on the heap.
352
  return value->IsString() || IsAnyByteSource(value) ?
353
           ByteSource::FromStringOrBuffer(env, value) :
354
           ByteSource::FromSymmetricKeyObjectHandle(value);
355
}
356
357
ByteSource ByteSource::NullTerminatedCopy(Environment* env,
358
                                          Local<Value> value) {
359
  return Buffer::HasInstance(value) ? FromBuffer(value, true)
360
                                    : FromString(env, value.As<String>(), true);
361
}
362
363
ByteSource ByteSource::FromSymmetricKeyObjectHandle(Local<Value> handle) {
364
  CHECK(handle->IsObject());
365
  KeyObjectHandle* key = Unwrap<KeyObjectHandle>(handle.As<Object>());
366
  CHECK_NOT_NULL(key);
367
  return Foreign(key->Data()->GetSymmetricKey(),
368
                 key->Data()->GetSymmetricKeySize());
369
}
370
371
14224
ByteSource::ByteSource(const char* data, char* allocated_data, size_t size)
372
    : data_(data),
373
      allocated_data_(allocated_data),
374
14224
      size_(size) {}
375
376
14224
ByteSource ByteSource::Allocated(char* data, size_t size) {
377
14224
  return ByteSource(data, data, size);
378
}
379
380
ByteSource ByteSource::Foreign(const char* data, size_t size) {
381
  return ByteSource(data, nullptr, size);
382
}
383
384
namespace error {
385
Maybe<bool> Decorate(Environment* env, Local<Object> obj,
386
              unsigned long err) {  // NOLINT(runtime/int)
387
  if (err == 0) return Just(true);  // No decoration necessary.
388
389
  const char* ls = ERR_lib_error_string(err);
390
  const char* fs = ERR_func_error_string(err);
391
  const char* rs = ERR_reason_error_string(err);
392
393
  Isolate* isolate = env->isolate();
394
  Local<Context> context = isolate->GetCurrentContext();
395
396
  if (ls != nullptr) {
397
    if (obj->Set(context, env->library_string(),
398
                 OneByteString(isolate, ls)).IsNothing()) {
399
      return Nothing<bool>();
400
    }
401
  }
402
  if (fs != nullptr) {
403
    if (obj->Set(context, env->function_string(),
404
                 OneByteString(isolate, fs)).IsNothing()) {
405
      return Nothing<bool>();
406
    }
407
  }
408
  if (rs != nullptr) {
409
    if (obj->Set(context, env->reason_string(),
410
                 OneByteString(isolate, rs)).IsNothing()) {
411
      return Nothing<bool>();
412
    }
413
414
    // SSL has no API to recover the error name from the number, so we
415
    // transform reason strings like "this error" to "ERR_SSL_THIS_ERROR",
416
    // which ends up being close to the original error macro name.
417
    std::string reason(rs);
418
419
    for (auto& c : reason) {
420
      if (c == ' ')
421
        c = '_';
422
      else
423
        c = ToUpper(c);
424
    }
425
426
#define OSSL_ERROR_CODES_MAP(V)                                               \
427
    V(SYS)                                                                    \
428
    V(BN)                                                                     \
429
    V(RSA)                                                                    \
430
    V(DH)                                                                     \
431
    V(EVP)                                                                    \
432
    V(BUF)                                                                    \
433
    V(OBJ)                                                                    \
434
    V(PEM)                                                                    \
435
    V(DSA)                                                                    \
436
    V(X509)                                                                   \
437
    V(ASN1)                                                                   \
438
    V(CONF)                                                                   \
439
    V(CRYPTO)                                                                 \
440
    V(EC)                                                                     \
441
    V(SSL)                                                                    \
442
    V(BIO)                                                                    \
443
    V(PKCS7)                                                                  \
444
    V(X509V3)                                                                 \
445
    V(PKCS12)                                                                 \
446
    V(RAND)                                                                   \
447
    V(DSO)                                                                    \
448
    V(ENGINE)                                                                 \
449
    V(OCSP)                                                                   \
450
    V(UI)                                                                     \
451
    V(COMP)                                                                   \
452
    V(ECDSA)                                                                  \
453
    V(ECDH)                                                                   \
454
    V(OSSL_STORE)                                                             \
455
    V(FIPS)                                                                   \
456
    V(CMS)                                                                    \
457
    V(TS)                                                                     \
458
    V(HMAC)                                                                   \
459
    V(CT)                                                                     \
460
    V(ASYNC)                                                                  \
461
    V(KDF)                                                                    \
462
    V(SM2)                                                                    \
463
    V(USER)                                                                   \
464
465
#define V(name) case ERR_LIB_##name: lib = #name "_"; break;
466
    const char* lib = "";
467
    const char* prefix = "OSSL_";
468
    switch (ERR_GET_LIB(err)) { OSSL_ERROR_CODES_MAP(V) }
469
#undef V
470
#undef OSSL_ERROR_CODES_MAP
471
    // Don't generate codes like "ERR_OSSL_SSL_".
472
    if (lib && strcmp(lib, "SSL_") == 0)
473
      prefix = "";
474
475
    // All OpenSSL reason strings fit in a single 80-column macro definition,
476
    // all prefix lengths are <= 10, and ERR_OSSL_ is 9, so 128 is more than
477
    // sufficient.
478
    char code[128];
479
    snprintf(code, sizeof(code), "ERR_%s%s%s", prefix, lib, reason.c_str());
480
481
    if (obj->Set(env->isolate()->GetCurrentContext(),
482
             env->code_string(),
483
             OneByteString(env->isolate(), code)).IsNothing())
484
      return Nothing<bool>();
485
  }
486
487
  return Just(true);
488
}
489
}  // namespace error
490
491
void ThrowCryptoError(Environment* env,
492
                      unsigned long err,  // NOLINT(runtime/int)
493
                      // Default, only used if there is no SSL `err` which can
494
                      // be used to create a long-style message string.
495
                      const char* message) {
496
  char message_buffer[128] = {0};
497
  if (err != 0 || message == nullptr) {
498
    ERR_error_string_n(err, message_buffer, sizeof(message_buffer));
499
    message = message_buffer;
500
  }
501
  HandleScope scope(env->isolate());
502
  Local<String> exception_string;
503
  Local<Value> exception;
504
  Local<Object> obj;
505
  if (!String::NewFromUtf8(env->isolate(), message).ToLocal(&exception_string))
506
    return;
507
  CryptoErrorVector errors;
508
  errors.Capture();
509
  if (!errors.ToException(env, exception_string).ToLocal(&exception) ||
510
      !exception->ToObject(env->context()).ToLocal(&obj) ||
511
      error::Decorate(env, obj, err).IsNothing()) {
512
    return;
513
  }
514
  env->isolate()->ThrowException(exception);
515
}
516
517
#ifndef OPENSSL_NO_ENGINE
518
EnginePointer LoadEngineById(const char* id, CryptoErrorVector* errors) {
519
  MarkPopErrorOnReturn mark_pop_error_on_return;
520
521
  EnginePointer engine(ENGINE_by_id(id));
522
  if (!engine) {
523
    // Engine not found, try loading dynamically.
524
    engine = EnginePointer(ENGINE_by_id("dynamic"));
525
    if (engine) {
526
      if (!ENGINE_ctrl_cmd_string(engine.get(), "SO_PATH", id, 0) ||
527
          !ENGINE_ctrl_cmd_string(engine.get(), "LOAD", nullptr, 0)) {
528
        engine.reset();
529
      }
530
    }
531
  }
532
533
  if (!engine && errors != nullptr) {
534
    if (ERR_get_error() != 0) {
535
      errors->Capture();
536
    } else {
537
      errors->push_back(std::string("Engine \"") + id + "\" was not found");
538
    }
539
  }
540
541
  return engine;
542
}
543
544
bool SetEngine(const char* id, uint32_t flags, CryptoErrorVector* errors) {
545
  ClearErrorOnReturn clear_error_on_return;
546
  EnginePointer engine = LoadEngineById(id, errors);
547
  if (!engine)
548
    return false;
549
550
  if (!ENGINE_set_default(engine.get(), flags)) {
551
    if (errors != nullptr)
552
      errors->Capture();
553
    return false;
554
  }
555
556
  return true;
557
}
558
559
void SetEngine(const FunctionCallbackInfo<Value>& args) {
560
  Environment* env = Environment::GetCurrent(args);
561
  CHECK(args.Length() >= 2 && args[0]->IsString());
562
  uint32_t flags;
563
  if (!args[1]->Uint32Value(env->context()).To(&flags)) return;
564
565
  const node::Utf8Value engine_id(env->isolate(), args[0]);
566
567
  args.GetReturnValue().Set(SetEngine(*engine_id, flags));
568
}
569
#endif  // !OPENSSL_NO_ENGINE
570
571
MaybeLocal<Value> EncodeBignum(
572
    Environment* env,
573
    const BIGNUM* bn,
574
    int size,
575
    Local<Value>* error) {
576
  std::vector<uint8_t> buf(size);
577
  CHECK_EQ(BN_bn2binpad(bn, buf.data(), size), size);
578
  return StringBytes::Encode(
579
      env->isolate(),
580
      reinterpret_cast<const char*>(buf.data()),
581
      buf.size(),
582
      BASE64URL,
583
      error);
584
}
585
586
Maybe<bool> SetEncodedValue(
587
    Environment* env,
588
    Local<Object> target,
589
    Local<String> name,
590
    const BIGNUM* bn,
591
    int size) {
592
  Local<Value> value;
593
  Local<Value> error;
594
  CHECK_NOT_NULL(bn);
595
  if (size == 0)
596
    size = BN_num_bytes(bn);
597
  if (!EncodeBignum(env, bn, size, &error).ToLocal(&value)) {
598
    if (!error.IsEmpty())
599
      env->isolate()->ThrowException(error);
600
    return Nothing<bool>();
601
  }
602
  return target->Set(env->context(), name, value);
603
}
604
605
4
CryptoJobMode GetCryptoJobMode(v8::Local<v8::Value> args) {
606
4
  CHECK(args->IsUint32());
607
8
  uint32_t mode = args.As<v8::Uint32>()->Value();
608
4
  CHECK_LE(mode, kCryptoJobSync);
609
4
  return static_cast<CryptoJobMode>(mode);
610
}
611
612
namespace {
613
// SecureBuffer uses openssl to allocate a Uint8Array using
614
// OPENSSL_secure_malloc. Because we do not yet actually
615
// make use of secure heap, this has the same semantics as
616
// using OPENSSL_malloc. However, if the secure heap is
617
// initialized, SecureBuffer will automatically use it.
618
void SecureBuffer(const FunctionCallbackInfo<Value>& args) {
619
  CHECK(args[0]->IsUint32());
620
  Environment* env = Environment::GetCurrent(args);
621
  uint32_t len = args[0].As<Uint32>()->Value();
622
  char* data = static_cast<char*>(OPENSSL_secure_malloc(len));
623
  if (data == nullptr) {
624
    // There's no memory available for the allocation.
625
    // Return nothing.
626
    return;
627
  }
628
  memset(data, 0, len);
629
  std::shared_ptr<BackingStore> store =
630
      ArrayBuffer::NewBackingStore(
631
          data,
632
          len,
633
          [](void* data, size_t len, void* deleter_data) {
634
            OPENSSL_secure_clear_free(data, len);
635
          },
636
          data);
637
  Local<ArrayBuffer> buffer = ArrayBuffer::New(env->isolate(), store);
638
  args.GetReturnValue().Set(Uint8Array::New(buffer, 0, len));
639
}
640
641
void SecureHeapUsed(const FunctionCallbackInfo<Value>& args) {
642
  Environment* env = Environment::GetCurrent(args);
643
  if (CRYPTO_secure_malloc_initialized())
644
    args.GetReturnValue().Set(
645
        BigInt::New(env->isolate(), CRYPTO_secure_used()));
646
}
647
}  // namespace
648
649
namespace Util {
650
2
void Initialize(Environment* env, Local<Object> target) {
651
#ifndef OPENSSL_NO_ENGINE
652
2
  env->SetMethod(target, "setEngine", SetEngine);
653
#endif  // !OPENSSL_NO_ENGINE
654
655
#ifdef NODE_FIPS_MODE
656
  env->SetMethodNoSideEffect(target, "getFipsCrypto", GetFipsCrypto);
657
  env->SetMethod(target, "setFipsCrypto", SetFipsCrypto);
658
#endif
659
660
8
  NODE_DEFINE_CONSTANT(target, kCryptoJobAsync);
661
2
  NODE_DEFINE_CONSTANT(target, kCryptoJobSync);
662
4
663
4
  env->SetMethod(target, "secureBuffer", SecureBuffer);
664
12
  env->SetMethod(target, "secureHeapUsed", SecureHeapUsed);
665
6
}
666
}  // namespace Util
667
668
}  // namespace crypto
669

366
}  // namespace node