GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: crypto/crypto_scrypt.cc Lines: 59 70 84.3 %
Date: 2022-05-20 04:15:46 Branches: 28 52 53.8 %

Line Branch Exec Source
1
#include "crypto/crypto_scrypt.h"
2
#include "async_wrap-inl.h"
3
#include "crypto/crypto_util.h"
4
#include "env-inl.h"
5
#include "memory_tracker-inl.h"
6
#include "node_buffer.h"
7
#include "threadpoolwork-inl.h"
8
#include "v8.h"
9
10
namespace node {
11
12
using v8::FunctionCallbackInfo;
13
using v8::Int32;
14
using v8::Just;
15
using v8::Maybe;
16
using v8::Nothing;
17
using v8::Uint32;
18
using v8::Value;
19
20
namespace crypto {
21
#ifndef OPENSSL_NO_SCRYPT
22
23
31
ScryptConfig::ScryptConfig(ScryptConfig&& other) noexcept
24
31
  : mode(other.mode),
25
31
    pass(std::move(other.pass)),
26
31
    salt(std::move(other.salt)),
27
31
    N(other.N),
28
31
    r(other.r),
29
31
    p(other.p),
30
31
    maxmem(other.maxmem),
31
31
    length(other.length) {}
32
33
ScryptConfig& ScryptConfig::operator=(ScryptConfig&& other) noexcept {
34
  if (&other == this) return *this;
35
  this->~ScryptConfig();
36
  return *new (this) ScryptConfig(std::move(other));
37
}
38
39
1
void ScryptConfig::MemoryInfo(MemoryTracker* tracker) const {
40
1
  if (mode == kCryptoJobAsync) {
41
1
    tracker->TrackFieldWithSize("pass", pass.size());
42
1
    tracker->TrackFieldWithSize("salt", salt.size());
43
  }
44
1
}
45
46
31
Maybe<bool> ScryptTraits::EncodeOutput(
47
    Environment* env,
48
    const ScryptConfig& params,
49
    ByteSource* out,
50
    v8::Local<v8::Value>* result) {
51
62
  *result = out->ToArrayBuffer(env);
52
31
  return Just(!result->IsEmpty());
53
}
54
55
43
Maybe<bool> ScryptTraits::AdditionalConfig(
56
    CryptoJobMode mode,
57
    const FunctionCallbackInfo<Value>& args,
58
    unsigned int offset,
59
    ScryptConfig* params) {
60
43
  Environment* env = Environment::GetCurrent(args);
61
62
43
  params->mode = mode;
63
64
129
  ArrayBufferOrViewContents<char> pass(args[offset]);
65
129
  ArrayBufferOrViewContents<char> salt(args[offset + 1]);
66
67
43
  if (UNLIKELY(!pass.CheckSizeInt32())) {
68
    THROW_ERR_OUT_OF_RANGE(env, "pass is too large");
69
    return Nothing<bool>();
70
  }
71
72
43
  if (UNLIKELY(!salt.CheckSizeInt32())) {
73
    THROW_ERR_OUT_OF_RANGE(env, "salt is too large");
74
    return Nothing<bool>();
75
  }
76
77
  params->pass = mode == kCryptoJobAsync
78
86
      ? pass.ToCopy()
79
43
      : pass.ToByteSource();
80
81
  params->salt = mode == kCryptoJobAsync
82
86
      ? salt.ToCopy()
83
43
      : salt.ToByteSource();
84
85

86
  CHECK(args[offset + 2]->IsUint32());  // N
86

86
  CHECK(args[offset + 3]->IsUint32());  // r
87

86
  CHECK(args[offset + 4]->IsUint32());  // p
88

86
  CHECK(args[offset + 5]->IsNumber());  // maxmem
89

86
  CHECK(args[offset + 6]->IsInt32());  // length
90
91
129
  params->N = args[offset + 2].As<Uint32>()->Value();
92
129
  params->r = args[offset + 3].As<Uint32>()->Value();
93
129
  params->p = args[offset + 4].As<Uint32>()->Value();
94
86
  params->maxmem = args[offset + 5]->IntegerValue(env->context()).ToChecked();
95
96
215
  if (EVP_PBE_scrypt(
97
          nullptr,
98
          0,
99
          nullptr,
100
          0,
101
43
          params->N,
102
43
          params->r,
103
43
          params->p,
104
          params->maxmem,
105
          nullptr,
106
43
          0) != 1) {
107
12
    THROW_ERR_CRYPTO_INVALID_SCRYPT_PARAMS(env);
108
12
    return Nothing<bool>();
109
  }
110
111
93
  params->length = args[offset + 6].As<Int32>()->Value();
112
31
  if (params->length < 0) {
113
    THROW_ERR_OUT_OF_RANGE(env, "length must be <= %d", INT_MAX);
114
    return Nothing<bool>();
115
  }
116
117
31
  return Just(true);
118
}
119
120
31
bool ScryptTraits::DeriveBits(
121
    Environment* env,
122
    const ScryptConfig& params,
123
    ByteSource* out) {
124
31
  char* data = MallocOpenSSL<char>(params.length);
125
62
  ByteSource buf = ByteSource::Allocated(data, params.length);
126
31
  unsigned char* ptr = reinterpret_cast<unsigned char*>(data);
127
128
  // Both the pass and salt may be zero-length at this point
129
130
31
  if (!EVP_PBE_scrypt(
131
          params.pass.get(),
132
          params.pass.size(),
133
          params.salt.data<unsigned char>(),
134
          params.salt.size(),
135
31
          params.N,
136
31
          params.r,
137
31
          params.p,
138
31
          params.maxmem,
139
          ptr,
140
31
          params.length)) {
141
    return false;
142
  }
143
31
  *out = std::move(buf);
144
31
  return true;
145
}
146
147
#endif  // !OPENSSL_NO_SCRYPT
148
149
}  // namespace crypto
150
}  // namespace node