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: 202 216 93.5 %
Date: 2020-11-20 19:51:53 Branches: 118 200 59.0 %

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 NetscapeSPKIPointer = DeleteFnPtr<NETSCAPE_SPKI, NETSCAPE_SPKI_free>;
63
using ECGroupPointer = DeleteFnPtr<EC_GROUP, EC_GROUP_free>;
64
using ECPointPointer = DeleteFnPtr<EC_POINT, EC_POINT_free>;
65
using ECKeyPointer = DeleteFnPtr<EC_KEY, EC_KEY_free>;
66
using DHPointer = DeleteFnPtr<DH, DH_free>;
67
using ECDSASigPointer = DeleteFnPtr<ECDSA_SIG, ECDSA_SIG_free>;
68
using HMACCtxPointer = DeleteFnPtr<HMAC_CTX, HMAC_CTX_free>;
69
using CipherCtxPointer = DeleteFnPtr<EVP_CIPHER_CTX, EVP_CIPHER_CTX_free>;
70
using RsaPointer = DeleteFnPtr<RSA, RSA_free>;
71
using DsaPointer = DeleteFnPtr<DSA, DSA_free>;
72
using EcdsaSigPointer = DeleteFnPtr<ECDSA_SIG, ECDSA_SIG_free>;
73
74
// Our custom implementation of the certificate verify callback
75
// used when establishing a TLS handshake. Because we cannot perform
76
// I/O quickly enough with X509_STORE_CTX_ APIs in this callback,
77
// we ignore preverify_ok errors here and let the handshake continue.
78
// In other words, this VerifyCallback is a non-op. It is imperative
79
// that the user user Connection::VerifyError after the `secure`
80
// callback has been made.
81
extern int VerifyCallback(int preverify_ok, X509_STORE_CTX* ctx);
82
83
void InitCryptoOnce();
84
85
void InitCrypto(v8::Local<v8::Object> target);
86
87
extern void UseExtraCaCerts(const std::string& file);
88
89
// Forcibly clear OpenSSL's error stack on return. This stops stale errors
90
// from popping up later in the lifecycle of crypto operations where they
91
// would cause spurious failures. It's a rather blunt method, though.
92
// ERR_clear_error() isn't necessarily cheap either.
93
struct ClearErrorOnReturn {
94
8544
  ~ClearErrorOnReturn() { ERR_clear_error(); }
95
};
96
97
// Pop errors from OpenSSL's error stack that were added
98
// between when this was constructed and destructed.
99
struct MarkPopErrorOnReturn {
100
20145
  MarkPopErrorOnReturn() { ERR_set_mark(); }
101
20144
  ~MarkPopErrorOnReturn() { ERR_pop_to_mark(); }
102
};
103
104
// Ensure that OpenSSL has enough entropy (at least 256 bits) for its PRNG.
105
// The entropy pool starts out empty and needs to fill up before the PRNG
106
// can be used securely.  Once the pool is filled, it never dries up again;
107
// its contents is stirred and reused when necessary.
108
//
109
// OpenSSL normally fills the pool automatically but not when someone starts
110
// generating random numbers before the pool is full: in that case OpenSSL
111
// keeps lowering the entropy estimate to thwart attackers trying to guess
112
// the initial state of the PRNG.
113
//
114
// When that happens, we will have to wait until enough entropy is available.
115
// That should normally never take longer than a few milliseconds.
116
//
117
// OpenSSL draws from /dev/random and /dev/urandom.  While /dev/random may
118
// block pending "true" randomness, /dev/urandom is a CSPRNG that doesn't
119
// block under normal circumstances.
120
//
121
// The only time when /dev/urandom may conceivably block is right after boot,
122
// when the whole system is still low on entropy.  That's not something we can
123
// do anything about.
124
void CheckEntropy();
125
126
// Generate length bytes of random data. If this returns false, the data
127
// may not be truly random but it's still generally good enough.
128
bool EntropySource(unsigned char* buffer, size_t length);
129
130
int PasswordCallback(char* buf, int size, int rwflag, void* u);
131
132
int NoPasswordCallback(char* buf, int size, int rwflag, void* u);
133
134
// Decode is used by the various stream-based crypto utilities to decode
135
// string input.
136
template <typename T>
137
3243
void Decode(const v8::FunctionCallbackInfo<v8::Value>& args,
138
            void (*callback)(T*, const v8::FunctionCallbackInfo<v8::Value>&,
139
                             const char*, size_t)) {
140
  T* ctx;
141

3243
  ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
142
143

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

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

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


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

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

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

3067
    CHECK_EQ(mode_, kCryptoJobAsync);
297



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

3067
    if (status == UV_ECANCELED) return;
304

6134
    v8::HandleScope handle_scope(env->isolate());
305
3067
    v8::Context::Scope context_scope(env->context());
306

9201
    v8::Local<v8::Value> args[2];
307

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

6517
    ASSIGN_OR_RETURN_UNWRAP(&job, args.Holder());
335

3449
    if (job->mode() == kCryptoJobAsync)
336
3068
      return job->ScheduleWork();
337
338

1143
    v8::Local<v8::Value> ret[2];
339
381
    env->PrintSyncTrace();
340
381
    job->DoThreadPoolWork();
341

762
    if (job->ToResult(&ret[0], &ret[1]).FromJust()) {
342
1143
      args.GetReturnValue().Set(
343
          v8::Array::New(env->isolate(), ret, arraysize(ret)));
344
    }
345
  }
