1 #include "crypto/crypto_timing.h"
2 #include "crypto/crypto_util.h"
3 #include "env-inl.h"
4 #include "node_errors.h"
5 #include "v8.h"
6 #include "node.h"
7
8 #include <openssl/crypto.h>
9
10 namespace node {
11
12 using v8::FunctionCallbackInfo;
13 using v8::Local;
14 using v8::Object;
15 using v8::Value;
16
17 namespace crypto {
18 namespace Timing {
TimingSafeEqual(const FunctionCallbackInfo<Value> & args)19 void TimingSafeEqual(const FunctionCallbackInfo<Value>& args) {
20 // Moving the type checking into JS leads to test failures, most likely due
21 // to V8 inlining certain parts of the wrapper. Therefore, keep them in C++.
22 // Refs: https://github.com/nodejs/node/issues/34073.
23 Environment* env = Environment::GetCurrent(args);
24 if (!IsAnyByteSource(args[0])) {
25 THROW_ERR_INVALID_ARG_TYPE(
26 env, "The \"buf1\" argument must be an instance of "
27 "ArrayBuffer, Buffer, TypedArray, or DataView.");
28 return;
29 }
30 if (!IsAnyByteSource(args[1])) {
31 THROW_ERR_INVALID_ARG_TYPE(
32 env, "The \"buf2\" argument must be an instance of "
33 "ArrayBuffer, Buffer, TypedArray, or DataView.");
34 return;
35 }
36
37 ArrayBufferOrViewContents<char> buf1(args[0]);
38 ArrayBufferOrViewContents<char> buf2(args[1]);
39
40 if (buf1.size() != buf2.size()) {
41 THROW_ERR_CRYPTO_TIMING_SAFE_EQUAL_LENGTH(env);
42 return;
43 }
44
45 return args.GetReturnValue().Set(
46 CRYPTO_memcmp(buf1.data(), buf2.data(), buf1.size()) == 0);
47 }
48
Initialize(Environment * env,Local<Object> target)49 void Initialize(Environment* env, Local<Object> target) {
50 SetMethodNoSideEffect(
51 env->context(), target, "timingSafeEqual", TimingSafeEqual);
52 }
RegisterExternalReferences(ExternalReferenceRegistry * registry)53 void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
54 registry->Register(TimingSafeEqual);
55 }
56 } // namespace Timing
57
58 } // namespace crypto
59 } // namespace node
60