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.h Lines: 199 213 93.4 %
Date: 2021-02-11 04:11:15 Branches: 119 200 59.5 %

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
26
#include <algorithm>
27
#include <memory>
28
#include <string>
29
#include <vector>
30
#include <climits>
31
#include <cstdio>
32
33
namespace node {
34
namespace crypto {
35
// Currently known sizes of commonly used OpenSSL struct sizes.
36
// OpenSSL considers it's various structs to be opaque and the
37
// sizes may change from one version of OpenSSL to another, so
38
// these values should not be trusted to remain static. These
39
// are provided to allow for some close to reasonable memory
40
// tracking.
41
constexpr size_t kSizeOf_DH = 144;
42
constexpr size_t kSizeOf_EC_KEY = 80;
43
constexpr size_t kSizeOf_EVP_CIPHER_CTX = 168;
44
constexpr size_t kSizeOf_EVP_MD_CTX = 48;
45
constexpr size_t kSizeOf_EVP_PKEY = 72;
46
constexpr size_t kSizeOf_EVP_PKEY_CTX = 80;
47
constexpr size_t kSizeOf_HMAC_CTX = 32;
48
49
// Define smart pointers for the most commonly used OpenSSL types:
50
using X509Pointer = DeleteFnPtr<X509, X509_free>;
51
using BIOPointer = DeleteFnPtr<BIO, BIO_free_all>;
52
using SSLCtxPointer = DeleteFnPtr<SSL_CTX, SSL_CTX_free>;
53
using SSLSessionPointer = DeleteFnPtr<SSL_SESSION, SSL_SESSION_free>;
54
using SSLPointer = DeleteFnPtr<SSL, SSL_free>;
55
using PKCS8Pointer = DeleteFnPtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free>;
56
using EVPKeyPointer = DeleteFnPtr<EVP_PKEY, EVP_PKEY_free>;
57
using EVPKeyCtxPointer = DeleteFnPtr<EVP_PKEY_CTX, EVP_PKEY_CTX_free>;
58
using EVPMDPointer = DeleteFnPtr<EVP_MD_CTX, EVP_MD_CTX_free>;
59
using RSAPointer = DeleteFnPtr<RSA, RSA_free>;
60
using ECPointer = DeleteFnPtr<EC_KEY, EC_KEY_free>;
61
using BignumPointer = DeleteFnPtr<BIGNUM, BN_free>;
62
using BignumCtxPointer = DeleteFnPtr<BN_CTX, BN_CTX_free>;
63
using NetscapeSPKIPointer = DeleteFnPtr<NETSCAPE_SPKI, NETSCAPE_SPKI_free>;
64
using ECGroupPointer = DeleteFnPtr<EC_GROUP, EC_GROUP_free>;
65
using ECPointPointer = DeleteFnPtr<EC_POINT, EC_POINT_free>;
66
using ECKeyPointer = DeleteFnPtr<EC_KEY, EC_KEY_free>;
67
using DHPointer = DeleteFnPtr<DH, DH_free>;
68
using ECDSASigPointer = DeleteFnPtr<ECDSA_SIG, ECDSA_SIG_free>;
69
using HMACCtxPointer = DeleteFnPtr<HMAC_CTX, HMAC_CTX_free>;
70
using CipherCtxPointer = DeleteFnPtr<EVP_CIPHER_CTX, EVP_CIPHER_CTX_free>;
71
using RsaPointer = DeleteFnPtr<RSA, RSA_free>;
72
using DsaPointer = DeleteFnPtr<DSA, DSA_free>;
73
using EcdsaSigPointer = DeleteFnPtr<ECDSA_SIG, ECDSA_SIG_free>;
74
75
// Our custom implementation of the certificate verify callback
76
// used when establishing a TLS handshake. Because we cannot perform
77
// I/O quickly enough with X509_STORE_CTX_ APIs in this callback,
78
// we ignore preverify_ok errors here and let the handshake continue.
79
// In other words, this VerifyCallback is a non-op. It is imperative
80
// that the user user Connection::VerifyError after the `secure`
81
// callback has been made.
82
extern int VerifyCallback(int preverify_ok, X509_STORE_CTX* ctx);
83
84
void InitCryptoOnce();
85
86
void InitCrypto(v8::Local<v8::Object> target);
87
88
extern void UseExtraCaCerts(const std::string& file);
89
90
// Forcibly clear OpenSSL's error stack on return. This stops stale errors
91
// from popping up later in the lifecycle of crypto operations where they
92
// would cause spurious failures. It's a rather blunt method, though.
93
// ERR_clear_error() isn't necessarily cheap either.
94
struct ClearErrorOnReturn {
95
8627
  ~ClearErrorOnReturn() { ERR_clear_error(); }
96
};
97
98
// Pop errors from OpenSSL's error stack that were added
99
// between when this was constructed and destructed.
100
struct MarkPopErrorOnReturn {
101
20297
  MarkPopErrorOnReturn() { ERR_set_mark(); }
102
20296
  ~MarkPopErrorOnReturn() { ERR_pop_to_mark(); }
103
};
104
105
// Ensure that OpenSSL has enough entropy (at least 256 bits) for its PRNG.
106
// The entropy pool starts out empty and needs to fill up before the PRNG
107
// can be used securely.  Once the pool is filled, it never dries up again;
108
// its contents is stirred and reused when necessary.
109
//
110
// OpenSSL normally fills the pool automatically but not when someone starts
111
// generating random numbers before the pool is full: in that case OpenSSL
112
// keeps lowering the entropy estimate to thwart attackers trying to guess
113
// the initial state of the PRNG.
114
//
115
// When that happens, we will have to wait until enough entropy is available.
116
// That should normally never take longer than a few milliseconds.
117
//
118
// OpenSSL draws from /dev/random and /dev/urandom.  While /dev/random may
119
// block pending "true" randomness, /dev/urandom is a CSPRNG that doesn't
120
// block under normal circumstances.
121
//
122
// The only time when /dev/urandom may conceivably block is right after boot,
123
// when the whole system is still low on entropy.  That's not something we can
124
// do anything about.
125
void CheckEntropy();
126
127
// Generate length bytes of random data. If this returns false, the data
128
// may not be truly random but it's still generally good enough.
129
bool EntropySource(unsigned char* buffer, size_t length);
130
131
int PasswordCallback(char* buf, int size, int rwflag, void* u);
132
133
int NoPasswordCallback(char* buf, int size, int rwflag, void* u);
134
135
// Decode is used by the various stream-based crypto utilities to decode
136
// string input.
137
template <typename T>
138
14566
void Decode(const v8::FunctionCallbackInfo<v8::Value>& args,
139
            void (*callback)(T*, const v8::FunctionCallbackInfo<v8::Value>&,
140
                             const char*, size_t)) {
141
  T* ctx;
142

14566
  ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
143
144

43698
  if (args[0]->IsString()) {
145
26374
    StringBytes::InlineDecoder decoder;
146
13187
    Environment* env = Environment::GetCurrent(args);
147
13187
    enum encoding enc = ParseEncoding(env->isolate(), args[1], UTF8);
148

39561
    if (decoder.Decode(env, args[0].As<v8::String>(), enc).IsNothing())
149
      return;
150

13187
    callback(ctx, args, decoder.out(), decoder.size());
151
  } else {
152
1379
    ArrayBufferViewContents<char> buf(args[0]);
153
1379
    callback(ctx, args, buf.data(), buf.length());
154
  }
155
}
156
157
// Utility struct used to harvest error information from openssl's error stack
158
7289
struct CryptoErrorVector : public std::vector<std::string> {
159
  void Capture();
160
161
  v8::MaybeLocal<v8::Value> ToException(
162
      Environment* env,
163
      v8::Local<v8::String> exception_string = v8::Local<v8::String>()) const;
164
};
165
166
template <typename T>
167
22545
T* MallocOpenSSL(size_t count) {
168
22545
  void* mem = OPENSSL_malloc(MultiplyWithOverflowCheck(count, sizeof(T)));
169


22545
  CHECK_IMPLIES(mem == nullptr, count == 0);
170
22545
  return static_cast<T*>(mem);
171
}
172
173
template <typename T>
174
440
T* ReallocOpenSSL(T* buf, size_t count) {
175
440
  void* mem = OPENSSL_realloc(buf, MultiplyWithOverflowCheck(count, sizeof(T)));
176

440
  CHECK_IMPLIES(mem == nullptr, count == 0);
177
440
  return static_cast<T*>(mem);
178
}
179
180
// A helper class representing a read-only byte array. When deallocated, its
181
// contents are zeroed.
182
class ByteSource {
183
 public:
184
25703
  ByteSource() = default;
185
  ByteSource(ByteSource&& other) noexcept;
186
  ~ByteSource();
187
188
  ByteSource& operator=(ByteSource&& other) noexcept;
189
190
  const char* get() const;
191
192
  template <typename T>
193
3860
  const T* data() const { return reinterpret_cast<const T*>(get()); }
194
195
  size_t size() const;
196
197
16049
  operator bool() const { return data_ != nullptr; }
198
199
1001
  BignumPointer ToBN() const {
200
    return BignumPointer(BN_bin2bn(
201
1001
        reinterpret_cast<const unsigned char*>(get()),
202
1001
        size(),
203
2002
        nullptr));
204
  }
205
206
  // Creates a v8::BackingStore that takes over responsibility for
207
  // any allocated data. The ByteSource will be reset with size = 0
208
  // after being called.
209
  std::unique_ptr<v8::BackingStore> ReleaseToBackingStore();
210
211
  v8::Local<v8::ArrayBuffer> ToArrayBuffer(Environment* env);
212
213
  void reset();
214
215
  // Allows an Allocated ByteSource to be truncated.
216
439
  void Resize(size_t newsize) {
217
439
    CHECK_LE(newsize, size_);
218
439
    CHECK_NOT_NULL(allocated_data_);
219
439
    char* new_data_ = ReallocOpenSSL<char>(allocated_data_, newsize);
220
440
    data_ = allocated_data_ = new_data_;
221
440
    size_ = newsize;
222
440
  }
223
224
  static ByteSource Allocated(char* data, size_t size);
225
  static ByteSource Foreign(const char* data, size_t size);
226
227
  static ByteSource FromEncodedString(Environment* env,
228
                                      v8::Local<v8::String> value,
229
                                      enum encoding enc = BASE64);
230
231
  static ByteSource FromStringOrBuffer(Environment* env,
232
                                       v8::Local<v8::Value> value);
233
234
  static ByteSource FromString(Environment* env,
235
                               v8::Local<v8::String> str,
236
                               bool ntc = false);
237
238
  static ByteSource FromBuffer(v8::Local<v8::Value> buffer,
239
                               bool ntc = false);
240
241
  static ByteSource FromBIO(const BIOPointer& bio);
242
243
  static ByteSource NullTerminatedCopy(Environment* env,
244
                                       v8::Local<v8::Value> value);
245
246
  static ByteSource FromSymmetricKeyObjectHandle(v8::Local<v8::Value> handle);
247
248
  ByteSource(const ByteSource&) = delete;
249
  ByteSource& operator=(const ByteSource&) = delete;
250
251
  static ByteSource FromSecretKeyBytes(
252
      Environment* env, v8::Local<v8::Value> value);
253
254
 private:
255
  const char* data_ = nullptr;
256
  char* allocated_data_ = nullptr;
257
  size_t size_ = 0;
258
259
  ByteSource(const char* data, char* allocated_data, size_t size);
260
};
261
262
enum CryptoJobMode {
263
  kCryptoJobAsync,
264
  kCryptoJobSync
265
};
266
267
CryptoJobMode GetCryptoJobMode(v8::Local<v8::Value> args);
268
269
template <typename CryptoJobTraits>
270
3548
class CryptoJob : public AsyncWrap, public ThreadPoolWork {
271
 public:
272
  using AdditionalParams = typename CryptoJobTraits::AdditionalParameters;
273
274
3549
  explicit CryptoJob(
275
      Environment* env,
276
      v8::Local<v8::Object> object,
277
      AsyncWrap::ProviderType type,
278
      CryptoJobMode mode,
279
      AdditionalParams&& params)
280
      : AsyncWrap(env, object, type),
281
        ThreadPoolWork(env),
282
        mode_(mode),
283
3549
        params_(std::move(params)) {
284
    // If the CryptoJob is async, then the instance will be
285
    // cleaned up when AfterThreadPoolWork is called.
286

3549
    if (mode == kCryptoJobSync) MakeWeak();
287
3549
  }
288
289
  bool IsNotIndicativeOfMemoryLeakAtExit() const override {
290
    // CryptoJobs run a work in the libuv thread pool and may still
291
    // exist when the event loop empties and starts to exit.
292
    return true;
293
  }
294
295
3125
  void AfterThreadPoolWork(int status) override {
296
3125
    Environment* env = AsyncWrap::env();
297

3125
    CHECK_EQ(mode_, kCryptoJobAsync);
298



3125
    CHECK(status == 0 || status == UV_ECANCELED);
299
6250
    std::unique_ptr<CryptoJob> ptr(this);
300
    // If the job was canceled do not execute the callback.
301
    // TODO(@jasnell): We should likely revisit skipping the
302
    // callback on cancel as that could leave the JS in a pending
303
    // state (e.g. unresolved promises...)
304

3125
    if (status == UV_ECANCELED) return;
305

6250
    v8::HandleScope handle_scope(env->isolate());
306
3125
    v8::Context::Scope context_scope(env->context());
307

9375
    v8::Local<v8::Value> args[2];
308

6250
    if (ptr->ToResult(&args[0], &args[1]).FromJust())
309
3125
      ptr->MakeCallback(env->ondone_string(), arraysize(args), args);
310
  }
311
312
  virtual v8::Maybe<bool> ToResult(
313
      v8::Local<v8::Value>* err,
314
      v8::Local<v8::Value>* result) = 0;
315
316
3542
  CryptoJobMode mode() const { return mode_; }
317
318
3559
  CryptoErrorVector* errors() { return &errors_; }
319
320
6397
  AdditionalParams* params() { return &params_; }
321
322
3
  std::string MemoryInfoName() const override {
323
3
    return CryptoJobTraits::JobName;
324
  }
325
326
3
  void MemoryInfo(MemoryTracker* tracker) const override {
327
3
    tracker->TrackField("params", params_);
328
3
    tracker->TrackField("errors", errors_);
329
3
  }
330
331
3542
  static void Run(const v8::FunctionCallbackInfo<v8::Value>& args) {
332
3542
    Environment* env = Environment::GetCurrent(args);
333
334
    CryptoJob<CryptoJobTraits>* job;
335

6668
    ASSIGN_OR_RETURN_UNWRAP(&job, args.Holder());
336

3542
    if (job->mode() == kCryptoJobAsync)
337
3126
      return job->ScheduleWork();
338
339

1248
    v8::Local<v8::Value> ret[2];
340
416
    env->PrintSyncTrace();
341
416
    job->DoThreadPoolWork();
342

832
    if (job->ToResult(&ret[0], &ret[1]).FromJust()) {
343
1248
      args.GetReturnValue().Set(
344
          v8::Array::New(env->isolate(), ret, arraysize(ret)));
345
    }
346
  }
347
348
15341
  static void Initialize(
349
      v8::FunctionCallback new_fn,
350
      Environment* env,
351
      v8::Local<v8::Object> target) {
352
15341
    v8::Local<v8::FunctionTemplate> job = env->NewFunctionTemplate(new_fn);
353
30682
    job->Inherit(AsyncWrap::GetConstructorTemplate(env));
354
30682
    job->InstanceTemplate()->SetInternalFieldCount(
355
        AsyncWrap::kInternalFieldCount);
356
15341
    env->SetProtoMethod(job, "run", Run);
357
15341
    env->SetConstructorFunction(target, CryptoJobTraits::JobName, job);
358
15341
  }
359
360
 private:
361
  const CryptoJobMode mode_;
362
  CryptoErrorVector errors_;
363
  AdditionalParams params_;
364
};
365
366
template <typename DeriveBitsTraits>
367
5260
class DeriveBitsJob final : public CryptoJob<DeriveBitsTraits> {
368
 public:
369
  using AdditionalParams = typename DeriveBitsTraits::AdditionalParameters;
370
371
2655
  static void New(const v8::FunctionCallbackInfo<v8::Value>& args) {
372
2655
    Environment* env = Environment::GetCurrent(args);
373
374
2655
    CryptoJobMode mode = GetCryptoJobMode(args[0]);
375
376
5285
    AdditionalParams params;
377

5310
    if (DeriveBitsTraits::AdditionalConfig(mode, args, 1, &params)
378
            .IsNothing()) {
379
      // The DeriveBitsTraits::AdditionalConfig is responsible for
380
      // calling an appropriate THROW_CRYPTO_* variant reporting
381
      // whatever error caused initialization to fail.
382
25
      return;
383
    }
384
385

2630
    new DeriveBitsJob(env, args.This(), mode, std::move(params));
386
  }
387
388
7337
  static void Initialize(
389
      Environment* env,
390
      v8::Local<v8::Object> target) {
391
7337
    CryptoJob<DeriveBitsTraits>::Initialize(New, env, target);
392
7337
  }
393
394
2630
  DeriveBitsJob(
395
      Environment* env,
396
      v8::Local<v8::Object> object,
397
      CryptoJobMode mode,
398
      AdditionalParams&& params)
399
      : CryptoJob<DeriveBitsTraits>(
400
            env,
401
            object,
402
            DeriveBitsTraits::Provider,
403
            mode,
404
2630
            std::move(params)) {}
405
406
2630
  void DoThreadPoolWork() override {
407

5260
    if (!DeriveBitsTraits::DeriveBits(
408
            AsyncWrap::env(),
409
2630
            *CryptoJob<DeriveBitsTraits>::params(), &out_)) {
410
      CryptoErrorVector* errors = CryptoJob<DeriveBitsTraits>::errors();
411
      errors->Capture();
412
      if (errors->empty())
413
        errors->push_back("Deriving bits failed");
414
      return;
415
    }
416
2630
    success_ = true;
417
  }
418
419
2630
  v8::Maybe<bool> ToResult(
420
      v8::Local<v8::Value>* err,
421
      v8::Local<v8::Value>* result) override {
422
2630
    Environment* env = AsyncWrap::env();
423
2630
    CryptoErrorVector* errors = CryptoJob<DeriveBitsTraits>::errors();
424

2630
    if (success_) {
425

2630
      CHECK(errors->empty());
426
5260
      *err = v8::Undefined(env->isolate());
427
2630
      return DeriveBitsTraits::EncodeOutput(
428
          env,
429
2630
          *CryptoJob<DeriveBitsTraits>::params(),
430
          &out_,
431
2630
          result);
432
    }
433
434
    if (errors->empty())
435
      errors->Capture();
436
    CHECK(!errors->empty());
437
    *result = v8::Undefined(env->isolate());
438
    return v8::Just(errors->ToException(env).ToLocal(err));
439
  }
440
441
3
  SET_SELF_SIZE(DeriveBitsJob);
442
3
  void MemoryInfo(MemoryTracker* tracker) const override {
443
3
    tracker->TrackFieldWithSize("out", out_.size());
444
3
    CryptoJob<DeriveBitsTraits>::MemoryInfo(tracker);
445
3
  }
446
447
 private:
448
  ByteSource out_;
449
  bool success_ = false;
450
};
451
452
void ThrowCryptoError(Environment* env,
453
                      unsigned long err,  // NOLINT(runtime/int)
454
                      const char* message = nullptr);
455
456
#ifndef OPENSSL_NO_ENGINE
457
struct EnginePointer {
458
  ENGINE* engine = nullptr;
459
  bool finish_on_exit = false;
460
461
2333
  inline EnginePointer() = default;
462
463
4
  inline explicit EnginePointer(ENGINE* engine_, bool finish_on_exit_ = false)
464
4
    : engine(engine_),
465
4
      finish_on_exit(finish_on_exit_) {}
466
467
2
  inline EnginePointer(EnginePointer&& other) noexcept
468
2
      : engine(other.engine),
469
2
        finish_on_exit(other.finish_on_exit) {
470
2
    other.release();
471
2
  }
472
473
2318
  inline ~EnginePointer() { reset(); }
474
475
2
  inline EnginePointer& operator=(EnginePointer&& other) noexcept {
476
2
    if (this == &other) return *this;
477
2
    this->~EnginePointer();
478
2
    return *new (this) EnginePointer(std::move(other));
479
  }
480
481
8
  inline operator bool() const { return engine != nullptr; }
482
483
4
  inline ENGINE* get() { return engine; }
484
485
2320
  inline void reset(ENGINE* engine_ = nullptr, bool finish_on_exit_ = false) {
486
2320
    if (engine != nullptr) {
487
2
      if (finish_on_exit)
488
        ENGINE_finish(engine);
489
2
      ENGINE_free(engine);
490
    }
491
2320
    engine = engine_;
492
2320
    finish_on_exit = finish_on_exit_;
493
2320
  }
494
495
2
  inline ENGINE* release() {
496
2
    ENGINE* ret = engine;
497
2
    engine = nullptr;
498
2
    finish_on_exit = false;
499
2
    return ret;
500
  }
501
};
502
503
EnginePointer LoadEngineById(const char* id, CryptoErrorVector* errors);
504
505
bool SetEngine(
506
    const char* id,
507
    uint32_t flags,
508
    CryptoErrorVector* errors = nullptr);
509
510
void SetEngine(const v8::FunctionCallbackInfo<v8::Value>& args);
511
#endif  // !OPENSSL_NO_ENGINE
512
513
#ifdef NODE_FIPS_MODE
514
void GetFipsCrypto(const v8::FunctionCallbackInfo<v8::Value>& args);
515
516
void SetFipsCrypto(const v8::FunctionCallbackInfo<v8::Value>& args);
517
#endif /* NODE_FIPS_MODE */
518
519
10
class CipherPushContext {
520
 public:
521
10
  inline explicit CipherPushContext(Environment* env) : env_(env) {}
522
523
938
  inline void push_back(const char* str) {
524
938
    list_.emplace_back(OneByteString(env_->isolate(), str));
525
938
  }
526
527
10
  inline v8::Local<v8::Array> ToJSArray() {
528
10
    return v8::Array::New(env_->isolate(), list_.data(), list_.size());
529
  }
530
531
 private:
532
  std::vector<v8::Local<v8::Value>> list_;
533
  Environment* env_;
534
};
535
536
template <class TypeName>
537
938
void array_push_back(const TypeName* md,
538
                     const char* from,
539
                     const char* to,
540
                     void* arg) {
541
938
  static_cast<CipherPushContext*>(arg)->push_back(from);
542
938
}
543
544
123138
inline bool IsAnyByteSource(v8::Local<v8::Value> arg) {
545
127189
  return arg->IsArrayBufferView() ||
546

129294
         arg->IsArrayBuffer() ||
547
125243
         arg->IsSharedArrayBuffer();
548
}
549
550
template <typename T>
551
116512
class ArrayBufferOrViewContents {
552
 public:
553
  ArrayBufferOrViewContents() = default;
554
555
114010
  inline explicit ArrayBufferOrViewContents(v8::Local<v8::Value> buf) {
556

114010
    CHECK(IsAnyByteSource(buf));
557

114010
    if (buf->IsArrayBufferView()) {
558
112648
      auto view = buf.As<v8::ArrayBufferView>();
559
112648
      offset_ = view->ByteOffset();
560
112648
      length_ = view->ByteLength();
561
225296
      store_ = view->Buffer()->GetBackingStore();
562

1362
    } else if (buf->IsArrayBuffer()) {
563
1344
      auto ab = buf.As<v8::ArrayBuffer>();
564
1344
      offset_ = 0;
565
1344
      length_ = ab->ByteLength();
566
1344
      store_ = ab->GetBackingStore();
567
    } else {
568
18
      auto sab = buf.As<v8::SharedArrayBuffer>();
569
18
      offset_ = 0;
570
18
      length_ = sab->ByteLength();
571
18
      store_ = sab->GetBackingStore();
572
    }
573
114010
  }
574
575
9616
  inline const T* data() const {
576
    // Ideally, these would return nullptr if IsEmpty() or length_ is zero,
577
    // but some of the openssl API react badly if given a nullptr even when
578
    // length is zero, so we have to return something.
579

9616
    if (size() == 0)
580
54
      return &buf;
581
9562
    return reinterpret_cast<T*>(store_->Data()) + offset_;
582
  }
583
584
103455
  inline T* data() {
585
    // Ideally, these would return nullptr if IsEmpty() or length_ is zero,
586
    // but some of the openssl API react badly if given a nullptr even when
587
    // length is zero, so we have to return something.
588

103455
    if (size() == 0)
589
33
      return &buf;
590
103422
    return reinterpret_cast<T*>(store_->Data()) + offset_;
591
  }
592
593
355447
  inline size_t size() const { return length_; }
594
595
  // In most cases, input buffer sizes passed in to openssl need to
596
  // be limited to <= INT_MAX. This utility method helps us check.
597
109891
  inline bool CheckSizeInt32() { return size() <= INT_MAX; }
598
599
2830
  inline ByteSource ToByteSource() const {
600
2830
    return ByteSource::Foreign(data(), size());
601
  }
602
603
6201
  inline ByteSource ToCopy() const {
604
6201
    if (size() == 0) return ByteSource();
605
5403
    char* buf = MallocOpenSSL<char>(size());
606
5403
    CHECK_NOT_NULL(buf);
607
5403
    memcpy(buf, data(), size());
608
5403
    return ByteSource::Allocated(buf, size());
609
  }
610
611
96
  inline ByteSource ToNullTerminatedCopy() const {
612
96
    if (size() == 0) return ByteSource();
613
90
    char* buf = MallocOpenSSL<char>(size() + 1);
614
90
    CHECK_NOT_NULL(buf);
615
90
    buf[size()] = 0;
616
90
    memcpy(buf, data(), size());
617
90
    return ByteSource::Allocated(buf, size());
618
  }
619
620
  template <typename M>
621
85
  void CopyTo(M* dest, size_t len) const {
622
    static_assert(sizeof(M) == 1, "sizeof(M) must equal 1");
623
85
    len = std::min(len, size());
624

85
    if (len > 0 && data() != nullptr)
625
85
      memcpy(dest, data(), len);
626
85
  }
627
628
 private:
629
  T buf = 0;
630
  size_t offset_ = 0;
631
  size_t length_ = 0;
632
  std::shared_ptr<v8::BackingStore> store_;
633
};
634
635
template <typename T>
636
std::vector<T> CopyBuffer(const ArrayBufferOrViewContents<T>& buf) {
637
  std::vector<T> vec;
638
  vec->resize(buf.size());
639
  if (vec->size() > 0 && buf.data() != nullptr)
640
    memcpy(vec->data(), buf.data(), vec->size());
641
  return vec;
642
}
643
644
template <typename T>
645
std::vector<T> CopyBuffer(v8::Local<v8::Value> buf) {
646
  return CopyBuffer(ArrayBufferOrViewContents<T>(buf));
647
}
648
649
v8::MaybeLocal<v8::Value> EncodeBignum(
650
    Environment* env,
651
    const BIGNUM* bn,
652
    int size,
653
    v8::Local<v8::Value>* error);
654
655
v8::Maybe<bool> SetEncodedValue(
656
    Environment* env,
657
    v8::Local<v8::Object> target,
658
    v8::Local<v8::String> name,
659
    const BIGNUM* bn,
660
    int size = 0);
661
662
namespace Util {
663
void Initialize(Environment* env, v8::Local<v8::Object> target);
664
}  // namespace Util
665
666
}  // namespace crypto
667
}  // namespace node
668
669
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
670
#endif  // SRC_CRYPTO_CRYPTO_UTIL_H_