346
347
13721
  static void Initialize(
348
      v8::FunctionCallback new_fn,
349
      Environment* env,
350
      v8::Local<v8::Object> target) {
351
13721
    v8::Local<v8::FunctionTemplate> job = env->NewFunctionTemplate(new_fn);
352
    v8::Local<v8::String> class_name =
353
13733
        OneByteString(env->isolate(), CryptoJobTraits::JobName);
354
13732
    job->SetClassName(class_name);
355
27464
    job->Inherit(AsyncWrap::GetConstructorTemplate(env));
356
27464
    job->InstanceTemplate()->SetInternalFieldCount(
357
        AsyncWrap::kInternalFieldCount);
358
13723
    env->SetProtoMethod(job, "run", Run);
359
41189
    target->Set(
360
        env->context(),
361
        class_name,
362
41190
        job->GetFunction(env->context()).ToLocalChecked()).Check();
363
13731
  }
364
365
 private:
366
  const CryptoJobMode mode_;
367
  CryptoErrorVector errors_;
368
  AdditionalParams params_;
369
};
370
371
template <typename DeriveBitsTraits>
372
5118
class DeriveBitsJob final : public CryptoJob<DeriveBitsTraits> {
373
 public:
374
  using AdditionalParams = typename DeriveBitsTraits::AdditionalParameters;
375
376
2578
  static void New(const v8::FunctionCallbackInfo<v8::Value>& args) {
377
2578
    Environment* env = Environment::GetCurrent(args);
378
379
2578
    CryptoJobMode mode = GetCryptoJobMode(args[0]);
380
381
5137
    AdditionalParams params;
382

5156
    if (DeriveBitsTraits::AdditionalConfig(mode, args, 1, &params)
383
            .IsNothing()) {
384
      // The DeriveBitsTraits::AdditionalConfig is responsible for
385
      // calling an appropriate THROW_CRYPTO_* variant reporting
386
      // whatever error caused initialization to fail.
387
19
      return;
388
    }
389
390

2559
    new DeriveBitsJob(env, args.This(), mode, std::move(params));
391
  }
392
393
5882
  static void Initialize(
394
      Environment* env,
395
      v8::Local<v8::Object> target) {
396
5882
    CryptoJob<DeriveBitsTraits>::Initialize(New, env, target);
397
5885
  }
398
399
2559
  DeriveBitsJob(
400
      Environment* env,
401
      v8::Local<v8::Object> object,
402
      CryptoJobMode mode,
403
      AdditionalParams&& params)
404
      : CryptoJob<DeriveBitsTraits>(
405
            env,
406
            object,
407
            DeriveBitsTraits::Provider,
408
            mode,
409
2559
            std::move(params)) {}
410
411
2559
  void DoThreadPoolWork() override {
412

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

2559
    if (success_) {
430

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

129013
         arg->IsArrayBuffer() ||
552
125009
         arg->IsSharedArrayBuffer();
553
}
554
555
template <typename T>
556
116372
class ArrayBufferOrViewContents {
557
 public:
558
  ArrayBufferOrViewContents() = default;
559
560
113870
  inline explicit ArrayBufferOrViewContents(v8::Local<v8::Value> buf) {
561

113870
    CHECK(IsAnyByteSource(buf));
562

113870
    if (buf->IsArrayBufferView()) {
563
112529
      auto view = buf.As<v8::ArrayBufferView>();
564
112529
      offset_ = view->ByteOffset();
565
112529
      length_ = view->ByteLength();
566
225058
      store_ = view->Buffer()->GetBackingStore();
567

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

9571
    if (size() == 0)
585
54
      return &buf;
586
9517
    return reinterpret_cast<T*>(store_->Data()) + offset_;
587
  }
588
589
103358
  inline T* data() {
590
    // Ideally, these would return nullptr if IsEmpty() or length_ is zero,
591
    // but some of the openssl API react badly if given a nullptr even when
592
    // length is zero, so we have to return something.
593

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

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