GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: crypto/crypto_util.h Lines: 218 224 97.3 %
Date: 2021-09-29 04:12:34 Branches: 74 107 69.2 %

Line Branch Exec Source
1
#ifndef SRC_CRYPTO_CRYPTO_UTIL_H_
2
#define SRC_CRYPTO_CRYPTO_UTIL_H_
3
4
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
5
6
#include "env.h"
7
#include "async_wrap.h"
8
#include "allocated_buffer.h"
9
#include "node_errors.h"
10
#include "node_internals.h"
11
#include "util.h"
12
#include "v8.h"
13
#include "string_bytes.h"
14
15
#include <openssl/err.h>
16
#include <openssl/evp.h>
17
#include <openssl/ec.h>
18
#include <openssl/kdf.h>
19
#include <openssl/rsa.h>
20
#include <openssl/dsa.h>
21
#include <openssl/ssl.h>
22
#ifndef OPENSSL_NO_ENGINE
23
#  include <openssl/engine.h>
24
#endif  // !OPENSSL_NO_ENGINE
25
// The FIPS-related functions are only available
26
// when the OpenSSL itself was compiled with FIPS support.
27
#if defined(OPENSSL_FIPS) && OPENSSL_VERSION_MAJOR < 3
28
#  include <openssl/fips.h>
29
#endif  // OPENSSL_FIPS
30
31
#include <algorithm>
32
#include <memory>
33
#include <string>
34
#include <vector>
35
#include <climits>
36
#include <cstdio>
37
38
namespace node {
39
namespace crypto {
40
// Currently known sizes of commonly used OpenSSL struct sizes.
41
// OpenSSL considers it's various structs to be opaque and the
42
// sizes may change from one version of OpenSSL to another, so
43
// these values should not be trusted to remain static. These
44
// are provided to allow for some close to reasonable memory
45
// tracking.
46
constexpr size_t kSizeOf_DH = 144;
47
constexpr size_t kSizeOf_EC_KEY = 80;
48
constexpr size_t kSizeOf_EVP_CIPHER_CTX = 168;
49
constexpr size_t kSizeOf_EVP_MD_CTX = 48;
50
constexpr size_t kSizeOf_EVP_PKEY = 72;
51
constexpr size_t kSizeOf_EVP_PKEY_CTX = 80;
52
constexpr size_t kSizeOf_HMAC_CTX = 32;
53
54
// Define smart pointers for the most commonly used OpenSSL types:
55
using X509Pointer = DeleteFnPtr<X509, X509_free>;
56
using BIOPointer = DeleteFnPtr<BIO, BIO_free_all>;
57
using SSLCtxPointer = DeleteFnPtr<SSL_CTX, SSL_CTX_free>;
58
using SSLSessionPointer = DeleteFnPtr<SSL_SESSION, SSL_SESSION_free>;
59
using SSLPointer = DeleteFnPtr<SSL, SSL_free>;
60
using PKCS8Pointer = DeleteFnPtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free>;
61
using EVPKeyPointer = DeleteFnPtr<EVP_PKEY, EVP_PKEY_free>;
62
using EVPKeyCtxPointer = DeleteFnPtr<EVP_PKEY_CTX, EVP_PKEY_CTX_free>;
63
using EVPMDPointer = DeleteFnPtr<EVP_MD_CTX, EVP_MD_CTX_free>;
64
using RSAPointer = DeleteFnPtr<RSA, RSA_free>;
65
using ECPointer = DeleteFnPtr<EC_KEY, EC_KEY_free>;
66
using BignumPointer = DeleteFnPtr<BIGNUM, BN_free>;
67
using BignumCtxPointer = DeleteFnPtr<BN_CTX, BN_CTX_free>;
68
using NetscapeSPKIPointer = DeleteFnPtr<NETSCAPE_SPKI, NETSCAPE_SPKI_free>;
69
using ECGroupPointer = DeleteFnPtr<EC_GROUP, EC_GROUP_free>;
70
using ECPointPointer = DeleteFnPtr<EC_POINT, EC_POINT_free>;
71
using ECKeyPointer = DeleteFnPtr<EC_KEY, EC_KEY_free>;
72
using DHPointer = DeleteFnPtr<DH, DH_free>;
73
using ECDSASigPointer = DeleteFnPtr<ECDSA_SIG, ECDSA_SIG_free>;
74
using HMACCtxPointer = DeleteFnPtr<HMAC_CTX, HMAC_CTX_free>;
75
using CipherCtxPointer = DeleteFnPtr<EVP_CIPHER_CTX, EVP_CIPHER_CTX_free>;
76
using RsaPointer = DeleteFnPtr<RSA, RSA_free>;
77
using DsaPointer = DeleteFnPtr<DSA, DSA_free>;
78
using DsaSigPointer = DeleteFnPtr<DSA_SIG, DSA_SIG_free>;
79
80
// Our custom implementation of the certificate verify callback
81
// used when establishing a TLS handshake. Because we cannot perform
82
// I/O quickly enough with X509_STORE_CTX_ APIs in this callback,
83
// we ignore preverify_ok errors here and let the handshake continue.
84
// In other words, this VerifyCallback is a non-op. It is imperative
85
// that the user user Connection::VerifyError after the `secure`
86
// callback has been made.
87
extern int VerifyCallback(int preverify_ok, X509_STORE_CTX* ctx);
88
89
bool ProcessFipsOptions();
90
91
void InitCryptoOnce();
92
93
void InitCrypto(v8::Local<v8::Object> target);
94
95
extern void UseExtraCaCerts(const std::string& file);
96
97
// Forcibly clear OpenSSL's error stack on return. This stops stale errors
98
// from popping up later in the lifecycle of crypto operations where they
99
// would cause spurious failures. It's a rather blunt method, though.
100
// ERR_clear_error() isn't necessarily cheap either.
101
struct ClearErrorOnReturn {
102
11146
  ~ClearErrorOnReturn() { ERR_clear_error(); }
103
};
104
105
// Pop errors from OpenSSL's error stack that were added
106
// between when this was constructed and destructed.
107
struct MarkPopErrorOnReturn {
108
22221
  MarkPopErrorOnReturn() { ERR_set_mark(); }
109
22220
  ~MarkPopErrorOnReturn() { ERR_pop_to_mark(); }
110
};
111
112
// Ensure that OpenSSL has enough entropy (at least 256 bits) for its PRNG.
113
// The entropy pool starts out empty and needs to fill up before the PRNG
114
// can be used securely.  Once the pool is filled, it never dries up again;
115
// its contents is stirred and reused when necessary.
116
//
117
// OpenSSL normally fills the pool automatically but not when someone starts
118
// generating random numbers before the pool is full: in that case OpenSSL
119
// keeps lowering the entropy estimate to thwart attackers trying to guess
120
// the initial state of the PRNG.
121
//
122
// When that happens, we will have to wait until enough entropy is available.
123
// That should normally never take longer than a few milliseconds.
124
//
125
// OpenSSL draws from /dev/random and /dev/urandom.  While /dev/random may
126
// block pending "true" randomness, /dev/urandom is a CSPRNG that doesn't
127
// block under normal circumstances.
128
//
129
// The only time when /dev/urandom may conceivably block is right after boot,
130
// when the whole system is still low on entropy.  That's not something we can
131
// do anything about.
132
void CheckEntropy();
133
134
// Generate length bytes of random data. If this returns false, the data
135
// may not be truly random but it's still generally good enough.
136
bool EntropySource(unsigned char* buffer, size_t length);
137
138
int PasswordCallback(char* buf, int size, int rwflag, void* u);
139
140
int NoPasswordCallback(char* buf, int size, int rwflag, void* u);
141
142
// Decode is used by the various stream-based crypto utilities to decode
143
// string input.
144
template <typename T>
145
3385
void Decode(const v8::FunctionCallbackInfo<v8::Value>& args,
146
            void (*callback)(T*, const v8::FunctionCallbackInfo<v8::Value>&,
147
                             const char*, size_t)) {
148
  T* ctx;
149
3385
  ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
150
151
6770
  if (args[0]->IsString()) {
152
1760
    StringBytes::InlineDecoder decoder;
153
1760
    Environment* env = Environment::GetCurrent(args);
154
1760
    enum encoding enc = ParseEncoding(env->isolate(), args[1], UTF8);
155
5280
    if (decoder.Decode(env, args[0].As<v8::String>(), enc).IsNothing())
156
      return;
157
1760
    callback(ctx, args, decoder.out(), decoder.size());
158
  } else {
159
1625
    ArrayBufferViewContents<char> buf(args[0]);
160
1625
    callback(ctx, args, buf.data(), buf.length());
161
  }
162
}
163
164
#define NODE_CRYPTO_ERROR_CODES_MAP(V)                                        \
165
    V(CIPHER_JOB_FAILED, "Cipher job failed")                                 \
166
    V(DERIVING_BITS_FAILED, "Deriving bits failed")                           \
167
    V(ENGINE_NOT_FOUND, "Engine \"%s\" was not found")                        \
168
    V(INVALID_KEY_TYPE, "Invalid key type")                                   \
169
    V(KEY_GENERATION_JOB_FAILED, "Key generation job failed")                 \
170
    V(OK, "Ok")                                                               \
171
172
enum class NodeCryptoError {
173
#define V(CODE, DESCRIPTION) CODE,
174
  NODE_CRYPTO_ERROR_CODES_MAP(V)
175
#undef V
176
};
177
178
// Utility struct used to harvest error information from openssl's error stack
179
struct CryptoErrorStore final : public MemoryRetainer {
180
 public:
181
  void Capture();
182
183
  bool Empty() const;
184
185
  template <typename... Args>
186
  void Insert(const NodeCryptoError error, Args&&... args);
187
188
  v8::MaybeLocal<v8::Value> ToException(
189
      Environment* env,
190
      v8::Local<v8::String> exception_string = v8::Local<v8::String>()) const;
191
192
3
  SET_NO_MEMORY_INFO()
193
3
  SET_MEMORY_INFO_NAME(CryptoErrorStore)
194
3
  SET_SELF_SIZE(CryptoErrorStore)
195
196
 private:
197
  std::vector<std::string> errors_;
198
};
199
200
template <typename... Args>
201
13
void CryptoErrorStore::Insert(const NodeCryptoError error, Args&&... args) {
202
13
  const char* error_string = nullptr;
203

13
  switch (error) {
204
#define V(CODE, DESCRIPTION) \
205
    case NodeCryptoError::CODE: error_string = DESCRIPTION; break;
206
13
    NODE_CRYPTO_ERROR_CODES_MAP(V)
207
#undef V
208
  }
209
13
  errors_.emplace_back(SPrintF(error_string,
210
                               std::forward<Args>(args)...));
211
13
}
212
213
template <typename T>
214
16004
T* MallocOpenSSL(size_t count) {
215
16004
  void* mem = OPENSSL_malloc(MultiplyWithOverflowCheck(count, sizeof(T)));
216

16004
  CHECK_IMPLIES(mem == nullptr, count == 0);
217
16004
  return static_cast<T*>(mem);
218
}
219
220
template <typename T>
221
1419
T* ReallocOpenSSL(T* buf, size_t count) {
222
1419
  void* mem = OPENSSL_realloc(buf, MultiplyWithOverflowCheck(count, sizeof(T)));
223

1419
  CHECK_IMPLIES(mem == nullptr, count == 0);
224
1419
  return static_cast<T*>(mem);
225
}
226
227
// A helper class representing a read-only byte array. When deallocated, its
228
// contents are zeroed.
229
class ByteSource {
230
 public:
231
21880
  ByteSource() = default;
232
  ByteSource(ByteSource&& other) noexcept;
233
  ~ByteSource();
234
235
  ByteSource& operator=(ByteSource&& other) noexcept;
236
237
  const char* get() const;
238
239
  template <typename T>
240
6958
  const T* data() const { return reinterpret_cast<const T*>(get()); }
241
242
  size_t size() const;
243
244
4442
  operator bool() const { return data_ != nullptr; }
245
246
2841
  BignumPointer ToBN() const {
247
    return BignumPointer(BN_bin2bn(
248
2841
        reinterpret_cast<const unsigned char*>(get()),
249
2841
        size(),
250
2841
        nullptr));
251
  }
252
253
  // Creates a v8::BackingStore that takes over responsibility for
254
  // any allocated data. The ByteSource will be reset with size = 0
255
  // after being called.
256
  std::unique_ptr<v8::BackingStore> ReleaseToBackingStore();
257
258
  v8::Local<v8::ArrayBuffer> ToArrayBuffer(Environment* env);
259
260
  void reset();
261
262
  // Allows an Allocated ByteSource to be truncated.
263
1419
  void Resize(size_t newsize) {
264
1419
    CHECK_LE(newsize, size_);
265
1419
    CHECK_NOT_NULL(allocated_data_);
266
1419
    char* new_data_ = ReallocOpenSSL<char>(allocated_data_, newsize);
267
1419
    data_ = allocated_data_ = new_data_;
268
1419
    size_ = newsize;
269
1419
  }
270
271
  static ByteSource Allocated(char* data, size_t size);
272
  static ByteSource Foreign(const char* data, size_t size);
273
274
  static ByteSource FromEncodedString(Environment* env,
275
                                      v8::Local<v8::String> value,
276
                                      enum encoding enc = BASE64);
277
278
  static ByteSource FromStringOrBuffer(Environment* env,
279
                                       v8::Local<v8::Value> value);
280
281
  static ByteSource FromString(Environment* env,
282
                               v8::Local<v8::String> str,
283
                               bool ntc = false);
284
285
  static ByteSource FromBuffer(v8::Local<v8::Value> buffer,
286
                               bool ntc = false);
287
288
  static ByteSource FromBIO(const BIOPointer& bio);
289
290
  static ByteSource NullTerminatedCopy(Environment* env,
291
                                       v8::Local<v8::Value> value);
292
293
  static ByteSource FromSymmetricKeyObjectHandle(v8::Local<v8::Value> handle);
294
295
  ByteSource(const ByteSource&) = delete;
296
  ByteSource& operator=(const ByteSource&) = delete;
297
298
  static ByteSource FromSecretKeyBytes(
299
      Environment* env, v8::Local<v8::Value> value);
300
301
 private:
302
  const char* data_ = nullptr;
303
  char* allocated_data_ = nullptr;
304
  size_t size_ = 0;
305
306
  ByteSource(const char* data, char* allocated_data, size_t size);
307
};
308
309
enum CryptoJobMode {
310
  kCryptoJobAsync,
311
  kCryptoJobSync
312
};
313
314
CryptoJobMode GetCryptoJobMode(v8::Local<v8::Value> args);
315
316
template <typename CryptoJobTraits>
317
class CryptoJob : public AsyncWrap, public ThreadPoolWork {
318
 public:
319
  using AdditionalParams = typename CryptoJobTraits::AdditionalParameters;
320
321
7525
  explicit CryptoJob(
322
      Environment* env,
323
      v8::Local<v8::Object> object,
324
      AsyncWrap::ProviderType type,
325
      CryptoJobMode mode,
326
      AdditionalParams&& params)
327
      : AsyncWrap(env, object, type),
328
        ThreadPoolWork(env),
329
        mode_(mode),
330
7525
        params_(std::move(params)) {
331
    // If the CryptoJob is async, then the instance will be
332
    // cleaned up when AfterThreadPoolWork is called.
333
7525
    if (mode == kCryptoJobSync) MakeWeak();
334
7525
  }
335
336
  bool IsNotIndicativeOfMemoryLeakAtExit() const override {
337
    // CryptoJobs run a work in the libuv thread pool and may still
338
    // exist when the event loop empties and starts to exit.
339
    return true;
340
  }
341
342
5979
  void AfterThreadPoolWork(int status) override {
343
5979
    Environment* env = AsyncWrap::env();
344
5979
    CHECK_EQ(mode_, kCryptoJobAsync);
345

5979
    CHECK(status == 0 || status == UV_ECANCELED);
346
5979
    std::unique_ptr<CryptoJob> ptr(this);
347
    // If the job was canceled do not execute the callback.
348
    // TODO(@jasnell): We should likely revisit skipping the
349
    // callback on cancel as that could leave the JS in a pending
350
    // state (e.g. unresolved promises...)
351
5979
    if (status == UV_ECANCELED) return;
352
5979
    v8::HandleScope handle_scope(env->isolate());
353
11958
    v8::Context::Scope context_scope(env->context());
354
355
    // TODO(tniessen): Remove the exception handling logic here as soon as we
356
    // can verify that no code path in ToResult will ever throw an exception.
357
    v8::Local<v8::Value> exception;
358
17937
    v8::Local<v8::Value> args[2];
359
    {
360
5979
      node::errors::TryCatchScope try_catch(env);
361
5979
      v8::Maybe<bool> ret = ptr->ToResult(&args[0], &args[1]);
362
5979
      if (!ret.IsJust()) {
363
4
        CHECK(try_catch.HasCaught());
364
4
        exception = try_catch.Exception();
365
5975
      } else if (!ret.FromJust()) {
366
        return;
367
      }
368
    }
369
370
5979
    if (exception.IsEmpty()) {
371
5975
      ptr->MakeCallback(env->ondone_string(), arraysize(args), args);
372
    } else {
373
4
      ptr->MakeCallback(env->ondone_string(), 1, &exception);
374
    }
375
  }
376
377
  virtual v8::Maybe<bool> ToResult(
378
      v8::Local<v8::Value>* err,
379
      v8::Local<v8::Value>* result) = 0;
380
381
7511
  CryptoJobMode mode() const { return mode_; }
382
383
7585
  CryptoErrorStore* errors() { return &errors_; }
384
385
12236
  AdditionalParams* params() { return &params_; }
386
387
6
  std::string MemoryInfoName() const override {
388
6
    return CryptoJobTraits::JobName;
389
  }
390
391
6
  void MemoryInfo(MemoryTracker* tracker) const override {
392
6
    tracker->TrackField("params", params_);
393
6
    tracker->TrackField("errors", errors_);
394
  }
395
396
7511
  static void Run(const v8::FunctionCallbackInfo<v8::Value>& args) {
397
7511
    Environment* env = Environment::GetCurrent(args);
398
399
    CryptoJob<CryptoJobTraits>* job;
400
13492
    ASSIGN_OR_RETURN_UNWRAP(&job, args.Holder());
401
7511
    if (job->mode() == kCryptoJobAsync)
402
5981
      return job->ScheduleWork();
403
404
4590
    v8::Local<v8::Value> ret[2];
405
1530
    env->PrintSyncTrace();
406
1530
    job->DoThreadPoolWork();
407
1530
    v8::Maybe<bool> result = job->ToResult(&ret[0], &ret[1]);
408

3054
    if (result.IsJust() && result.FromJust()) {
409
3048
      args.GetReturnValue().Set(
410
          v8::Array::New(env->isolate(), ret, arraysize(ret)));
411
    }
412
  }
413
414
180642
  static void Initialize(
415
      v8::FunctionCallback new_fn,
416
      Environment* env,
417
      v8::Local<v8::Object> target) {
418
180642
    v8::Local<v8::FunctionTemplate> job = env->NewFunctionTemplate(new_fn);
419
180642
    job->Inherit(AsyncWrap::GetConstructorTemplate(env));
420
361284
    job->InstanceTemplate()->SetInternalFieldCount(
421
        AsyncWrap::kInternalFieldCount);
422
180642
    env->SetProtoMethod(job, "run", Run);
423
180642
    env->SetConstructorFunction(target, CryptoJobTraits::JobName, job);
424
180642
  }
425
426
 private:
427
  const CryptoJobMode mode_;
428
  CryptoErrorStore errors_;
429
  AdditionalParams params_;
430
};
431
432
template <typename DeriveBitsTraits>
433
class DeriveBitsJob final : public CryptoJob<DeriveBitsTraits> {
434
 public:
435
  using AdditionalParams = typename DeriveBitsTraits::AdditionalParameters;
436
437
3762
  static void New(const v8::FunctionCallbackInfo<v8::Value>& args) {
438
3762
    Environment* env = Environment::GetCurrent(args);
439
440
3762
    CryptoJobMode mode = GetCryptoJobMode(args[0]);
441
442
3762
    AdditionalParams params;
443
7524
    if (DeriveBitsTraits::AdditionalConfig(mode, args, 1, &params)
444
            .IsNothing()) {
445
      // The DeriveBitsTraits::AdditionalConfig is responsible for
446
      // calling an appropriate THROW_CRYPTO_* variant reporting
447
      // whatever error caused initialization to fail.
448
73
      return;
449
    }
450
451
3689
    new DeriveBitsJob(env, args.This(), mode, std::move(params));
452
  }
453
454
73117
  static void Initialize(
455
      Environment* env,
456
      v8::Local<v8::Object> target) {
457
73117
    CryptoJob<DeriveBitsTraits>::Initialize(New, env, target);
458
73117
  }
459
460
3689
  DeriveBitsJob(
461
      Environment* env,
462
      v8::Local<v8::Object> object,
463
      CryptoJobMode mode,
464
      AdditionalParams&& params)
465
      : CryptoJob<DeriveBitsTraits>(
466
            env,
467
            object,
468
            DeriveBitsTraits::Provider,
469
            mode,
470
3689
            std::move(params)) {}
471
472
3689
  void DoThreadPoolWork() override {
473
3689
    if (!DeriveBitsTraits::DeriveBits(
474
            AsyncWrap::env(),
475
3689
            *CryptoJob<DeriveBitsTraits>::params(), &out_)) {
476
13
      CryptoErrorStore* errors = CryptoJob<DeriveBitsTraits>::errors();
477
13
      errors->Capture();
478
13
      if (errors->Empty())
479
13
        errors->Insert(NodeCryptoError::DERIVING_BITS_FAILED);
480
13
      return;
481
    }
482
3676
    success_ = true;
483
  }
484
485
3689
  v8::Maybe<bool> ToResult(
486
      v8::Local<v8::Value>* err,
487
      v8::Local<v8::Value>* result) override {
488
3689
    Environment* env = AsyncWrap::env();
489
3689
    CryptoErrorStore* errors = CryptoJob<DeriveBitsTraits>::errors();
490
3689
    if (success_) {
491
3676
      CHECK(errors->Empty());
492
3676
      *err = v8::Undefined(env->isolate());
493
3676
      return DeriveBitsTraits::EncodeOutput(
494
          env,
495
3676
          *CryptoJob<DeriveBitsTraits>::params(),
496
          &out_,
497
3676
          result);
498
    }
499
500
13
    if (errors->Empty())
501
      errors->Capture();
502
13
    CHECK(!errors->Empty());
503
26
    *result = v8::Undefined(env->isolate());
504
26
    return v8::Just(errors->ToException(env).ToLocal(err));
505
  }
506
507
6
  SET_SELF_SIZE(DeriveBitsJob)
508
3
  void MemoryInfo(MemoryTracker* tracker) const override {
509
6
    tracker->TrackFieldWithSize("out", out_.size());
510
6
    CryptoJob<DeriveBitsTraits>::MemoryInfo(tracker);
511
  }
512
513
 private:
514
  ByteSource out_;
515
  bool success_ = false;
516
};
517
518
void ThrowCryptoError(Environment* env,
519
                      unsigned long err,  // NOLINT(runtime/int)
520
                      const char* message = nullptr);
521
522
#ifndef OPENSSL_NO_ENGINE
523
struct EnginePointer {
524
  ENGINE* engine = nullptr;
525
  bool finish_on_exit = false;
526
527
2360
  inline EnginePointer() = default;
528
529
4
  inline explicit EnginePointer(ENGINE* engine_, bool finish_on_exit_ = false)
530
4
    : engine(engine_),
531
4
      finish_on_exit(finish_on_exit_) {}
532
533
2
  inline EnginePointer(EnginePointer&& other) noexcept
534
2
      : engine(other.engine),
535
2
        finish_on_exit(other.finish_on_exit) {
536
2
    other.release();
537
2
  }
538
539
2357
  inline ~EnginePointer() { reset(); }
540
541
2
  inline EnginePointer& operator=(EnginePointer&& other) noexcept {
542
2
    if (this == &other) return *this;
543
2
    this->~EnginePointer();
544
2
    return *new (this) EnginePointer(std::move(other));
545
  }
546
547
8
  inline operator bool() const { return engine != nullptr; }
548
549
4
  inline ENGINE* get() { return engine; }
550
551
2359
  inline void reset(ENGINE* engine_ = nullptr, bool finish_on_exit_ = false) {
552
2359
    if (engine != nullptr) {
553
2
      if (finish_on_exit)
554
        ENGINE_finish(engine);
555
2
      ENGINE_free(engine);
556
    }
557
2359
    engine = engine_;
558
2359
    finish_on_exit = finish_on_exit_;
559
2359
  }
560
561
2
  inline ENGINE* release() {
562
2
    ENGINE* ret = engine;
563
2
    engine = nullptr;
564
2
    finish_on_exit = false;
565
2
    return ret;
566
  }
567
};
568
569
EnginePointer LoadEngineById(const char* id, CryptoErrorStore* errors);
570
571
bool SetEngine(
572
    const char* id,
573
    uint32_t flags,
574
    CryptoErrorStore* errors = nullptr);
575
576
void SetEngine(const v8::FunctionCallbackInfo<v8::Value>& args);
577
#endif  // !OPENSSL_NO_ENGINE
578
579
void GetFipsCrypto(const v8::FunctionCallbackInfo<v8::Value>& args);
580
581
void SetFipsCrypto(const v8::FunctionCallbackInfo<v8::Value>& args);
582
583
void TestFipsCrypto(const v8::FunctionCallbackInfo<v8::Value>& args);
584
585
class CipherPushContext {
586
 public:
587
9
  inline explicit CipherPushContext(Environment* env) : env_(env) {}
588
589
879
  inline void push_back(const char* str) {
590
879
    list_.emplace_back(OneByteString(env_->isolate(), str));
591
879
  }
592
593
9
  inline v8::Local<v8::Array> ToJSArray() {
594
9
    return v8::Array::New(env_->isolate(), list_.data(), list_.size());
595
  }
596
597
 private:
598
  std::vector<v8::Local<v8::Value>> list_;
599
  Environment* env_;
600
};
601
602
template <class TypeName>
603
879
void array_push_back(const TypeName* md,
604
                     const char* from,
605
                     const char* to,
606
                     void* arg) {
607
879
  static_cast<CipherPushContext*>(arg)->push_back(from);
608
879
}
609
610
130378
inline bool IsAnyByteSource(v8::Local<v8::Value> arg) {
611
136944
  return arg->IsArrayBufferView() ||
612

143510
         arg->IsArrayBuffer() ||
613
134818
         arg->IsSharedArrayBuffer();
614
}
615
616
template <typename T>
617
class ArrayBufferOrViewContents {
618
 public:
619
  ArrayBufferOrViewContents() = default;
620
621
218468
  inline explicit ArrayBufferOrViewContents(v8::Local<v8::Value> buf) {
622
218468
    CHECK(IsAnyByteSource(buf));
623
218468
    if (buf->IsArrayBufferView()) {
624
216608
      auto view = buf.As<v8::ArrayBufferView>();
625
216608
      offset_ = view->ByteOffset();
626
216608
      length_ = view->ByteLength();
627
433216
      store_ = view->Buffer()->GetBackingStore();
628
1860
    } else if (buf->IsArrayBuffer()) {
629
1840
      auto ab = buf.As<v8::ArrayBuffer>();
630
1840
      offset_ = 0;
631
1840
      length_ = ab->ByteLength();
632
1840
      store_ = ab->GetBackingStore();
633
    } else {
634
20
      auto sab = buf.As<v8::SharedArrayBuffer>();
635
20
      offset_ = 0;
636
20
      length_ = sab->ByteLength();
637
20
      store_ = sab->GetBackingStore();
638
    }
639
218468
  }
640
641
14083
  inline const T* data() const {
642
    // Ideally, these would return nullptr if IsEmpty() or length_ is zero,
643
    // but some of the openssl API react badly if given a nullptr even when
644
    // length is zero, so we have to return something.
645
14083
    if (size() == 0)
646
109
      return &buf;
647
13974
    return reinterpret_cast<T*>(store_->Data()) + offset_;
648
  }
649
650
102959
  inline T* data() {
651
    // Ideally, these would return nullptr if IsEmpty() or length_ is zero,
652
    // but some of the openssl API react badly if given a nullptr even when
653
    // length is zero, so we have to return something.
654
102959
    if (size() == 0)
655
3
      return &buf;
656
102956
    return reinterpret_cast<T*>(store_->Data()) + offset_;
657
  }
658
659
673236
  inline size_t size() const { return length_; }
660
661
  // In most cases, input buffer sizes passed in to openssl need to
662
  // be limited to <= INT_MAX. This utility method helps us check.
663
213985
  inline bool CheckSizeInt32() { return size() <= INT_MAX; }
664
665
5023
  inline ByteSource ToByteSource() const {
666
5023
    return ByteSource::Foreign(data(), size());
667
  }
668
669
7135
  inline ByteSource ToCopy() const {
670
7135
    if (size() == 0) return ByteSource();
671
6528
    char* buf = MallocOpenSSL<char>(size());
672
6528
    CHECK_NOT_NULL(buf);
673
6528
    memcpy(buf, data(), size());
674
6528
    return ByteSource::Allocated(buf, size());
675
  }
676
677
96
  inline ByteSource ToNullTerminatedCopy() const {
678
96
    if (size() == 0) return ByteSource();
679
90
    char* buf = MallocOpenSSL<char>(size() + 1);
680
90
    CHECK_NOT_NULL(buf);
681
90
    buf[size()] = 0;
682
90
    memcpy(buf, data(), size());
683
90
    return ByteSource::Allocated(buf, size());
684
  }
685
686
  template <typename M>
687
85
  void CopyTo(M* dest, size_t len) const {
688
    static_assert(sizeof(M) == 1, "sizeof(M) must equal 1");
689
85
    len = std::min(len, size());
690

85
    if (len > 0 && data() != nullptr)
691
85
      memcpy(dest, data(), len);
692
85
  }
693
694
 private:
695
  T buf = 0;
696
  size_t offset_ = 0;
697
  size_t length_ = 0;
698
  std::shared_ptr<v8::BackingStore> store_;
699
};
700
701
template <typename T>
702
std::vector<T> CopyBuffer(const ArrayBufferOrViewContents<T>& buf) {
703
  std::vector<T> vec;
704
  vec->resize(buf.size());
705
  if (vec->size() > 0 && buf.data() != nullptr)
706
    memcpy(vec->data(), buf.data(), vec->size());
707
  return vec;
708
}
709
710
template <typename T>
711
std::vector<T> CopyBuffer(v8::Local<v8::Value> buf) {
712
  return CopyBuffer(ArrayBufferOrViewContents<T>(buf));
713
}
714
715
v8::MaybeLocal<v8::Value> EncodeBignum(
716
    Environment* env,
717
    const BIGNUM* bn,
718
    int size,
719
    v8::Local<v8::Value>* error);
720
721
v8::Maybe<bool> SetEncodedValue(
722
    Environment* env,
723
    v8::Local<v8::Object> target,
724
    v8::Local<v8::String> name,
725
    const BIGNUM* bn,
726
    int size = 0);
727
728
namespace Util {
729
void Initialize(Environment* env, v8::Local<v8::Object> target);
730
}  // namespace Util
731
732
}  // namespace crypto
733
}  // namespace node
734
735
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
736
#endif  // SRC_CRYPTO_CRYPTO_UTIL_H_