GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
#include "crypto/crypto_sig.h" |
||
2 |
#include "crypto/crypto_ecdh.h" |
||
3 |
#include "crypto/crypto_keys.h" |
||
4 |
#include "crypto/crypto_util.h" |
||
5 |
#include "allocated_buffer-inl.h" |
||
6 |
#include "async_wrap-inl.h" |
||
7 |
#include "base_object-inl.h" |
||
8 |
#include "env-inl.h" |
||
9 |
#include "memory_tracker-inl.h" |
||
10 |
#include "threadpoolwork-inl.h" |
||
11 |
#include "v8.h" |
||
12 |
|||
13 |
namespace node { |
||
14 |
|||
15 |
using v8::FunctionCallbackInfo; |
||
16 |
using v8::FunctionTemplate; |
||
17 |
using v8::HandleScope; |
||
18 |
using v8::Int32; |
||
19 |
using v8::Just; |
||
20 |
using v8::Local; |
||
21 |
using v8::Maybe; |
||
22 |
using v8::Nothing; |
||
23 |
using v8::Object; |
||
24 |
using v8::Uint32; |
||
25 |
using v8::Value; |
||
26 |
|||
27 |
namespace crypto { |
||
28 |
namespace { |
||
29 |
180 |
bool ValidateDSAParameters(EVP_PKEY* key) { |
|
30 |
#ifdef NODE_FIPS_MODE |
||
31 |
/* Validate DSA2 parameters from FIPS 186-4 */ |
||
32 |
if (FIPS_mode() && EVP_PKEY_DSA == EVP_PKEY_base_id(key)) { |
||
33 |
DSA* dsa = EVP_PKEY_get0_DSA(key); |
||
34 |
const BIGNUM* p; |
||
35 |
DSA_get0_pqg(dsa, &p, nullptr, nullptr); |
||
36 |
size_t L = BN_num_bits(p); |
||
37 |
const BIGNUM* q; |
||
38 |
DSA_get0_pqg(dsa, nullptr, &q, nullptr); |
||
39 |
size_t N = BN_num_bits(q); |
||
40 |
|||
41 |
return (L == 1024 && N == 160) || |
||
42 |
(L == 2048 && N == 224) || |
||
43 |
(L == 2048 && N == 256) || |
||
44 |
(L == 3072 && N == 256); |
||
45 |
} |
||
46 |
#endif // NODE_FIPS_MODE |
||
47 |
|||
48 |
180 |
return true; |
|
49 |
} |
||
50 |
|||
51 |
1486 |
bool ApplyRSAOptions(const ManagedEVPPKey& pkey, |
|
52 |
EVP_PKEY_CTX* pkctx, |
||
53 |
int padding, |
||
54 |
const Maybe<int>& salt_len) { |
||
55 |
✓✗✓✓ |
3427 |
if (EVP_PKEY_id(pkey.get()) == EVP_PKEY_RSA || |
56 |
✓✓✓✓ |
1941 |
EVP_PKEY_id(pkey.get()) == EVP_PKEY_RSA2 || |
57 |
455 |
EVP_PKEY_id(pkey.get()) == EVP_PKEY_RSA_PSS) { |
|
58 |
✓✓ | 1206 |
if (EVP_PKEY_CTX_set_rsa_padding(pkctx, padding) <= 0) |
59 |
3 |
return false; |
|
60 |
✓✓✓✓ ✓✓ |
2228 |
if (padding == RSA_PKCS1_PSS_PADDING && salt_len.IsJust()) { |
61 |
✓✓ | 976 |
if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, salt_len.FromJust()) <= 0) |
62 |
6 |
return false; |
|
63 |
} |
||
64 |
} |
||
65 |
|||
66 |
1477 |
return true; |
|
67 |
} |
||
68 |
|||
69 |
112 |
AllocatedBuffer Node_SignFinal(Environment* env, |
|
70 |
EVPMDPointer&& mdctx, |
||
71 |
const ManagedEVPPKey& pkey, |
||
72 |
int padding, |
||
73 |
Maybe<int> pss_salt_len) { |
||
74 |
unsigned char m[EVP_MAX_MD_SIZE]; |
||
75 |
unsigned int m_len; |
||
76 |
|||
77 |
✗✓ | 112 |
if (!EVP_DigestFinal_ex(mdctx.get(), m, &m_len)) |
78 |
return AllocatedBuffer(); |
||
79 |
|||
80 |
112 |
int signed_sig_len = EVP_PKEY_size(pkey.get()); |
|
81 |
✗✓ | 112 |
CHECK_GE(signed_sig_len, 0); |
82 |
112 |
size_t sig_len = static_cast<size_t>(signed_sig_len); |
|
83 |
224 |
AllocatedBuffer sig = AllocatedBuffer::AllocateManaged(env, sig_len); |
|
84 |
112 |
unsigned char* ptr = reinterpret_cast<unsigned char*>(sig.data()); |
|
85 |
|||
86 |
224 |
EVPKeyCtxPointer pkctx(EVP_PKEY_CTX_new(pkey.get(), nullptr)); |
|
87 |
✓✗✓✓ |
224 |
if (pkctx && |
88 |
✓✓ | 336 |
EVP_PKEY_sign_init(pkctx.get()) && |
89 |
✓✓ | 216 |
ApplyRSAOptions(pkey, pkctx.get(), padding, pss_salt_len) && |
90 |
✓✗✓✓ |
314 |
EVP_PKEY_CTX_set_signature_md(pkctx.get(), EVP_MD_CTX_md(mdctx.get())) && |
91 |
98 |
EVP_PKEY_sign(pkctx.get(), ptr, &sig_len, m, m_len)) { |
|
92 |
97 |
sig.Resize(sig_len); |
|
93 |
97 |
return sig; |
|
94 |
} |
||
95 |
|||
96 |
15 |
return AllocatedBuffer(); |
|
97 |
} |
||
98 |
|||
99 |
1404 |
int GetDefaultSignPadding(const ManagedEVPPKey& key) { |
|
100 |
✓✓ | 1404 |
return EVP_PKEY_id(key.get()) == EVP_PKEY_RSA_PSS ? RSA_PKCS1_PSS_PADDING : |
101 |
1404 |
RSA_PKCS1_PADDING; |
|
102 |
} |
||
103 |
|||
104 |
24 |
unsigned int GetBytesOfRS(const ManagedEVPPKey& pkey) { |
|
105 |
24 |
int bits, base_id = EVP_PKEY_base_id(pkey.get()); |
|
106 |
|||
107 |
✓✓ | 24 |
if (base_id == EVP_PKEY_DSA) { |
108 |
9 |
DSA* dsa_key = EVP_PKEY_get0_DSA(pkey.get()); |
|
109 |
// Both r and s are computed mod q, so their width is limited by that of q. |
||
110 |
9 |
bits = BN_num_bits(DSA_get0_q(dsa_key)); |
|
111 |
✓✓ | 15 |
} else if (base_id == EVP_PKEY_EC) { |
112 |
13 |
EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(pkey.get()); |
|
113 |
13 |
const EC_GROUP* ec_group = EC_KEY_get0_group(ec_key); |
|
114 |
13 |
bits = EC_GROUP_order_bits(ec_group); |
|
115 |
} else { |
||
116 |
2 |
return kNoDsaSignature; |
|
117 |
} |
||
118 |
|||
119 |
22 |
return (bits + 7) / 8; |
|
120 |
} |
||
121 |
|||
122 |
// Returns the maximum size of each of the integers (r, s) of the DSA signature. |
||
123 |
3 |
AllocatedBuffer ConvertSignatureToP1363(Environment* env, |
|
124 |
const ManagedEVPPKey& pkey, |
||
125 |
AllocatedBuffer&& signature) { |
||
126 |
3 |
unsigned int n = GetBytesOfRS(pkey); |
|
127 |
✓✓ | 3 |
if (n == kNoDsaSignature) |
128 |
1 |
return std::move(signature); |
|
129 |
|||
130 |
const unsigned char* sig_data = |
||
131 |
2 |
reinterpret_cast<unsigned char*>(signature.data()); |
|
132 |
|||
133 |
4 |
ECDSASigPointer asn1_sig(d2i_ECDSA_SIG(nullptr, &sig_data, signature.size())); |
|
134 |
✗✓ | 2 |
if (!asn1_sig) |
135 |
return AllocatedBuffer(); |
||
136 |
|||
137 |
4 |
AllocatedBuffer buf = AllocatedBuffer::AllocateManaged(env, 2 * n); |
|
138 |
2 |
unsigned char* data = reinterpret_cast<unsigned char*>(buf.data()); |
|
139 |
|||
140 |
2 |
const BIGNUM* r = ECDSA_SIG_get0_r(asn1_sig.get()); |
|
141 |
2 |
const BIGNUM* s = ECDSA_SIG_get0_s(asn1_sig.get()); |
|
142 |
✗✓ | 2 |
CHECK_EQ(n, static_cast<unsigned int>(BN_bn2binpad(r, data, n))); |
143 |
✗✓ | 2 |
CHECK_EQ(n, static_cast<unsigned int>(BN_bn2binpad(s, data + n, n))); |
144 |
|||
145 |
2 |
return buf; |
|
146 |
} |
||
147 |
|||
148 |
|||
149 |
21 |
ByteSource ConvertSignatureToDER( |
|
150 |
const ManagedEVPPKey& pkey, |
||
151 |
const ArrayBufferOrViewContents<char>& signature) { |
||
152 |
21 |
unsigned int n = GetBytesOfRS(pkey); |
|
153 |
✓✓ | 21 |
if (n == kNoDsaSignature) |
154 |
1 |
return signature.ToByteSource(); |
|
155 |
|||
156 |
const unsigned char* sig_data = |
||
157 |
20 |
reinterpret_cast<const unsigned char*>(signature.data()); |
|
158 |
|||
159 |
✓✓ | 20 |
if (signature.size() != 2 * n) |
160 |
12 |
return ByteSource(); |
|
161 |
|||
162 |
16 |
ECDSASigPointer asn1_sig(ECDSA_SIG_new()); |
|
163 |
✗✓ | 8 |
CHECK(asn1_sig); |
164 |
8 |
BIGNUM* r = BN_new(); |
|
165 |
✗✓ | 8 |
CHECK_NOT_NULL(r); |
166 |
8 |
BIGNUM* s = BN_new(); |
|
167 |
✗✓ | 8 |
CHECK_NOT_NULL(s); |
168 |
✗✓ | 8 |
CHECK_EQ(r, BN_bin2bn(sig_data, n, r)); |
169 |
✗✓ | 8 |
CHECK_EQ(s, BN_bin2bn(sig_data + n, n, s)); |
170 |
✗✓ | 8 |
CHECK_EQ(1, ECDSA_SIG_set0(asn1_sig.get(), r, s)); |
171 |
|||
172 |
8 |
unsigned char* data = nullptr; |
|
173 |
8 |
int len = i2d_ECDSA_SIG(asn1_sig.get(), &data); |
|
174 |
|||
175 |
✗✓ | 8 |
if (len <= 0) |
176 |
return ByteSource(); |
||
177 |
|||
178 |
✗✓ | 8 |
CHECK_NOT_NULL(data); |
179 |
|||
180 |
8 |
return ByteSource::Allocated(reinterpret_cast<char*>(data), len); |
|
181 |
} |
||
182 |
|||
183 |
1481 |
void CheckThrow(Environment* env, SignBase::Error error) { |
|
184 |
1481 |
HandleScope scope(env->isolate()); |
|
185 |
|||
186 |
✓✗✓✓ ✓✗ |
1481 |
switch (error) { |
187 |
case SignBase::Error::kSignUnknownDigest: |
||
188 |
2 |
return THROW_ERR_CRYPTO_INVALID_DIGEST(env); |
|
189 |
|||
190 |
case SignBase::Error::kSignNotInitialised: |
||
191 |
return THROW_ERR_CRYPTO_INVALID_STATE(env, "Not initialised"); |
||
192 |
|||
193 |
case SignBase::Error::kSignMalformedSignature: |
||
194 |
12 |
return THROW_ERR_CRYPTO_OPERATION_FAILED(env, "Malformed signature"); |
|
195 |
|||
196 |
case SignBase::Error::kSignInit: |
||
197 |
case SignBase::Error::kSignUpdate: |
||
198 |
case SignBase::Error::kSignPrivateKey: |
||
199 |
case SignBase::Error::kSignPublicKey: |
||
200 |
{ |
||
201 |
16 |
unsigned long err = ERR_get_error(); // NOLINT(runtime/int) |
|
202 |
✓✗ | 16 |
if (err) |
203 |
16 |
return ThrowCryptoError(env, err); |
|
204 |
switch (error) { |
||
205 |
case SignBase::Error::kSignInit: |
||
206 |
return THROW_ERR_CRYPTO_OPERATION_FAILED(env, |
||
207 |
"EVP_SignInit_ex failed"); |
||
208 |
case SignBase::Error::kSignUpdate: |
||
209 |
return THROW_ERR_CRYPTO_OPERATION_FAILED(env, |
||
210 |
"EVP_SignUpdate failed"); |
||
211 |
case SignBase::Error::kSignPrivateKey: |
||
212 |
return THROW_ERR_CRYPTO_OPERATION_FAILED(env, |
||
213 |
"PEM_read_bio_PrivateKey failed"); |
||
214 |
case SignBase::Error::kSignPublicKey: |
||
215 |
return THROW_ERR_CRYPTO_OPERATION_FAILED(env, |
||
216 |
"PEM_read_bio_PUBKEY failed"); |
||
217 |
default: |
||
218 |
ABORT(); |
||
219 |
} |
||
220 |
} |
||
221 |
|||
222 |
case SignBase::Error::kSignOk: |
||
223 |
✗✓ | 1451 |
return; |
224 |
} |
||
225 |
} |
||
226 |
} // namespace |
||
227 |
|||
228 |
728 |
SignBase::Error SignBase::Init(const char* sign_type) { |
|
229 |
✗✓ | 728 |
CHECK_NULL(mdctx_); |
230 |
// Historically, "dss1" and "DSS1" were DSA aliases for SHA-1 |
||
231 |
// exposed through the public API. |
||
232 |
✓✗✓✓ |
1456 |
if (strcmp(sign_type, "dss1") == 0 || |
233 |
728 |
strcmp(sign_type, "DSS1") == 0) { |
|
234 |
2 |
sign_type = "SHA1"; |
|
235 |
} |
||
236 |
728 |
const EVP_MD* md = EVP_get_digestbyname(sign_type); |
|
237 |
✓✓ | 728 |
if (md == nullptr) |
238 |
1 |
return kSignUnknownDigest; |
|
239 |
|||
240 |
727 |
mdctx_.reset(EVP_MD_CTX_new()); |
|
241 |
✓✗✗✓ ✗✓ |
727 |
if (!mdctx_ || !EVP_DigestInit_ex(mdctx_.get(), md, nullptr)) { |
242 |
mdctx_.reset(); |
||
243 |
return kSignInit; |
||
244 |
} |
||
245 |
|||
246 |
727 |
return kSignOk; |
|
247 |
} |
||
248 |
|||
249 |
724 |
SignBase::Error SignBase::Update(const char* data, size_t len) { |
|
250 |
✗✓ | 724 |
if (mdctx_ == nullptr) |
251 |
return kSignNotInitialised; |
||
252 |
✗✓ | 724 |
if (!EVP_DigestUpdate(mdctx_.get(), data, len)) |
253 |
return kSignUpdate; |
||
254 |
724 |
return kSignOk; |
|
255 |
} |
||
256 |
|||
257 |
728 |
SignBase::SignBase(Environment* env, Local<Object> wrap) |
|
258 |
728 |
: BaseObject(env, wrap) {} |
|
259 |
|||
260 |
void SignBase::MemoryInfo(MemoryTracker* tracker) const { |
||
261 |
tracker->TrackFieldWithSize("mdctx", mdctx_ ? kSizeOf_EVP_MD_CTX : 0); |
||
262 |
} |
||
263 |
|||
264 |
139 |
Sign::Sign(Environment* env, Local<Object> wrap) : SignBase(env, wrap) { |
|
265 |
139 |
MakeWeak(); |
|
266 |
139 |
} |
|
267 |
|||
268 |
654 |
void Sign::Initialize(Environment* env, Local<Object> target) { |
|
269 |
654 |
Local<FunctionTemplate> t = env->NewFunctionTemplate(New); |
|
270 |
|||
271 |
1962 |
t->InstanceTemplate()->SetInternalFieldCount( |
|
272 |
654 |
SignBase::kInternalFieldCount); |
|
273 |
1308 |
t->Inherit(BaseObject::GetConstructorTemplate(env)); |
|
274 |
|||
275 |
654 |
env->SetProtoMethod(t, "init", SignInit); |
|
276 |
654 |
env->SetProtoMethod(t, "update", SignUpdate); |
|
277 |
654 |
env->SetProtoMethod(t, "sign", SignFinal); |
|
278 |
|||
279 |
1308 |
target->Set(env->context(), |
|
280 |
FIXED_ONE_BYTE_STRING(env->isolate(), "Sign"), |
||
281 |
3924 |
t->GetFunction(env->context()).ToLocalChecked()).Check(); |
|
282 |
|||
283 |
654 |
env->SetMethod(target, "signOneShot", Sign::SignSync); |
|
284 |
|||
285 |
654 |
SignJob::Initialize(env, target); |
|
286 |
|||
287 |
654 |
constexpr int kSignJobModeSign = SignConfiguration::kSign; |
|
288 |
654 |
constexpr int kSignJobModeVerify = SignConfiguration::kVerify; |
|
289 |
|||
290 |
2616 |
NODE_DEFINE_CONSTANT(target, kSignJobModeSign); |
|
291 |
654 |
NODE_DEFINE_CONSTANT(target, kSignJobModeVerify); |
|
292 |
1962 |
NODE_DEFINE_CONSTANT(target, RSA_PKCS1_PSS_PADDING); |
|
293 |
3270 |
} |
|
294 |
4578 |
||
295 |
3409 |
void Sign::New(const FunctionCallbackInfo<Value>& args) { |
|
296 |
1447 |
Environment* env = Environment::GetCurrent(args); |
|
297 |
139 |
new Sign(env, args.This()); |
|
298 |
139 |
} |
|
299 |
|||
300 |
139 |
void Sign::SignInit(const FunctionCallbackInfo<Value>& args) { |
|
301 |
139 |
Environment* env = Environment::GetCurrent(args); |
|
302 |
Sign* sign; |
||
303 |
✗✓ | 139 |
ASSIGN_OR_RETURN_UNWRAP(&sign, args.Holder()); |
304 |
|||
305 |
278 |
const node::Utf8Value sign_type(args.GetIsolate(), args[0]); |
|
306 |
139 |
crypto::CheckThrow(env, sign->Init(*sign_type)); |
|
307 |
} |
||
308 |
|||
309 |
125 |
void Sign::SignUpdate(const FunctionCallbackInfo<Value>& args) { |
|
310 |
250 |
Decode<Sign>(args, [](Sign* sign, const FunctionCallbackInfo<Value>& args, |
|
311 |
375 |
const char* data, size_t size) { |
|
312 |
125 |
Environment* env = Environment::GetCurrent(args); |
|
313 |
✗✓ | 125 |
if (UNLIKELY(size > INT_MAX)) |
314 |
return THROW_ERR_OUT_OF_RANGE(env, "data is too long"); |
||
315 |
125 |
Error err = sign->Update(data, size); |
|
316 |
125 |
crypto::CheckThrow(sign->env(), err); |
|
317 |
375 |
}); |
|
318 |
125 |
} |
|
319 |
|||
320 |
112 |
Sign::SignResult Sign::SignFinal( |
|
321 |
const ManagedEVPPKey& pkey, |
||
322 |
int padding, |
||
323 |
const Maybe<int>& salt_len, |
||
324 |
DSASigEnc dsa_sig_enc) { |
||
325 |
✗✓ | 112 |
if (!mdctx_) |
326 |
return SignResult(kSignNotInitialised); |
||
327 |
|||
328 |
224 |
EVPMDPointer mdctx = std::move(mdctx_); |
|
329 |
|||
330 |
✗✓ | 112 |
if (!ValidateDSAParameters(pkey.get())) |
331 |
return SignResult(kSignPrivateKey); |
||
332 |
|||
333 |
AllocatedBuffer buffer = |
||
334 |
224 |
Node_SignFinal(env(), std::move(mdctx), pkey, padding, salt_len); |
|
335 |
✓✓ | 112 |
Error error = buffer.data() == nullptr ? kSignPrivateKey : kSignOk; |
336 |
✓✓✗✓ |
112 |
if (error == kSignOk && dsa_sig_enc == kSigEncP1363) { |
337 |
buffer = ConvertSignatureToP1363(env(), pkey, std::move(buffer)); |
||
338 |
CHECK_NOT_NULL(buffer.data()); |
||
339 |
} |
||
340 |
112 |
return SignResult(error, std::move(buffer)); |
|
341 |
} |
||
342 |
|||
343 |
116 |
void Sign::SignFinal(const FunctionCallbackInfo<Value>& args) { |
|
344 |
116 |
Environment* env = Environment::GetCurrent(args); |
|
345 |
Sign* sign; |
||
346 |
✗✓ | 135 |
ASSIGN_OR_RETURN_UNWRAP(&sign, args.Holder()); |
347 |
|||
348 |
97 |
ClearErrorOnReturn clear_error_on_return; |
|
349 |
|||
350 |
116 |
unsigned int offset = 0; |
|
351 |
✓✓ | 213 |
ManagedEVPPKey key = ManagedEVPPKey::GetPrivateKeyFromJs(args, &offset, true); |
352 |
✓✓ | 116 |
if (!key) |
353 |
4 |
return; |
|
354 |
|||
355 |
112 |
int padding = GetDefaultSignPadding(key); |
|
356 |
✓✓ | 448 |
if (!args[offset]->IsUndefined()) { |
357 |
✗✓ | 63 |
CHECK(args[offset]->IsInt32()); |
358 |
84 |
padding = args[offset].As<Int32>()->Value(); |
|
359 |
} |
||
360 |
|||
361 |
112 |
Maybe<int> salt_len = Nothing<int>(); |
|
362 |
✓✓ | 448 |
if (!args[offset + 1]->IsUndefined()) { |
363 |
✗✓ | 162 |
CHECK(args[offset + 1]->IsInt32()); |
364 |
216 |
salt_len = Just<int>(args[offset + 1].As<Int32>()->Value()); |
|
365 |
} |
||
366 |
|||
367 |
✗✓ | 336 |
CHECK(args[offset + 2]->IsInt32()); |
368 |
DSASigEnc dsa_sig_enc = |
||
369 |
448 |
static_cast<DSASigEnc>(args[offset + 2].As<Int32>()->Value()); |
|
370 |
|||
371 |
SignResult ret = sign->SignFinal( |
||
372 |
key, |
||
373 |
padding, |
||
374 |
salt_len, |
||
375 |
✓✓ | 209 |
dsa_sig_enc); |
376 |
|||
377 |
✓✓ | 112 |
if (ret.error != kSignOk) |
378 |
15 |
return crypto::CheckThrow(env, ret.error); |
|
379 |
|||
380 |
✓✓ | 291 |
args.GetReturnValue().Set(ret.signature.ToBuffer().FromMaybe(Local<Value>())); |
381 |
} |
||
382 |
|||
383 |
589 |
Verify::Verify(Environment* env, Local<Object> wrap) |
|
384 |
589 |
: SignBase(env, wrap) { |
|
385 |
589 |
MakeWeak(); |
|
386 |
589 |
} |
|
387 |
|||
388 |
654 |
void Verify::Initialize(Environment* env, Local<Object> target) { |
|
389 |
654 |
Local<FunctionTemplate> t = env->NewFunctionTemplate(New); |
|
390 |
|||
391 |
1962 |
t->InstanceTemplate()->SetInternalFieldCount( |
|
392 |
654 |
SignBase::kInternalFieldCount); |
|
393 |
1308 |
t->Inherit(BaseObject::GetConstructorTemplate(env)); |
|
394 |
|||
395 |
654 |
env->SetProtoMethod(t, "init", VerifyInit); |
|
396 |
654 |
env->SetProtoMethod(t, "update", VerifyUpdate); |
|
397 |
654 |
env->SetProtoMethod(t, "verify", VerifyFinal); |
|
398 |
|||
399 |
1308 |
target->Set(env->context(), |
|
400 |
FIXED_ONE_BYTE_STRING(env->isolate(), "Verify"), |
||
401 |
3924 |
t->GetFunction(env->context()).ToLocalChecked()).Check(); |
|
402 |
|||
403 |
654 |
env->SetMethod(target, "verifyOneShot", Verify::VerifySync); |
|
404 |
654 |
} |
|
405 |
|||
406 |
589 |
void Verify::New(const FunctionCallbackInfo<Value>& args) { |
|
407 |
589 |
Environment* env = Environment::GetCurrent(args); |
|
408 |
589 |
new Verify(env, args.This()); |
|
409 |
589 |
} |
|
410 |
|||
411 |
589 |
void Verify::VerifyInit(const FunctionCallbackInfo<Value>& args) { |
|
412 |
589 |
Environment* env = Environment::GetCurrent(args); |
|
413 |
Verify* verify; |
||
414 |
✗✓ | 589 |
ASSIGN_OR_RETURN_UNWRAP(&verify, args.Holder()); |
415 |
|||
416 |
1178 |
const node::Utf8Value verify_type(args.GetIsolate(), args[0]); |
|
417 |
589 |
crypto::CheckThrow(env, verify->Init(*verify_type)); |
|
418 |
} |
||
419 |
|||
420 |
599 |
void Verify::VerifyUpdate(const FunctionCallbackInfo<Value>& args) { |
|
421 |
1198 |
Decode<Verify>(args, [](Verify* verify, |
|
422 |
const FunctionCallbackInfo<Value>& args, |
||
423 |
1797 |
const char* data, size_t size) { |
|
424 |
599 |
Environment* env = Environment::GetCurrent(args); |
|
425 |
✗✓ | 599 |
if (UNLIKELY(size > INT_MAX)) |
426 |
return THROW_ERR_OUT_OF_RANGE(env, "data is too long"); |
||
427 |
599 |
Error err = verify->Update(data, size); |
|
428 |
599 |
crypto::CheckThrow(verify->env(), err); |
|
429 |
1797 |
}); |
|
430 |
599 |
} |
|
431 |
|||
432 |
582 |
SignBase::Error Verify::VerifyFinal(const ManagedEVPPKey& pkey, |
|
433 |
const ByteSource& sig, |
||
434 |
int padding, |
||
435 |
const Maybe<int>& saltlen, |
||
436 |
bool* verify_result) { |
||
437 |
✗✓ | 582 |
if (!mdctx_) |
438 |
return kSignNotInitialised; |
||
439 |
|||
440 |
unsigned char m[EVP_MAX_MD_SIZE]; |
||
441 |
unsigned int m_len; |
||
442 |
582 |
*verify_result = false; |
|
443 |
1164 |
EVPMDPointer mdctx = std::move(mdctx_); |
|
444 |
|||
445 |
✗✓ | 582 |
if (!EVP_DigestFinal_ex(mdctx.get(), m, &m_len)) |
446 |
return kSignPublicKey; |
||
447 |
|||
448 |
1164 |
EVPKeyCtxPointer pkctx(EVP_PKEY_CTX_new(pkey.get(), nullptr)); |
|
449 |
✓✗✓✗ |
1164 |
if (pkctx && |
450 |
✓✗ | 1746 |
EVP_PKEY_verify_init(pkctx.get()) > 0 && |
451 |
✓✗✓✗ |
1746 |
ApplyRSAOptions(pkey, pkctx.get(), padding, saltlen) && |
452 |
582 |
EVP_PKEY_CTX_set_signature_md(pkctx.get(), |
|
453 |
EVP_MD_CTX_md(mdctx.get())) > 0) { |
||
454 |
582 |
const unsigned char* s = reinterpret_cast<const unsigned char*>(sig.get()); |
|
455 |
582 |
const int r = EVP_PKEY_verify(pkctx.get(), s, sig.size(), m, m_len); |
|
456 |
582 |
*verify_result = r == 1; |
|
457 |
} |
||
458 |
|||
459 |
582 |
return kSignOk; |
|
460 |
} |
||
461 |
|||
462 |
582 |
void Verify::VerifyFinal(const FunctionCallbackInfo<Value>& args) { |
|
463 |
582 |
Environment* env = Environment::GetCurrent(args); |
|
464 |
582 |
ClearErrorOnReturn clear_error_on_return; |
|
465 |
|||
466 |
Verify* verify; |
||
467 |
✗✓ | 582 |
ASSIGN_OR_RETURN_UNWRAP(&verify, args.Holder()); |
468 |
|||
469 |
582 |
unsigned int offset = 0; |
|
470 |
ManagedEVPPKey pkey = |
||
471 |
✓✗ | 1164 |
ManagedEVPPKey::GetPublicOrPrivateKeyFromJs(args, &offset); |
472 |
✗✓ | 582 |
if (!pkey) |
473 |
return; |
||
474 |
|||
475 |
✓✗ | 1746 |
ArrayBufferOrViewContents<char> hbuf(args[offset]); |
476 |
✗✓ | 582 |
if (UNLIKELY(!hbuf.CheckSizeInt32())) |
477 |
return THROW_ERR_OUT_OF_RANGE(env, "buffer is too big"); |
||
478 |
|||
479 |
582 |
int padding = GetDefaultSignPadding(pkey); |
|
480 |
✓✓ | 2328 |
if (!args[offset + 1]->IsUndefined()) { |
481 |
✗✓ | 1116 |
CHECK(args[offset + 1]->IsInt32()); |
482 |
1488 |
padding = args[offset + 1].As<Int32>()->Value(); |
|
483 |
} |
||
484 |
|||
485 |
582 |
Maybe<int> salt_len = Nothing<int>(); |
|
486 |
✓✓ | 2328 |
if (!args[offset + 2]->IsUndefined()) { |
487 |
✗✓ | 1386 |
CHECK(args[offset + 2]->IsInt32()); |
488 |
1848 |
salt_len = Just<int>(args[offset + 2].As<Int32>()->Value()); |
|
489 |
} |
||
490 |
|||
491 |
✗✓ | 1746 |
CHECK(args[offset + 3]->IsInt32()); |
492 |
DSASigEnc dsa_sig_enc = |
||
493 |
2328 |
static_cast<DSASigEnc>(args[offset + 3].As<Int32>()->Value()); |
|
494 |
|||
495 |
✓✗ | 1164 |
ByteSource signature = hbuf.ToByteSource(); |
496 |
✓✓ | 582 |
if (dsa_sig_enc == kSigEncP1363) { |
497 |
4 |
signature = ConvertSignatureToDER(pkey, hbuf); |
|
498 |
✗✓ | 4 |
if (signature.get() == nullptr) |
499 |
return crypto::CheckThrow(env, Error::kSignMalformedSignature); |
||
500 |
} |
||
501 |
|||
502 |
bool verify_result; |
||
503 |
582 |
Error err = verify->VerifyFinal(pkey, signature, padding, |
|
504 |
582 |
salt_len, &verify_result); |
|
505 |
✗✓ | 582 |
if (err != kSignOk) |
506 |
return crypto::CheckThrow(env, err); |
||
507 |
✓✗ | 1746 |
args.GetReturnValue().Set(verify_result); |
508 |
} |
||
509 |
|||
510 |
77 |
void Sign::SignSync(const FunctionCallbackInfo<Value>& args) { |
|
511 |
66 |
ClearErrorOnReturn clear_error_on_return; |
|
512 |
77 |
Environment* env = Environment::GetCurrent(args); |
|
513 |
|||
514 |
77 |
unsigned int offset = 0; |
|
515 |
✓✓ | 143 |
ManagedEVPPKey key = ManagedEVPPKey::GetPrivateKeyFromJs(args, &offset, true); |
516 |
✓✓ | 77 |
if (!key) |
517 |
9 |
return; |
|
518 |
|||
519 |
✗✓ | 68 |
if (!ValidateDSAParameters(key.get())) |
520 |
return crypto::CheckThrow(env, SignBase::Error::kSignPrivateKey); |
||
521 |
|||
522 |
✓✓ | 202 |
ArrayBufferOrViewContents<char> data(args[offset]); |
523 |
✗✓ | 68 |
if (UNLIKELY(!data.CheckSizeInt32())) |
524 |
return THROW_ERR_OUT_OF_RANGE(env, "data is too big"); |
||
525 |
|||
526 |
const EVP_MD* md; |
||
527 |
✓✓ | 272 |
if (args[offset + 1]->IsNullOrUndefined()) { |
528 |
16 |
md = nullptr; |
|
529 |
} else { |
||
530 |
155 |
const node::Utf8Value sign_type(args.GetIsolate(), args[offset + 1]); |
|
531 |
52 |
md = EVP_get_digestbyname(*sign_type); |
|
532 |
✓✓ | 52 |
if (md == nullptr) |
533 |
✓✓ | 1 |
return crypto::CheckThrow(env, SignBase::Error::kSignUnknownDigest); |
534 |
} |
||
535 |
|||
536 |
67 |
int rsa_padding = GetDefaultSignPadding(key); |
|
537 |
✓✓ | 268 |
if (!args[offset + 2]->IsUndefined()) { |
538 |
✗✓ | 57 |
CHECK(args[offset + 2]->IsInt32()); |
539 |
76 |
rsa_padding = args[offset + 2].As<Int32>()->Value(); |
|
540 |
} |
||
541 |
|||
542 |
67 |
Maybe<int> rsa_salt_len = Nothing<int>(); |
|
543 |
✓✓ | 268 |
if (!args[offset + 3]->IsUndefined()) { |
544 |
✗✓ | 54 |
CHECK(args[offset + 3]->IsInt32()); |
545 |
72 |
rsa_salt_len = Just<int>(args[offset + 3].As<Int32>()->Value()); |
|
546 |
} |
||
547 |
|||
548 |
✗✓ | 201 |
CHECK(args[offset + 4]->IsInt32()); |
549 |
DSASigEnc dsa_sig_enc = |
||
550 |
268 |
static_cast<DSASigEnc>(args[offset + 4].As<Int32>()->Value()); |
|
551 |
|||
552 |
67 |
EVP_PKEY_CTX* pkctx = nullptr; |
|
553 |
✓✓ | 133 |
EVPMDPointer mdctx(EVP_MD_CTX_new()); |
554 |
|||
555 |
✓✗✗✓ ✗✓ |
134 |
if (!mdctx || |
556 |
67 |
!EVP_DigestSignInit(mdctx.get(), &pkctx, md, nullptr, key.get())) { |
|
557 |
return crypto::CheckThrow(env, SignBase::Error::kSignInit); |
||
558 |
} |
||
559 |
|||
560 |
✓✓ | 67 |
if (!ApplyRSAOptions(key, pkctx, rsa_padding, rsa_salt_len)) |
561 |
1 |
return crypto::CheckThrow(env, SignBase::Error::kSignPrivateKey); |
|
562 |
|||
563 |
const unsigned char* input = |
||
564 |
66 |
reinterpret_cast<const unsigned char*>(data.data()); |
|
565 |
size_t sig_len; |
||
566 |
✗✓ | 66 |
if (!EVP_DigestSign(mdctx.get(), nullptr, &sig_len, input, data.size())) |
567 |
return crypto::CheckThrow(env, SignBase::Error::kSignPrivateKey); |
||
568 |
|||
569 |
✓✓ | 132 |
AllocatedBuffer signature = AllocatedBuffer::AllocateManaged(env, sig_len); |
570 |
✗✓ | 132 |
if (!EVP_DigestSign(mdctx.get(), |
571 |
66 |
reinterpret_cast<unsigned char*>(signature.data()), |
|
572 |
&sig_len, |
||
573 |
input, |
||
574 |
data.size())) { |
||
575 |
return crypto::CheckThrow(env, SignBase::Error::kSignPrivateKey); |
||
576 |
} |
||
577 |
|||
578 |
66 |
signature.Resize(sig_len); |
|
579 |
|||
580 |
✓✓ | 66 |
if (dsa_sig_enc == kSigEncP1363) { |
581 |
3 |
signature = ConvertSignatureToP1363(env, key, std::move(signature)); |
|
582 |
} |
||
583 |
|||
584 |
✓✗ | 198 |
args.GetReturnValue().Set(signature.ToBuffer().FromMaybe(Local<Value>())); |
585 |
} |
||
586 |
|||
587 |
479 |
void Verify::VerifySync(const FunctionCallbackInfo<Value>& args) { |
|
588 |
467 |
ClearErrorOnReturn clear_error_on_return; |
|
589 |
479 |
Environment* env = Environment::GetCurrent(args); |
|
590 |
|||
591 |
479 |
unsigned int offset = 0; |
|
592 |
ManagedEVPPKey key = |
||
593 |
✓✓ | 946 |
ManagedEVPPKey::GetPublicOrPrivateKeyFromJs(args, &offset); |
594 |
✗✓ | 479 |
if (!key) |
595 |
return; |
||
596 |
|||
597 |
✓✓ | 1425 |
ArrayBufferOrViewContents<char> sig(args[offset]); |
598 |
✓✓ | 1425 |
ArrayBufferOrViewContents<char> data(args[offset + 1]); |
599 |
|||
600 |
✗✓ | 479 |
if (UNLIKELY(!sig.CheckSizeInt32())) |
601 |
return THROW_ERR_OUT_OF_RANGE(env, "sig is too big"); |
||
602 |
✗✓ | 479 |
if (UNLIKELY(!data.CheckSizeInt32())) |
603 |
return THROW_ERR_OUT_OF_RANGE(env, "data is too big"); |
||
604 |
|||
605 |
const EVP_MD* md; |
||
606 |
✓✓ | 1916 |
if (args[offset + 2]->IsNullOrUndefined()) { |
607 |
20 |
md = nullptr; |
|
608 |
} else { |
||
609 |
1377 |
const node::Utf8Value sign_type(args.GetIsolate(), args[offset + 2]); |
|
610 |
459 |
md = EVP_get_digestbyname(*sign_type); |
|
611 |
✗✓ | 459 |
if (md == nullptr) |
612 |
return crypto::CheckThrow(env, SignBase::Error::kSignUnknownDigest); |
||
613 |
} |
||
614 |
|||
615 |
479 |
int rsa_padding = GetDefaultSignPadding(key); |
|
616 |
✓✓ | 1916 |
if (!args[offset + 3]->IsUndefined()) { |
617 |
✗✓ | 1080 |
CHECK(args[offset + 3]->IsInt32()); |
618 |
1440 |
rsa_padding = args[offset + 3].As<Int32>()->Value(); |
|
619 |
} |
||
620 |
|||
621 |
479 |
Maybe<int> rsa_salt_len = Nothing<int>(); |
|
622 |
✓✓ | 1916 |
if (!args[offset + 4]->IsUndefined()) { |
623 |
✗✓ | 1080 |
CHECK(args[offset + 4]->IsInt32()); |
624 |
1440 |
rsa_salt_len = Just<int>(args[offset + 4].As<Int32>()->Value()); |
|
625 |
} |
||
626 |
|||
627 |
✗✓ | 1437 |
CHECK(args[offset + 5]->IsInt32()); |
628 |
DSASigEnc dsa_sig_enc = |
||
629 |
1916 |
static_cast<DSASigEnc>(args[offset + 5].As<Int32>()->Value()); |
|
630 |
|||
631 |
479 |
EVP_PKEY_CTX* pkctx = nullptr; |
|
632 |
✓✓ | 946 |
EVPMDPointer mdctx(EVP_MD_CTX_new()); |
633 |
✓✗✗✓ ✗✓ |
958 |
if (!mdctx || |
634 |
479 |
!EVP_DigestVerifyInit(mdctx.get(), &pkctx, md, nullptr, key.get())) { |
|
635 |
return crypto::CheckThrow(env, SignBase::Error::kSignInit); |
||
636 |
} |
||
637 |
|||
638 |
✗✓ | 479 |
if (!ApplyRSAOptions(key, pkctx, rsa_padding, rsa_salt_len)) |
639 |
return crypto::CheckThrow(env, SignBase::Error::kSignPublicKey); |
||
640 |
|||
641 |
✓✓ | 946 |
ByteSource sig_bytes = ByteSource::Foreign(sig.data(), sig.size()); |
642 |
✓✓ | 479 |
if (dsa_sig_enc == kSigEncP1363) { |
643 |
17 |
sig_bytes = ConvertSignatureToDER(key, sig); |
|
644 |
✓✓ | 17 |
if (!sig_bytes) |
645 |
12 |
return crypto::CheckThrow(env, SignBase::Error::kSignMalformedSignature); |
|
646 |
} |
||
647 |
|||
648 |
bool verify_result; |
||
649 |
934 |
const int r = EVP_DigestVerify( |
|
650 |
mdctx.get(), |
||
651 |
sig_bytes.data<unsigned char>(), |
||
652 |
sig_bytes.size(), |
||
653 |
467 |
reinterpret_cast<const unsigned char*>(data.data()), |
|
654 |
467 |
data.size()); |
|
655 |
✓✓✗ | 467 |
switch (r) { |
656 |
case 1: |
||
657 |
191 |
verify_result = true; |
|
658 |
191 |
break; |
|
659 |
case 0: |
||
660 |
276 |
verify_result = false; |
|
661 |
276 |
break; |
|
662 |
default: |
||
663 |
return crypto::CheckThrow(env, SignBase::Error::kSignPublicKey); |
||
664 |
} |
||
665 |
|||
666 |
✓✓ | 1401 |
args.GetReturnValue().Set(verify_result); |
667 |
} |
||
668 |
|||
669 |
246 |
SignConfiguration::SignConfiguration(SignConfiguration&& other) noexcept |
|
670 |
246 |
: job_mode(other.job_mode), |
|
671 |
246 |
mode(other.mode), |
|
672 |
246 |
key(std::move(other.key)), |
|
673 |
246 |
data(std::move(other.data)), |
|
674 |
246 |
signature(std::move(other.signature)), |
|
675 |
246 |
digest(other.digest), |
|
676 |
246 |
flags(other.flags), |
|
677 |
246 |
padding(other.padding), |
|
678 |
2214 |
salt_length(other.salt_length) {} |
|
679 |
|||
680 |
SignConfiguration& SignConfiguration::operator=( |
||
681 |
SignConfiguration&& other) noexcept { |
||
682 |
if (&other == this) return *this; |
||
683 |
this->~SignConfiguration(); |
||
684 |
return *new (this) SignConfiguration(std::move(other)); |
||
685 |
} |
||
686 |
|||
687 |
void SignConfiguration::MemoryInfo(MemoryTracker* tracker) const { |
||
688 |
tracker->TrackField("key", key.get()); |
||
689 |
if (job_mode == kCryptoJobAsync) { |
||
690 |
tracker->TrackFieldWithSize("data", data.size()); |
||
691 |
tracker->TrackFieldWithSize("signature", signature.size()); |
||
692 |
} |
||
693 |
} |
||
694 |
|||
695 |
246 |
Maybe<bool> SignTraits::AdditionalConfig( |
|
696 |
CryptoJobMode mode, |
||
697 |
const FunctionCallbackInfo<Value>& args, |
||
698 |
unsigned int offset, |
||
699 |
SignConfiguration* params) { |
||
700 |
246 |
Environment* env = Environment::GetCurrent(args); |
|
701 |
|||
702 |
246 |
params->job_mode = mode; |
|
703 |
|||
704 |
✗✓ | 738 |
CHECK(args[offset]->IsUint32()); // Sign Mode |
705 |
✗✓ | 738 |
CHECK(args[offset + 1]->IsObject()); // Key |
706 |
|||
707 |
246 |
params->mode = |
|
708 |
1230 |
static_cast<SignConfiguration::Mode>(args[offset].As<Uint32>()->Value()); |
|
709 |
|||
710 |
KeyObjectHandle* key; |
||
711 |
✗✓ | 492 |
ASSIGN_OR_RETURN_UNWRAP(&key, args[offset + 1], Nothing<bool>()); |
712 |
246 |
params->key = key->Data(); |
|
713 |
|||
714 |
738 |
ArrayBufferOrViewContents<char> data(args[offset + 2]); |
|
715 |
✗✓ | 246 |
if (UNLIKELY(!data.CheckSizeInt32())) { |
716 |
THROW_ERR_OUT_OF_RANGE(env, "data is too big"); |
||
717 |
return Nothing<bool>(); |
||
718 |
} |
||
719 |
params->data = mode == kCryptoJobAsync |
||
720 |
✓✗ | 492 |
? data.ToCopy() |
721 |
246 |
: data.ToByteSource(); |
|
722 |
|||
723 |
✓✗ | 984 |
if (args[offset + 3]->IsString()) { |
724 |
738 |
Utf8Value digest(env->isolate(), args[offset + 3]); |
|
725 |
246 |
params->digest = EVP_get_digestbyname(*digest); |
|
726 |
✗✓ | 246 |
if (params->digest == nullptr) { |
727 |
THROW_ERR_CRYPTO_INVALID_DIGEST(env); |
||
728 |
return Nothing<bool>(); |
||
729 |
} |
||
730 |
} |
||
731 |
|||
732 |
✓✓ | 738 |
if (args[offset + 4]->IsUint32()) { // Salt length |
733 |
82 |
params->flags |= SignConfiguration::kHasSaltLength; |
|
734 |
328 |
params->salt_length = args[offset + 4].As<Uint32>()->Value(); |
|
735 |
} |
||
736 |
✓✓ | 738 |
if (args[offset + 5]->IsUint32()) { // Padding |
737 |
82 |
params->flags |= SignConfiguration::kHasPadding; |
|
738 |
328 |
params->padding = args[offset + 5].As<Uint32>()->Value(); |
|
739 |
} |
||
740 |
|||
741 |
✓✓ | 246 |
if (params->mode == SignConfiguration::kVerify) { |
742 |
585 |
ArrayBufferOrViewContents<char> signature(args[offset + 6]); |
|
743 |
✗✓ | 195 |
if (UNLIKELY(!signature.CheckSizeInt32())) { |
744 |
THROW_ERR_OUT_OF_RANGE(env, "signature is too big"); |
||
745 |
return Nothing<bool>(); |
||
746 |
} |
||
747 |
// If this is an EC key (assuming ECDSA) we need to convert the |
||
748 |
// the signature from WebCrypto format into DER format... |
||
749 |
✓✓ | 195 |
if (EVP_PKEY_id(params->key->GetAsymmetricKey().get()) == EVP_PKEY_EC) { |
750 |
params->signature = |
||
751 |
130 |
ConvertFromWebCryptoSignature( |
|
752 |
130 |
params->key->GetAsymmetricKey(), |
|
753 |
195 |
signature.ToByteSource()); |
|
754 |
} else { |
||
755 |
params->signature = mode == kCryptoJobAsync |
||
756 |
✓✗✓✗ |
260 |
? signature.ToCopy() |
757 |
130 |
: signature.ToByteSource(); |
|
758 |
} |
||
759 |
} |
||
760 |
|||
761 |
246 |
return Just(true); |
|
762 |
} |
||
763 |
|||
764 |
246 |
bool SignTraits::DeriveBits( |
|
765 |
Environment* env, |
||
766 |
const SignConfiguration& params, |
||
767 |
ByteSource* out) { |
||
768 |
492 |
EVPMDPointer context(EVP_MD_CTX_new()); |
|
769 |
246 |
EVP_PKEY_CTX* ctx = nullptr; |
|
770 |
|||
771 |
✓✓✗ | 246 |
switch (params.mode) { |
772 |
case SignConfiguration::kSign: |
||
773 |
✗✓ | 51 |
CHECK_EQ(params.key->GetKeyType(), kKeyTypePrivate); |
774 |
✗✓ | 153 |
if (!EVP_DigestSignInit( |
775 |
context.get(), |
||
776 |
&ctx, |
||
777 |
51 |
params.digest, |
|
778 |
nullptr, |
||
779 |
102 |
params.key->GetAsymmetricKey().get())) { |
|
780 |
return false; |
||
781 |
} |
||
782 |
51 |
break; |
|
783 |
case SignConfiguration::kVerify: |
||
784 |
✗✓ | 195 |
CHECK_EQ(params.key->GetKeyType(), kKeyTypePublic); |
785 |
✗✓ | 585 |
if (!EVP_DigestVerifyInit( |
786 |
context.get(), |
||
787 |
&ctx, |
||
788 |
195 |
params.digest, |
|
789 |
nullptr, |
||
790 |
390 |
params.key->GetAsymmetricKey().get())) { |
|
791 |
return false; |
||
792 |
} |
||
793 |
195 |
break; |
|
794 |
} |
||
795 |
|||
796 |
246 |
int padding = params.flags & SignConfiguration::kHasPadding |
|
797 |
✓✓ | 410 |
? params.padding |
798 |
✓✓ | 410 |
: GetDefaultSignPadding(params.key->GetAsymmetricKey()); |
799 |
|||
800 |
246 |
Maybe<int> salt_length = params.flags & SignConfiguration::kHasSaltLength |
|
801 |
✓✓ | 246 |
? Just<int>(params.salt_length) : Nothing<int>(); |
802 |
|||
803 |
✗✓ | 738 |
if (!ApplyRSAOptions( |
804 |
492 |
params.key->GetAsymmetricKey(), |
|
805 |
ctx, |
||
806 |
padding, |
||
807 |
salt_length)) { |
||
808 |
return false; |
||
809 |
} |
||
810 |
|||
811 |
✓✓✗ | 246 |
switch (params.mode) { |
812 |
case SignConfiguration::kSign: { |
||
813 |
size_t len; |
||
814 |
✗✓ | 102 |
if (!EVP_DigestSignUpdate( |
815 |
context.get(), |
||
816 |
params.data.data<unsigned char>(), |
||
817 |
✓✗✗✓ |
102 |
params.data.size()) || |
818 |
51 |
!EVP_DigestSignFinal(context.get(), nullptr, &len)) { |
|
819 |
return false; |
||
820 |
} |
||
821 |
51 |
char* data = MallocOpenSSL<char>(len); |
|
822 |
51 |
ByteSource buf = ByteSource::Allocated(data, len); |
|
823 |
51 |
unsigned char* ptr = reinterpret_cast<unsigned char*>(data); |
|
824 |
✗✓ | 51 |
if (!EVP_DigestSignFinal(context.get(), ptr, &len)) |
825 |
return false; |
||
826 |
|||
827 |
// If this is an EC key (assuming ECDSA) we have to |
||
828 |
// convert the signature in to the proper format. |
||
829 |
✓✓ | 51 |
if (EVP_PKEY_id(params.key->GetAsymmetricKey().get()) == EVP_PKEY_EC) { |
830 |
17 |
*out = ConvertToWebCryptoSignature(params.key->GetAsymmetricKey(), buf); |
|
831 |
} else { |
||
832 |
34 |
buf.Resize(len); |
|
833 |
34 |
*out = std::move(buf); |
|
834 |
} |
||
835 |
✗✓ | 51 |
break; |
836 |
} |
||
837 |
case SignConfiguration::kVerify: { |
||
838 |
195 |
char* data = MallocOpenSSL<char>(1); |
|
839 |
195 |
data[0] = 0; |
|
840 |
195 |
*out = ByteSource::Allocated(data, 1); |
|
841 |
✗✓ | 195 |
if (!EVP_DigestVerifyUpdate( |
842 |
context.get(), |
||
843 |
params.data.data<unsigned char>(), |
||
844 |
params.data.size())) { |
||
845 |
return false; |
||
846 |
} |
||
847 |
|||
848 |
✓✓ | 195 |
if (EVP_DigestVerifyFinal( |
849 |
context.get(), |
||
850 |
params.signature.data<unsigned char>(), |
||
851 |
params.signature.size()) == 1) { |
||
852 |
99 |
data[0] = 1; |
|
853 |
} |
||
854 |
} |
||
855 |
} |
||
856 |
|||
857 |
246 |
return true; |
|
858 |
} |
||
859 |
|||
860 |
246 |
Maybe<bool> SignTraits::EncodeOutput( |
|
861 |
Environment* env, |
||
862 |
const SignConfiguration& params, |
||
863 |
ByteSource* out, |
||
864 |
Local<Value>* result) { |
||
865 |
✓✓✗ | 246 |
switch (params.mode) { |
866 |
case SignConfiguration::kSign: |
||
867 |
102 |
*result = out->ToArrayBuffer(env); |
|
868 |
51 |
break; |
|
869 |
case SignConfiguration::kVerify: |
||
870 |
390 |
*result = out->get()[0] == 1 |
|
871 |
99 |
? v8::True(env->isolate()) |
|
872 |
✓✓ | 486 |
: v8::False(env->isolate()); |
873 |
195 |
break; |
|
874 |
default: |
||
875 |
UNREACHABLE(); |
||
876 |
} |
||
877 |
246 |
return Just(!result->IsEmpty()); |
|
878 |
} |
||
879 |
|||
880 |
} // namespace crypto |
||
881 |
✓✗✓✗ |
14034 |
} // namespace node |
Generated by: GCOVR (Version 3.4) |