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-04-28 04:12:15 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
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
2146
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
2146
  return 1;
55
}
56
57
15676
void CheckEntropy() {
58
  for (;;) {
59
15676
    int status = RAND_status();
60
15676
    CHECK_GE(status, 0);  // Cannot fail.
61
15676
    if (status != 0)
62
31352
      break;
63
64
    // Give up, RAND_poll() not supported.
65
    if (RAND_poll() == 0)
66
      break;
67
  }
68
15676
}
69
70
15281
bool EntropySource(unsigned char* buffer, size_t length) {
71
  // Ensure that OpenSSL's PRNG is properly seeded.
72
15281
  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
15281
  return RAND_bytes(buffer, length) != -1;
77
}
78
79
103
int PasswordCallback(char* buf, int size, int rwflag, void* u) {
80
103
  const ByteSource* passphrase = *static_cast<const ByteSource**>(u);
81
103
  if (passphrase != nullptr) {
82
92
    size_t buflen = static_cast<size_t>(size);
83
92
    size_t len = passphrase->size();
84
92
    if (buflen < len)
85
1
      return -1;
86
91
    memcpy(buf, passphrase->get(), len);
87
91
    return len;
88
  }
89
90
11
  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
4057
void InitCryptoOnce() {
103
#ifndef OPENSSL_IS_BORINGSSL
104
4057
  OPENSSL_INIT_SETTINGS* settings = OPENSSL_INIT_new();
105
106
  // --openssl-config=...
107
4057
  if (!per_process::cli_options->openssl_config.empty()) {
108
7
    const char* conf = per_process::cli_options->openssl_config.c_str();
109
7
    OPENSSL_INIT_set_config_filename(settings, conf);
110
  }
111
112
4057
  OPENSSL_init_ssl(0, settings);
113
4057
  OPENSSL_INIT_free(settings);
114
4057
  settings = nullptr;
115
#endif
116
117
#ifndef _WIN32
118
4057
  if (per_process::cli_options->secure_heap != 0) {
119

2
    switch (CRYPTO_secure_malloc_init(
120
1
                per_process::cli_options->secure_heap,
121
1
                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
1
        break;
132
    }
133
  }
134
#endif
135
136
  /* Override FIPS settings in cnf file, if needed. */
137
4057
  unsigned long err = 0;  // NOLINT(runtime/int)
138

8108
  if (per_process::cli_options->enable_fips_crypto ||
139
4051
      per_process::cli_options->force_fips_crypto) {
140
#if OPENSSL_VERSION_MAJOR >= 3
141
    if (0 == EVP_default_properties_is_fips_enabled(nullptr) &&
142
        !EVP_default_properties_enable_fips(nullptr, 1)) {
143
#else
144

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

100
    if (!ToV8Value(env->context(), errors_).ToLocal(&stack) ||
254
100
        exception->Set(env->context(), env->openssl_error_stack(), stack)
255
25
            .IsNothing()) {
256
1
      return MaybeLocal<Value>();
257
    }
258
  }
259
260
115
  return exception_v;
261
}
262
263
10846
ByteSource::ByteSource(ByteSource&& other) noexcept
264
10846
    : data_(other.data_),
265
10846
      allocated_data_(other.allocated_data_),
266
21692
      size_(other.size_) {
267
10846
  other.allocated_data_ = nullptr;
268
10846
}
269
270
172096
ByteSource::~ByteSource() {
271
86049
  OPENSSL_clear_free(allocated_data_, size_);
272
86047
}
273
274
void ByteSource::reset() {
275
  OPENSSL_clear_free(allocated_data_, size_);
276
  data_ = nullptr;
277
  size_ = 0;
278
}
279
280
32009
ByteSource& ByteSource::operator=(ByteSource&& other) noexcept {
281
32009
  if (&other != this) {
282
32009
    OPENSSL_clear_free(allocated_data_, size_);
283
32009
    data_ = other.data_;
284
32009
    allocated_data_ = other.allocated_data_;
285
32009
    other.allocated_data_ = nullptr;
286
32009
    size_ = other.size_;
287
  }
288
32009
  return *this;
289
}
290
291
1684
std::unique_ptr<BackingStore> ByteSource::ReleaseToBackingStore() {
292
  // It's ok for allocated_data_ to be nullptr but
293
  // only if size_ is zero.
294

1684
  CHECK_IMPLIES(size_ > 0, allocated_data_ != nullptr);
295
  std::unique_ptr<BackingStore> ptr = ArrayBuffer::NewBackingStore(
296
1684
      allocated_data_,
297
      size(),
298
5048
      [](void* data, size_t length, void* deleter_data) {
299
1682
        OPENSSL_clear_free(deleter_data, length);
300
8416
      }, allocated_data_);
301
1684
  CHECK(ptr);
302
1684
  allocated_data_ = nullptr;
303
1684
  data_ = nullptr;
304
1684
  size_ = 0;
305
1684
  return ptr;
306
}
307
308
1684
Local<ArrayBuffer> ByteSource::ToArrayBuffer(Environment* env) {
309
3368
  std::unique_ptr<BackingStore> store = ReleaseToBackingStore();
310
3368
  return ArrayBuffer::New(env->isolate(), std::move(store));
311
}
312
313
36531
const char* ByteSource::get() const {
314
36531
  return data_;
315
}
316
317
13520
size_t ByteSource::size() const {
318
13520
  return size_;
319
}
320
321
224
ByteSource ByteSource::FromBIO(const BIOPointer& bio) {
322
224
  CHECK(bio);
323
  BUF_MEM* bptr;
324
224
  BIO_get_mem_ptr(bio.get(), &bptr);
325
224
  char* data = MallocOpenSSL<char>(bptr->length);
326
224
  memcpy(data, bptr->data, bptr->length);
327
224
  return Allocated(data, bptr->length);
328
}
329
330
1139
ByteSource ByteSource::FromEncodedString(Environment* env,
331
                                         Local<String> key,
332
                                         enum encoding enc) {
333
1139
  size_t length = 0;
334
1139
  size_t actual = 0;
335
1139
  char* data = nullptr;
336
337

2278
  if (StringBytes::Size(env->isolate(), key, enc).To(&length) && length > 0) {
338
1139
    data = MallocOpenSSL<char>(length);
339
1139
    actual = StringBytes::Write(env->isolate(), data, length, key, enc);
340
341
1139
    CHECK(actual <= length);
342
343
1139
    if (actual == 0) {
344
      OPENSSL_clear_free(data, length);
345
      data = nullptr;
346
1139
    } else if (actual < length) {
347
      data = reinterpret_cast<char*>(OPENSSL_realloc(data, actual));
348
    }
349
  }
350
351
1139
  return Allocated(data, actual);
352
}
353
354
1857
ByteSource ByteSource::FromStringOrBuffer(Environment* env,
355
                                          Local<Value> value) {
356
1857
  return IsAnyByteSource(value) ? FromBuffer(value)
357
1857
                                : FromString(env, value.As<String>());
358
}
359
360
24
ByteSource ByteSource::FromString(Environment* env, Local<String> str,
361
                                  bool ntc) {
362
48
  CHECK(str->IsString());
363
48
  size_t size = str->Utf8Length(env->isolate());
364
24
  size_t alloc_size = ntc ? size + 1 : size;
365
24
  char* data = MallocOpenSSL<char>(alloc_size);
366
24
  int opts = String::NO_OPTIONS;
367
24
  if (!ntc) opts |= String::NO_NULL_TERMINATION;
368
48
  str->WriteUtf8(env->isolate(), data, alloc_size, nullptr, opts);
369
24
  return Allocated(data, size);
370
}
371
372
1859
ByteSource ByteSource::FromBuffer(Local<Value> buffer, bool ntc) {
373
3718
  ArrayBufferOrViewContents<char> buf(buffer);
374
3718
  return ntc ? buf.ToNullTerminatedCopy() : buf.ToByteSource();
375
}
376
377
1348
ByteSource ByteSource::FromSecretKeyBytes(
378
    Environment* env,
379
    Local<Value> value) {
380
  // A key can be passed as a string, buffer or KeyObject with type 'secret'.
381
  // If it is a string, we need to convert it to a buffer. We are not doing that
382
  // in JS to avoid creating an unprotected copy on the heap.
383

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









83
    switch (ERR_GET_LIB(err)) { OSSL_ERROR_CODES_MAP(V) }
500
16
#undef V
501
#undef OSSL_ERROR_CODES_MAP
502
2
    // Don't generate codes like "ERR_OSSL_SSL_".
503

89
    if (lib && strcmp(lib, "SSL_") == 0)
504
6
      prefix = "";
505
506
    // All OpenSSL reason strings fit in a single 80-column macro definition,
507
    // all prefix lengths are <= 10, and ERR_OSSL_ is 9, so 128 is more than
508
    // sufficient.
509
    char code[128];
510
83
    snprintf(code, sizeof(code), "ERR_%s%s%s", prefix, lib, reason.c_str());
511
512
249
    if (obj->Set(env->isolate()->GetCurrentContext(),
513
             env->code_string(),
514
415
             OneByteString(env->isolate(), code)).IsNothing())
515
      return Nothing<bool>();
516
  }
517
518
83
  return Just(true);
519
}
520
}  // namespace error
521
522
98
void ThrowCryptoError(Environment* env,
523
                      unsigned long err,  // NOLINT(runtime/int)
524
                      // Default, only used if there is no SSL `err` which can
525
                      // be used to create a long-style message string.
526
                      const char* message) {
527
98
  char message_buffer[128] = {0};
528

98
  if (err != 0 || message == nullptr) {
529
85
    ERR_error_string_n(err, message_buffer, sizeof(message_buffer));
530
85
    message = message_buffer;
531
  }
532
194
  HandleScope scope(env->isolate());
533
  Local<String> exception_string;
534
  Local<Value> exception;
535
  Local<Object> obj;
536
196
  if (!String::NewFromUtf8(env->isolate(), message).ToLocal(&exception_string))
537
    return;
538
194
  CryptoErrorStore errors;
539
98
  errors.Capture();
540

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

487
      !exception->ToObject(env->context()).ToLocal(&obj) ||
542
292
      error::Decorate(env, obj, err).IsNothing()) {
543
2
    return;
544
  }
545
96
  env->isolate()->ThrowException(exception);
546
}
547
548
#ifndef OPENSSL_NO_ENGINE
549
2
EnginePointer LoadEngineById(const char* id, CryptoErrorStore* errors) {
550
4
  MarkPopErrorOnReturn mark_pop_error_on_return;
551
552
2
  EnginePointer engine(ENGINE_by_id(id));
553
2
  if (!engine) {
554
    // Engine not found, try loading dynamically.
555
2
    engine = EnginePointer(ENGINE_by_id("dynamic"));
556
2
    if (engine) {
557

4
      if (!ENGINE_ctrl_cmd_string(engine.get(), "SO_PATH", id, 0) ||
558
2
          !ENGINE_ctrl_cmd_string(engine.get(), "LOAD", nullptr, 0)) {
559
2
        engine.reset();
560
      }
561
    }
562
  }
563
564

2
  if (!engine && errors != nullptr) {
565
    if (ERR_get_error() != 0) {
566
      errors->Capture();
567
    } else {
568
      errors->Insert(NodeCryptoError::ENGINE_NOT_FOUND, id);
569
    }
570
  }
571
572
4
  return engine;
573
}
574
575
2
bool SetEngine(const char* id, uint32_t flags, CryptoErrorStore* errors) {
576
2
  ClearErrorOnReturn clear_error_on_return;
577
4
  EnginePointer engine = LoadEngineById(id, errors);
578
2
  if (!engine)
579
2
    return false;
580
581
  if (!ENGINE_set_default(engine.get(), flags)) {
582
    if (errors != nullptr)
583
      errors->Capture();
584
    return false;
585
  }
586
587
  return true;
588
}
589
590
2
void SetEngine(const FunctionCallbackInfo<Value>& args) {
591
2
  Environment* env = Environment::GetCurrent(args);
592

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

14478
}  // namespace node