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: 291 329 88.4 %
Date: 2021-06-07 04:11:51 Branches: 132 240 55.0 %

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
#ifdef OPENSSL_FIPS
18
#if OPENSSL_VERSION_MAJOR >= 3
19
#include "openssl/provider.h"
20
#endif
21
#endif
22
23
#include <openssl/rand.h>
24
25
namespace node {
26
27
using v8::ArrayBuffer;
28
using v8::BackingStore;
29
using v8::BigInt;
30
using v8::Context;
31
using v8::Exception;
32
using v8::FunctionCallbackInfo;
33
using v8::HandleScope;
34
using v8::Isolate;
35
using v8::Just;
36
using v8::Local;
37
using v8::Maybe;
38
using v8::MaybeLocal;
39
using v8::NewStringType;
40
using v8::Nothing;
41
using v8::Object;
42
using v8::String;
43
using v8::Uint32;
44
using v8::Uint8Array;
45
using v8::Value;
46
47
namespace crypto {
48
2146
int VerifyCallback(int preverify_ok, X509_STORE_CTX* ctx) {
49
  // From https://www.openssl.org/docs/man1.1.1/man3/SSL_verify_cb:
50
  //
51
  //   If VerifyCallback returns 1, the verification process is continued. If
52
  //   VerifyCallback always returns 1, the TLS/SSL handshake will not be
53
  //   terminated with respect to verification failures and the connection will
54
  //   be established. The calling process can however retrieve the error code
55
  //   of the last verification error using SSL_get_verify_result(3) or by
56
  //   maintaining its own error storage managed by VerifyCallback.
57
  //
58
  // Since we cannot perform I/O quickly enough with X509_STORE_CTX_ APIs in
59
  // this callback, we ignore all preverify_ok errors and let the handshake
60
  // continue. It is imperative that the user use Connection::VerifyError after
61
  // the 'secure' callback has been made.
62
2146
  return 1;
63
}
64
65
15728
void CheckEntropy() {
66
  for (;;) {
67
15728
    int status = RAND_status();
68
15728
    CHECK_GE(status, 0);  // Cannot fail.
69
15728
    if (status != 0)
70
31456
      break;
71
72
    // Give up, RAND_poll() not supported.
73
    if (RAND_poll() == 0)
74
      break;
75
  }
76
15728
}
77
78
15332
bool EntropySource(unsigned char* buffer, size_t length) {
79
  // Ensure that OpenSSL's PRNG is properly seeded.
80
15332
  CheckEntropy();
81
  // RAND_bytes() can return 0 to indicate that the entropy data is not truly
82
  // random. That's okay, it's still better than V8's stock source of entropy,
83
  // which is /dev/urandom on UNIX platforms and the current time on Windows.
84
15332
  return RAND_bytes(buffer, length) != -1;
85
}
86
87
103
int PasswordCallback(char* buf, int size, int rwflag, void* u) {
88
103
  const ByteSource* passphrase = *static_cast<const ByteSource**>(u);
89
103
  if (passphrase != nullptr) {
90
92
    size_t buflen = static_cast<size_t>(size);
91
92
    size_t len = passphrase->size();
92
92
    if (buflen < len)
93
1
      return -1;
94
91
    memcpy(buf, passphrase->get(), len);
95
91
    return len;
96
  }
97
98
11
  return -1;
99
}
100
101
// This callback is used to avoid the default passphrase callback in OpenSSL
102
// which will typically prompt for the passphrase. The prompting is designed
103
// for the OpenSSL CLI, but works poorly for Node.js because it involves
104
// synchronous interaction with the controlling terminal, something we never
105
// want, and use this function to avoid it.
106
int NoPasswordCallback(char* buf, int size, int rwflag, void* u) {
107
  return 0;
108
}
109
110
4076
void InitCryptoOnce() {
111
#ifndef OPENSSL_IS_BORINGSSL
112
4076
  OPENSSL_INIT_SETTINGS* settings = OPENSSL_INIT_new();
113
114
#if OPENSSL_VERSION_MAJOR < 3
115
  // --openssl-config=...
116
4076
  if (!per_process::cli_options->openssl_config.empty()) {
117
7
    const char* conf = per_process::cli_options->openssl_config.c_str();
118
7
    OPENSSL_INIT_set_config_filename(settings, conf);
119
  }
120
#endif
121
122
4076
  OPENSSL_init_ssl(0, settings);
123
4076
  OPENSSL_INIT_free(settings);
124
4076
  settings = nullptr;
125
#endif
126
127
#ifndef _WIN32
128
4076
  if (per_process::cli_options->secure_heap != 0) {
129

2
    switch (CRYPTO_secure_malloc_init(
130
1
                per_process::cli_options->secure_heap,
131
1
                static_cast<int>(per_process::cli_options->secure_heap_min))) {
132
      case 0:
133
        fprintf(stderr, "Unable to initialize openssl secure heap.\n");
134
        break;
135
      case 2:
136
        // Not a fatal error but worthy of a warning.
137
        fprintf(stderr, "Unable to memory map openssl secure heap.\n");
138
        break;
139
      case 1:
140
        // OK!
141
1
        break;
142
    }
143
  }
144
#endif
145
146
  /* Override FIPS settings in cnf file, if needed. */
147
4076
  unsigned long err = 0;  // NOLINT(runtime/int)
148

8146
  if (per_process::cli_options->enable_fips_crypto ||
149
4070
      per_process::cli_options->force_fips_crypto) {
150
#if OPENSSL_VERSION_MAJOR >= 3
151
    if (0 == EVP_default_properties_is_fips_enabled(nullptr) &&
152
        !EVP_default_properties_enable_fips(nullptr, 1)) {
153
#else
154

11
    if (0 == FIPS_mode() && !FIPS_mode_set(1)) {
155
#endif
156
11
      err = ERR_get_error();
157
    }
158
  }
159
4076
  if (0 != err) {
160
11
    auto* isolate = Isolate::GetCurrent();
161
11
    auto* env = Environment::GetCurrent(isolate);
162
11
    return ThrowCryptoError(env, err);
163
  }
164
165
  // Turn off compression. Saves memory and protects against CRIME attacks.
166
  // No-op with OPENSSL_NO_COMP builds of OpenSSL.
167
4065
  sk_SSL_COMP_zero(SSL_COMP_get_compression_methods());
168
169
#ifndef OPENSSL_NO_ENGINE
170
4065
  ERR_load_ENGINE_strings();
171
4065
  ENGINE_load_builtin_engines();
172
#endif  // !OPENSSL_NO_ENGINE
173
174
4065
  NodeBIO::GetMethod();
175
}
176
177
416
void GetFipsCrypto(const FunctionCallbackInfo<Value>& args) {
178
#if OPENSSL_VERSION_MAJOR >= 3
179
  args.GetReturnValue().Set(EVP_default_properties_is_fips_enabled(nullptr) ?
180
      1 : 0);
181
#else
182
1248
  args.GetReturnValue().Set(FIPS_mode() ? 1 : 0);
183
#endif
184
416
}
185
186
4
void SetFipsCrypto(const FunctionCallbackInfo<Value>& args) {
187
4
  CHECK(!per_process::cli_options->force_fips_crypto);
188
4
  Environment* env = Environment::GetCurrent(args);
189
12
  bool enable = args[0]->BooleanValue(env->isolate());
190
191
#if OPENSSL_VERSION_MAJOR >= 3
192
  if (enable == EVP_default_properties_is_fips_enabled(nullptr))
193
#else
194
4
  if (enable == FIPS_mode())
195
#endif
196
1
    return;  // No action needed.
197
198
#if OPENSSL_VERSION_MAJOR >= 3
199
  if (!EVP_default_properties_enable_fips(nullptr, enable)) {
200
#else
201
3
  if (!FIPS_mode_set(enable)) {
202
#endif
203
3
    unsigned long err = ERR_get_error();  // NOLINT(runtime/int)
204
3
    return ThrowCryptoError(env, err);
205
  }
206
}
207
208
29
void TestFipsCrypto(const v8::FunctionCallbackInfo<v8::Value>& args) {
209
#ifdef OPENSSL_FIPS
210
#if OPENSSL_VERSION_MAJOR >= 3
211
  OSSL_PROVIDER* fips_provider = nullptr;
212
  if (OSSL_PROVIDER_available(nullptr, "fips")) {
213
    fips_provider = OSSL_PROVIDER_load(nullptr, "fips");
214
  }
215
  const auto enabled = fips_provider == nullptr ? 0 :
216
      OSSL_PROVIDER_self_test(fips_provider) ? 1 : 0;
217
#else
218
  const auto enabled = FIPS_selftest() ? 1 : 0;
219
#endif
220
#else  // OPENSSL_FIPS
221
29
  const auto enabled = 0;
222
#endif  // OPENSSL_FIPS
223
224
58
  args.GetReturnValue().Set(enabled);
225
29
}
226
227
116
void CryptoErrorStore::Capture() {
228
116
  errors_.clear();
229
171
  while (const uint32_t err = ERR_get_error()) {
230
    char buf[256];
231
55
    ERR_error_string_n(err, buf, sizeof(buf));
232
55
    errors_.emplace_back(buf);
233
55
  }
234
116
  std::reverse(std::begin(errors_), std::end(errors_));
235
116
}
236
237
2965
bool CryptoErrorStore::Empty() const {
238
2965
  return errors_.empty();
239
}
240
241
134
MaybeLocal<Value> CryptoErrorStore::ToException(
242
    Environment* env,
243
    Local<String> exception_string) const {
244
134
  if (exception_string.IsEmpty()) {
245
36
    CryptoErrorStore copy(*this);
246
18
    if (copy.Empty()) {
247
      // But possibly a bug...
248
      copy.Insert(NodeCryptoError::OK);
249
    }
250
    // Use last element as the error message, everything else goes
251
    // into the .opensslErrorStack property on the exception object.
252
18
    const std::string& last_error_string = copy.errors_.back();
253
    Local<String> exception_string;
254
36
    if (!String::NewFromUtf8(
255
            env->isolate(),
256
            last_error_string.data(),
257
            NewStringType::kNormal,
258
36
            last_error_string.size()).ToLocal(&exception_string)) {
259
      return MaybeLocal<Value>();
260
    }
261
18
    copy.errors_.pop_back();
262
18
    return copy.ToException(env, exception_string);
263
  }
264
265
116
  Local<Value> exception_v = Exception::Error(exception_string);
266
116
  CHECK(!exception_v.IsEmpty());
267
268
116
  if (!Empty()) {
269
25
    CHECK(exception_v->IsObject());
270
25
    Local<Object> exception = exception_v.As<Object>();
271
    Local<Value> stack;
272

100
    if (!ToV8Value(env->context(), errors_).ToLocal(&stack) ||
273
100
        exception->Set(env->context(), env->openssl_error_stack(), stack)
274
25
            .IsNothing()) {
275
1
      return MaybeLocal<Value>();
276
    }
277
  }
278
279
115
  return exception_v;
280
}
281
282
10852
ByteSource::ByteSource(ByteSource&& other) noexcept
283
10852
    : data_(other.data_),
284
10852
      allocated_data_(other.allocated_data_),
285
21704
      size_(other.size_) {
286
10852
  other.allocated_data_ = nullptr;
287
10852
}
288
289
84423
ByteSource::~ByteSource() {
290
42211
  OPENSSL_clear_free(allocated_data_, size_);
291
42212
}
292
293
void ByteSource::reset() {
294
  OPENSSL_clear_free(allocated_data_, size_);
295
  data_ = nullptr;
296
  size_ = 0;
297
}
298
299
10111
ByteSource& ByteSource::operator=(ByteSource&& other) noexcept {
300
10111
  if (&other != this) {
301
10111
    OPENSSL_clear_free(allocated_data_, size_);
302
10111
    data_ = other.data_;
303
10111
    allocated_data_ = other.allocated_data_;
304
10111
    other.allocated_data_ = nullptr;
305
10111
    size_ = other.size_;
306
  }
307
10111
  return *this;
308
}
309
310
1677
std::unique_ptr<BackingStore> ByteSource::ReleaseToBackingStore() {
311
  // It's ok for allocated_data_ to be nullptr but
312
  // only if size_ is zero.
313

1677
  CHECK_IMPLIES(size_ > 0, allocated_data_ != nullptr);
314
  std::unique_ptr<BackingStore> ptr = ArrayBuffer::NewBackingStore(
315
1677
      allocated_data_,
316
      size(),
317
5027
      [](void* data, size_t length, void* deleter_data) {
318
1675
        OPENSSL_clear_free(deleter_data, length);
319
8381
      }, allocated_data_);
320
1677
  CHECK(ptr);
321
1677
  allocated_data_ = nullptr;
322
1677
  data_ = nullptr;
323
1677
  size_ = 0;
324
1677
  return ptr;
325
}
326
327
1677
Local<ArrayBuffer> ByteSource::ToArrayBuffer(Environment* env) {
328
3354
  std::unique_ptr<BackingStore> store = ReleaseToBackingStore();
329
3354
  return ArrayBuffer::New(env->isolate(), std::move(store));
330
}
331
332
14642
const char* ByteSource::get() const {
333
14642
  return data_;
334
}
335
336
13520
size_t ByteSource::size() const {
337
13520
  return size_;
338
}
339
340
223
ByteSource ByteSource::FromBIO(const BIOPointer& bio) {
341
223
  CHECK(bio);
342
  BUF_MEM* bptr;
343
223
  BIO_get_mem_ptr(bio.get(), &bptr);
344
223
  char* data = MallocOpenSSL<char>(bptr->length);
345
223
  memcpy(data, bptr->data, bptr->length);
346
223
  return Allocated(data, bptr->length);
347
}
348
349
1139
ByteSource ByteSource::FromEncodedString(Environment* env,
350
                                         Local<String> key,
351
                                         enum encoding enc) {
352
1139
  size_t length = 0;
353
1139
  size_t actual = 0;
354
1139
  char* data = nullptr;
355
356

2278
  if (StringBytes::Size(env->isolate(), key, enc).To(&length) && length > 0) {
357
1139
    data = MallocOpenSSL<char>(length);
358
1139
    actual = StringBytes::Write(env->isolate(), data, length, key, enc);
359
360
1139
    CHECK(actual <= length);
361
362
1139
    if (actual == 0) {
363
      OPENSSL_clear_free(data, length);
364
      data = nullptr;
365
1139
    } else if (actual < length) {
366
      data = reinterpret_cast<char*>(OPENSSL_realloc(data, actual));
367
    }
368
  }
369
370
1139
  return Allocated(data, actual);
371
}
372
373
1857
ByteSource ByteSource::FromStringOrBuffer(Environment* env,
374
                                          Local<Value> value) {
375
1857
  return IsAnyByteSource(value) ? FromBuffer(value)
376
1857
                                : FromString(env, value.As<String>());
377
}
378
379
24
ByteSource ByteSource::FromString(Environment* env, Local<String> str,
380
                                  bool ntc) {
381
48
  CHECK(str->IsString());
382
48
  size_t size = str->Utf8Length(env->isolate());
383
24
  size_t alloc_size = ntc ? size + 1 : size;
384
24
  char* data = MallocOpenSSL<char>(alloc_size);
385
24
  int opts = String::NO_OPTIONS;
386
24
  if (!ntc) opts |= String::NO_NULL_TERMINATION;
387
48
  str->WriteUtf8(env->isolate(), data, alloc_size, nullptr, opts);
388
24
  return Allocated(data, size);
389
}
390
391
1859
ByteSource ByteSource::FromBuffer(Local<Value> buffer, bool ntc) {
392
3718
  ArrayBufferOrViewContents<char> buf(buffer);
393
3718
  return ntc ? buf.ToNullTerminatedCopy() : buf.ToByteSource();
394
}
395
396
1348
ByteSource ByteSource::FromSecretKeyBytes(
397
    Environment* env,
398
    Local<Value> value) {
399
  // A key can be passed as a string, buffer or KeyObject with type 'secret'.
400
  // If it is a string, we need to convert it to a buffer. We are not doing that
401
  // in JS to avoid creating an unprotected copy on the heap.
402

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









83
    switch (ERR_GET_LIB(err)) { OSSL_ERROR_CODES_MAP(V) }
519
16
#undef V
520
#undef OSSL_ERROR_CODES_MAP
521
2
    // Don't generate codes like "ERR_OSSL_SSL_".
522

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

98
  if (err != 0 || message == nullptr) {
548
85
    ERR_error_string_n(err, message_buffer, sizeof(message_buffer));
549
85
    message = message_buffer;
550
  }
551
194
  HandleScope scope(env->isolate());
552
  Local<String> exception_string;
553
  Local<Value> exception;
554
  Local<Object> obj;
555
196
  if (!String::NewFromUtf8(env->isolate(), message).ToLocal(&exception_string))
556
    return;
557
194
  CryptoErrorStore errors;
558
98
  errors.Capture();
559

489
  if (!errors.ToException(env, exception_string).ToLocal(&exception) ||
560

487
      !exception->ToObject(env->context()).ToLocal(&obj) ||
561
292
      error::Decorate(env, obj, err).IsNothing()) {
562
2
    return;
563
  }
564
96
  env->isolate()->ThrowException(exception);
565
}
566
567
#ifndef OPENSSL_NO_ENGINE
568
2
EnginePointer LoadEngineById(const char* id, CryptoErrorStore* errors) {
569
4
  MarkPopErrorOnReturn mark_pop_error_on_return;
570
571
2
  EnginePointer engine(ENGINE_by_id(id));
572
2
  if (!engine) {
573
    // Engine not found, try loading dynamically.
574
2
    engine = EnginePointer(ENGINE_by_id("dynamic"));
575
2
    if (engine) {
576

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

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

8
  CHECK(args.Length() >= 2 && args[0]->IsString());
612
  uint32_t flags;
613
8
  if (!args[1]->Uint32Value(env->context()).To(&flags)) return;
614
615
4
  const node::Utf8Value engine_id(env->isolate(), args[0]);
616
617
6
  args.GetReturnValue().Set(SetEngine(*engine_id, flags));
618
}
619
#endif  // !OPENSSL_NO_ENGINE
620
621
967
MaybeLocal<Value> EncodeBignum(
622
    Environment* env,
623
    const BIGNUM* bn,
624
    int size,
625
    Local<Value>* error) {
626
1934
  std::vector<uint8_t> buf(size);
627
967
  CHECK_EQ(BN_bn2binpad(bn, buf.data(), size), size);
628
  return StringBytes::Encode(
629
      env->isolate(),
630
967
      reinterpret_cast<const char*>(buf.data()),
631
      buf.size(),
632
      BASE64URL,
633
2901
      error);
634
}
635
636
967
Maybe<bool> SetEncodedValue(
637
    Environment* env,
638
    Local<Object> target,
639
    Local<String> name,
640
    const BIGNUM* bn,
641
    int size) {
642
  Local<Value> value;
643
  Local<Value> error;
644
967
  CHECK_NOT_NULL(bn);
645
967
  if (size == 0)
646
746
    size = BN_num_bytes(bn);
647
1934
  if (!EncodeBignum(env, bn, size, &error).ToLocal(&value)) {
648
    if (!error.IsEmpty())
649
      env->isolate()->ThrowException(error);
650
    return Nothing<bool>();
651
  }
652
1934
  return target->Set(env->context(), name, value);
653
}
654
655
3072
CryptoJobMode GetCryptoJobMode(v8::Local<v8::Value> args) {
656
3072
  CHECK(args->IsUint32());
657
6144
  uint32_t mode = args.As<v8::Uint32>()->Value();
658
3072
  CHECK_LE(mode, kCryptoJobSync);
659
3072
  return static_cast<CryptoJobMode>(mode);
660
}
661
662
namespace {
663
// SecureBuffer uses openssl to allocate a Uint8Array using
664
// OPENSSL_secure_malloc. Because we do not yet actually
665
// make use of secure heap, this has the same semantics as
666
// using OPENSSL_malloc. However, if the secure heap is
667
// initialized, SecureBuffer will automatically use it.
668
2
void SecureBuffer(const FunctionCallbackInfo<Value>& args) {
669
4
  CHECK(args[0]->IsUint32());
670
2
  Environment* env = Environment::GetCurrent(args);
671
6
  uint32_t len = args[0].As<Uint32>()->Value();
672
2
  char* data = static_cast<char*>(OPENSSL_secure_malloc(len));
673
2
  if (data == nullptr) {
674
    // There's no memory available for the allocation.
675
    // Return nothing.
676
    return;
677
  }
678
2
  memset(data, 0, len);
679
  std::shared_ptr<BackingStore> store =
680
4
      ArrayBuffer::NewBackingStore(
681
          data,
682
          len,
683
6
          [](void* data, size_t len, void* deleter_data) {
684
2
            OPENSSL_secure_clear_free(data, len);
685
6
          },
686
4
          data);
687
2
  Local<ArrayBuffer> buffer = ArrayBuffer::New(env->isolate(), store);
688
6
  args.GetReturnValue().Set(Uint8Array::New(buffer, 0, len));
689
}
690
691
4
void SecureHeapUsed(const FunctionCallbackInfo<Value>& args) {
692
4
  Environment* env = Environment::GetCurrent(args);
693
4
  if (CRYPTO_secure_malloc_initialized())
694
12
    args.GetReturnValue().Set(
695
4
        BigInt::New(env->isolate(), CRYPTO_secure_used()));
696
4
}
697
}  // namespace
698
699
namespace Util {
700
4170
void Initialize(Environment* env, Local<Object> target) {
701
#ifndef OPENSSL_NO_ENGINE
702
4170
  env->SetMethod(target, "setEngine", SetEngine);
703
#endif  // !OPENSSL_NO_ENGINE
704
705
4170
  env->SetMethodNoSideEffect(target, "getFipsCrypto", GetFipsCrypto);
706
4170
  env->SetMethod(target, "setFipsCrypto", SetFipsCrypto);
707
4170
  env->SetMethodNoSideEffect(target, "testFipsCrypto", TestFipsCrypto);
708
709
16680
  NODE_DEFINE_CONSTANT(target, kCryptoJobAsync);
710
4170
  NODE_DEFINE_CONSTANT(target, kCryptoJobSync);
711
8340
712
8340
  env->SetMethod(target, "secureBuffer", SecureBuffer);
713
25020
  env->SetMethod(target, "secureHeapUsed", SecureHeapUsed);
714
12510
}
715
}  // namespace Util
716
717
}  // namespace crypto
718

14535
}  // namespace node