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 |