• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "crypto/crypto_util.h"
2 #include "async_wrap-inl.h"
3 #include "crypto/crypto_bio.h"
4 #include "crypto/crypto_keys.h"
5 #include "env-inl.h"
6 #include "memory_tracker-inl.h"
7 #include "node_buffer.h"
8 #include "node_options-inl.h"
9 #include "string_bytes.h"
10 #include "threadpoolwork-inl.h"
11 #include "util-inl.h"
12 #include "v8.h"
13 
14 #include "math.h"
15 
16 #if OPENSSL_VERSION_MAJOR >= 3
17 #include "openssl/provider.h"
18 #endif
19 
20 #include <openssl/rand.h>
21 
22 namespace node {
23 
24 using v8::ArrayBuffer;
25 using v8::BackingStore;
26 using v8::BigInt;
27 using v8::Context;
28 using v8::Exception;
29 using v8::FunctionCallbackInfo;
30 using v8::HandleScope;
31 using v8::Isolate;
32 using v8::Just;
33 using v8::Local;
34 using v8::Maybe;
35 using v8::MaybeLocal;
36 using v8::NewStringType;
37 using v8::Nothing;
38 using v8::Object;
39 using v8::String;
40 using v8::TryCatch;
41 using v8::Uint32;
42 using v8::Uint8Array;
43 using v8::Value;
44 
45 namespace crypto {
VerifyCallback(int preverify_ok,X509_STORE_CTX * ctx)46 int VerifyCallback(int preverify_ok, X509_STORE_CTX* ctx) {
47   // From https://www.openssl.org/docs/man1.1.1/man3/SSL_verify_cb:
48   //
49   //   If VerifyCallback returns 1, the verification process is continued. If
50   //   VerifyCallback always returns 1, the TLS/SSL handshake will not be
51   //   terminated with respect to verification failures and the connection will
52   //   be established. The calling process can however retrieve the error code
53   //   of the last verification error using SSL_get_verify_result(3) or by
54   //   maintaining its own error storage managed by VerifyCallback.
55   //
56   // Since we cannot perform I/O quickly enough with X509_STORE_CTX_ APIs in
57   // this callback, we ignore all preverify_ok errors and let the handshake
58   // continue. It is imperative that the user use Connection::VerifyError after
59   // the 'secure' callback has been made.
60   return 1;
61 }
62 
CSPRNG(void * buffer,size_t length)63 MUST_USE_RESULT CSPRNGResult CSPRNG(void* buffer, size_t length) {
64   unsigned char* buf = static_cast<unsigned char*>(buffer);
65   do {
66     if (1 == RAND_status()) {
67 #if OPENSSL_VERSION_MAJOR >= 3
68       if (1 == RAND_bytes_ex(nullptr, buf, length, 0)) return {true};
69 #else
70       while (length > INT_MAX && 1 == RAND_bytes(buf, INT_MAX)) {
71         buf += INT_MAX;
72         length -= INT_MAX;
73       }
74       if (length <= INT_MAX && 1 == RAND_bytes(buf, static_cast<int>(length)))
75         return {true};
76 #endif
77     }
78 #if OPENSSL_VERSION_MAJOR >= 3
79     const auto code = ERR_peek_last_error();
80     // A misconfigured OpenSSL 3 installation may report 1 from RAND_poll()
81     // and RAND_status() but fail in RAND_bytes() if it cannot look up
82     // a matching algorithm for the CSPRNG.
83     if (ERR_GET_LIB(code) == ERR_LIB_RAND) {
84       const auto reason = ERR_GET_REASON(code);
85       if (reason == RAND_R_ERROR_INSTANTIATING_DRBG ||
86           reason == RAND_R_UNABLE_TO_FETCH_DRBG ||
87           reason == RAND_R_UNABLE_TO_CREATE_DRBG) {
88         return {false};
89       }
90     }
91 #endif
92   } while (1 == RAND_poll());
93 
94   return {false};
95 }
96 
PasswordCallback(char * buf,int size,int rwflag,void * u)97 int PasswordCallback(char* buf, int size, int rwflag, void* u) {
98   const ByteSource* passphrase = *static_cast<const ByteSource**>(u);
99   if (passphrase != nullptr) {
100     size_t buflen = static_cast<size_t>(size);
101     size_t len = passphrase->size();
102     if (buflen < len)
103       return -1;
104     memcpy(buf, passphrase->data(), len);
105     return len;
106   }
107 
108   return -1;
109 }
110 
111 // This callback is used to avoid the default passphrase callback in OpenSSL
112 // which will typically prompt for the passphrase. The prompting is designed
113 // for the OpenSSL CLI, but works poorly for Node.js because it involves
114 // synchronous interaction with the controlling terminal, something we never
115 // want, and use this function to avoid it.
NoPasswordCallback(char * buf,int size,int rwflag,void * u)116 int NoPasswordCallback(char* buf, int size, int rwflag, void* u) {
117   return 0;
118 }
119 
ProcessFipsOptions()120 bool ProcessFipsOptions() {
121   /* Override FIPS settings in configuration file, if needed. */
122   if (per_process::cli_options->enable_fips_crypto ||
123       per_process::cli_options->force_fips_crypto) {
124 #if OPENSSL_VERSION_MAJOR >= 3
125     OSSL_PROVIDER* fips_provider = OSSL_PROVIDER_load(nullptr, "fips");
126     if (fips_provider == nullptr)
127       return false;
128     OSSL_PROVIDER_unload(fips_provider);
129 
130     return EVP_default_properties_enable_fips(nullptr, 1) &&
131            EVP_default_properties_is_fips_enabled(nullptr);
132 #else
133     if (FIPS_mode() == 0) return FIPS_mode_set(1);
134 
135 #endif
136   }
137   return true;
138 }
139 
InitCryptoOnce(Isolate * isolate)140 bool InitCryptoOnce(Isolate* isolate) {
141   static uv_once_t init_once = UV_ONCE_INIT;
142   TryCatch try_catch{isolate};
143   uv_once(&init_once, InitCryptoOnce);
144   if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
145     try_catch.ReThrow();
146     return false;
147   }
148   return true;
149 }
150 
151 // Protect accesses to FIPS state with a mutex. This should potentially
152 // be part of a larger mutex for global OpenSSL state.
153 static Mutex fips_mutex;
154 
InitCryptoOnce()155 void InitCryptoOnce() {
156   Mutex::ScopedLock lock(per_process::cli_options_mutex);
157   Mutex::ScopedLock fips_lock(fips_mutex);
158 #ifndef OPENSSL_IS_BORINGSSL
159   OPENSSL_INIT_SETTINGS* settings = OPENSSL_INIT_new();
160 
161 #if OPENSSL_VERSION_MAJOR < 3
162   // --openssl-config=...
163   if (!per_process::cli_options->openssl_config.empty()) {
164     const char* conf = per_process::cli_options->openssl_config.c_str();
165     OPENSSL_INIT_set_config_filename(settings, conf);
166   }
167 #endif
168 
169 #if OPENSSL_VERSION_MAJOR >= 3
170   // --openssl-legacy-provider
171   if (per_process::cli_options->openssl_legacy_provider) {
172     OSSL_PROVIDER* legacy_provider = OSSL_PROVIDER_load(nullptr, "legacy");
173     if (legacy_provider == nullptr) {
174       fprintf(stderr, "Unable to load legacy provider.\n");
175     }
176   }
177 #endif
178 
179   OPENSSL_init_ssl(0, settings);
180   OPENSSL_INIT_free(settings);
181   settings = nullptr;
182 
183 #ifndef _WIN32
184   if (per_process::cli_options->secure_heap != 0) {
185     switch (CRYPTO_secure_malloc_init(
186                 per_process::cli_options->secure_heap,
187                 static_cast<int>(per_process::cli_options->secure_heap_min))) {
188       case 0:
189         fprintf(stderr, "Unable to initialize openssl secure heap.\n");
190         break;
191       case 2:
192         // Not a fatal error but worthy of a warning.
193         fprintf(stderr, "Unable to memory map openssl secure heap.\n");
194         break;
195       case 1:
196         // OK!
197         break;
198     }
199   }
200 #endif
201 
202 #endif  // OPENSSL_IS_BORINGSSL
203 
204   // Turn off compression. Saves memory and protects against CRIME attacks.
205   // No-op with OPENSSL_NO_COMP builds of OpenSSL.
206   sk_SSL_COMP_zero(SSL_COMP_get_compression_methods());
207 
208 #ifndef OPENSSL_NO_ENGINE
209   ERR_load_ENGINE_strings();
210   ENGINE_load_builtin_engines();
211 #endif  // !OPENSSL_NO_ENGINE
212 }
213 
GetFipsCrypto(const FunctionCallbackInfo<Value> & args)214 void GetFipsCrypto(const FunctionCallbackInfo<Value>& args) {
215   Mutex::ScopedLock lock(per_process::cli_options_mutex);
216   Mutex::ScopedLock fips_lock(fips_mutex);
217 
218 #if OPENSSL_VERSION_MAJOR >= 3
219   args.GetReturnValue().Set(EVP_default_properties_is_fips_enabled(nullptr) ?
220       1 : 0);
221 #else
222   args.GetReturnValue().Set(FIPS_mode() ? 1 : 0);
223 #endif
224 }
225 
SetFipsCrypto(const FunctionCallbackInfo<Value> & args)226 void SetFipsCrypto(const FunctionCallbackInfo<Value>& args) {
227   Mutex::ScopedLock lock(per_process::cli_options_mutex);
228   Mutex::ScopedLock fips_lock(fips_mutex);
229 
230   CHECK(!per_process::cli_options->force_fips_crypto);
231   Environment* env = Environment::GetCurrent(args);
232   // TODO(addaleax): This should not be possible to set from worker threads.
233   // CHECK(env->owns_process_state());
234   bool enable = args[0]->BooleanValue(env->isolate());
235 
236 #if OPENSSL_VERSION_MAJOR >= 3
237   if (enable == EVP_default_properties_is_fips_enabled(nullptr))
238 #else
239   if (static_cast<int>(enable) == FIPS_mode())
240 #endif
241     return;  // No action needed.
242 
243 #if OPENSSL_VERSION_MAJOR >= 3
244   if (!EVP_default_properties_enable_fips(nullptr, enable)) {
245 #else
246   if (!FIPS_mode_set(enable)) {
247 #endif
248     unsigned long err = ERR_get_error();  // NOLINT(runtime/int)
249     return ThrowCryptoError(env, err);
250   }
251 }
252 
253 void TestFipsCrypto(const v8::FunctionCallbackInfo<v8::Value>& args) {
254   Mutex::ScopedLock lock(per_process::cli_options_mutex);
255   Mutex::ScopedLock fips_lock(fips_mutex);
256 
257 #if OPENSSL_VERSION_MAJOR >= 3
258   OSSL_PROVIDER* fips_provider = nullptr;
259   if (OSSL_PROVIDER_available(nullptr, "fips")) {
260     fips_provider = OSSL_PROVIDER_load(nullptr, "fips");
261   }
262   const auto enabled = fips_provider == nullptr ? 0 :
263       OSSL_PROVIDER_self_test(fips_provider) ? 1 : 0;
264 #else
265 #ifdef OPENSSL_FIPS
266   const auto enabled = FIPS_selftest() ? 1 : 0;
267 #else  // OPENSSL_FIPS
268   const auto enabled = 0;
269 #endif  // OPENSSL_FIPS
270 #endif
271 
272   args.GetReturnValue().Set(enabled);
273 }
274 
275 void CryptoErrorStore::Capture() {
276   errors_.clear();
277   while (const uint32_t err = ERR_get_error()) {
278     char buf[256];
279     ERR_error_string_n(err, buf, sizeof(buf));
280     errors_.emplace_back(buf);
281   }
282   std::reverse(std::begin(errors_), std::end(errors_));
283 }
284 
285 bool CryptoErrorStore::Empty() const {
286   return errors_.empty();
287 }
288 
289 MaybeLocal<Value> CryptoErrorStore::ToException(
290     Environment* env,
291     Local<String> exception_string) const {
292   if (exception_string.IsEmpty()) {
293     CryptoErrorStore copy(*this);
294     if (copy.Empty()) {
295       // But possibly a bug...
296       copy.Insert(NodeCryptoError::OK);
297     }
298     // Use last element as the error message, everything else goes
299     // into the .opensslErrorStack property on the exception object.
300     const std::string& last_error_string = copy.errors_.back();
301     Local<String> exception_string;
302     if (!String::NewFromUtf8(
303             env->isolate(),
304             last_error_string.data(),
305             NewStringType::kNormal,
306             last_error_string.size()).ToLocal(&exception_string)) {
307       return MaybeLocal<Value>();
308     }
309     copy.errors_.pop_back();
310     return copy.ToException(env, exception_string);
311   }
312 
313   Local<Value> exception_v = Exception::Error(exception_string);
314   CHECK(!exception_v.IsEmpty());
315 
316   if (!Empty()) {
317     CHECK(exception_v->IsObject());
318     Local<Object> exception = exception_v.As<Object>();
319     Local<Value> stack;
320     if (!ToV8Value(env->context(), errors_).ToLocal(&stack) ||
321         exception->Set(env->context(), env->openssl_error_stack(), stack)
322             .IsNothing()) {
323       return MaybeLocal<Value>();
324     }
325   }
326 
327   return exception_v;
328 }
329 
330 ByteSource::ByteSource(ByteSource&& other) noexcept
331     : data_(other.data_),
332       allocated_data_(other.allocated_data_),
333       size_(other.size_) {
334   other.allocated_data_ = nullptr;
335 }
336 
337 ByteSource::~ByteSource() {
338   OPENSSL_clear_free(allocated_data_, size_);
339 }
340 
341 ByteSource& ByteSource::operator=(ByteSource&& other) noexcept {
342   if (&other != this) {
343     OPENSSL_clear_free(allocated_data_, size_);
344     data_ = other.data_;
345     allocated_data_ = other.allocated_data_;
346     other.allocated_data_ = nullptr;
347     size_ = other.size_;
348   }
349   return *this;
350 }
351 
352 std::unique_ptr<BackingStore> ByteSource::ReleaseToBackingStore() {
353   // It's ok for allocated_data_ to be nullptr but
354   // only if size_ is zero.
355   CHECK_IMPLIES(size_ > 0, allocated_data_ != nullptr);
356   std::unique_ptr<BackingStore> ptr = ArrayBuffer::NewBackingStore(
357       allocated_data_,
358       size(),
359       [](void* data, size_t length, void* deleter_data) {
360         OPENSSL_clear_free(deleter_data, length);
361       }, allocated_data_);
362   CHECK(ptr);
363   allocated_data_ = nullptr;
364   data_ = nullptr;
365   size_ = 0;
366   return ptr;
367 }
368 
369 Local<ArrayBuffer> ByteSource::ToArrayBuffer(Environment* env) {
370   std::unique_ptr<BackingStore> store = ReleaseToBackingStore();
371   return ArrayBuffer::New(env->isolate(), std::move(store));
372 }
373 
374 MaybeLocal<Uint8Array> ByteSource::ToBuffer(Environment* env) {
375   Local<ArrayBuffer> ab = ToArrayBuffer(env);
376   return Buffer::New(env, ab, 0, ab->ByteLength());
377 }
378 
379 ByteSource ByteSource::FromBIO(const BIOPointer& bio) {
380   CHECK(bio);
381   BUF_MEM* bptr;
382   BIO_get_mem_ptr(bio.get(), &bptr);
383   ByteSource::Builder out(bptr->length);
384   memcpy(out.data<void>(), bptr->data, bptr->length);
385   return std::move(out).release();
386 }
387 
388 ByteSource ByteSource::FromEncodedString(Environment* env,
389                                          Local<String> key,
390                                          enum encoding enc) {
391   size_t length = 0;
392   ByteSource out;
393 
394   if (StringBytes::Size(env->isolate(), key, enc).To(&length) && length > 0) {
395     ByteSource::Builder buf(length);
396     size_t actual =
397         StringBytes::Write(env->isolate(), buf.data<char>(), length, key, enc);
398     out = std::move(buf).release(actual);
399   }
400 
401   return out;
402 }
403 
404 ByteSource ByteSource::FromStringOrBuffer(Environment* env,
405                                           Local<Value> value) {
406   return IsAnyByteSource(value) ? FromBuffer(value)
407                                 : FromString(env, value.As<String>());
408 }
409 
410 ByteSource ByteSource::FromString(Environment* env, Local<String> str,
411                                   bool ntc) {
412   CHECK(str->IsString());
413   size_t size = str->Utf8Length(env->isolate());
414   size_t alloc_size = ntc ? size + 1 : size;
415   ByteSource::Builder out(alloc_size);
416   int opts = String::NO_OPTIONS;
417   if (!ntc) opts |= String::NO_NULL_TERMINATION;
418   str->WriteUtf8(env->isolate(), out.data<char>(), alloc_size, nullptr, opts);
419   return std::move(out).release();
420 }
421 
422 ByteSource ByteSource::FromBuffer(Local<Value> buffer, bool ntc) {
423   ArrayBufferOrViewContents<char> buf(buffer);
424   return ntc ? buf.ToNullTerminatedCopy() : buf.ToByteSource();
425 }
426 
427 ByteSource ByteSource::FromSecretKeyBytes(
428     Environment* env,
429     Local<Value> value) {
430   // A key can be passed as a string, buffer or KeyObject with type 'secret'.
431   // If it is a string, we need to convert it to a buffer. We are not doing that
432   // in JS to avoid creating an unprotected copy on the heap.
433   return value->IsString() || IsAnyByteSource(value) ?
434            ByteSource::FromStringOrBuffer(env, value) :
435            ByteSource::FromSymmetricKeyObjectHandle(value);
436 }
437 
438 ByteSource ByteSource::NullTerminatedCopy(Environment* env,
439                                           Local<Value> value) {
440   return Buffer::HasInstance(value) ? FromBuffer(value, true)
441                                     : FromString(env, value.As<String>(), true);
442 }
443 
444 ByteSource ByteSource::FromSymmetricKeyObjectHandle(Local<Value> handle) {
445   CHECK(handle->IsObject());
446   KeyObjectHandle* key = Unwrap<KeyObjectHandle>(handle.As<Object>());
447   CHECK_NOT_NULL(key);
448   return Foreign(key->Data()->GetSymmetricKey(),
449                  key->Data()->GetSymmetricKeySize());
450 }
451 
452 ByteSource ByteSource::Allocated(void* data, size_t size) {
453   return ByteSource(data, data, size);
454 }
455 
456 ByteSource ByteSource::Foreign(const void* data, size_t size) {
457   return ByteSource(data, nullptr, size);
458 }
459 
460 namespace error {
461 Maybe<bool> Decorate(Environment* env, Local<Object> obj,
462               unsigned long err) {  // NOLINT(runtime/int)
463   if (err == 0) return Just(true);  // No decoration necessary.
464 
465   const char* ls = ERR_lib_error_string(err);
466   const char* fs = ERR_func_error_string(err);
467   const char* rs = ERR_reason_error_string(err);
468 
469   Isolate* isolate = env->isolate();
470   Local<Context> context = isolate->GetCurrentContext();
471 
472   if (ls != nullptr) {
473     if (obj->Set(context, env->library_string(),
474                  OneByteString(isolate, ls)).IsNothing()) {
475       return Nothing<bool>();
476     }
477   }
478   if (fs != nullptr) {
479     if (obj->Set(context, env->function_string(),
480                  OneByteString(isolate, fs)).IsNothing()) {
481       return Nothing<bool>();
482     }
483   }
484   if (rs != nullptr) {
485     if (obj->Set(context, env->reason_string(),
486                  OneByteString(isolate, rs)).IsNothing()) {
487       return Nothing<bool>();
488     }
489 
490     // SSL has no API to recover the error name from the number, so we
491     // transform reason strings like "this error" to "ERR_SSL_THIS_ERROR",
492     // which ends up being close to the original error macro name.
493     std::string reason(rs);
494 
495     for (auto& c : reason) {
496       if (c == ' ')
497         c = '_';
498       else
499         c = ToUpper(c);
500     }
501 
502 #define OSSL_ERROR_CODES_MAP(V)                                               \
503     V(SYS)                                                                    \
504     V(BN)                                                                     \
505     V(RSA)                                                                    \
506     V(DH)                                                                     \
507     V(EVP)                                                                    \
508     V(BUF)                                                                    \
509     V(OBJ)                                                                    \
510     V(PEM)                                                                    \
511     V(DSA)                                                                    \
512     V(X509)                                                                   \
513     V(ASN1)                                                                   \
514     V(CONF)                                                                   \
515     V(CRYPTO)                                                                 \
516     V(EC)                                                                     \
517     V(SSL)                                                                    \
518     V(BIO)                                                                    \
519     V(PKCS7)                                                                  \
520     V(X509V3)                                                                 \
521     V(PKCS12)                                                                 \
522     V(RAND)                                                                   \
523     V(DSO)                                                                    \
524     V(ENGINE)                                                                 \
525     V(OCSP)                                                                   \
526     V(UI)                                                                     \
527     V(COMP)                                                                   \
528     V(ECDSA)                                                                  \
529     V(ECDH)                                                                   \
530     V(OSSL_STORE)                                                             \
531     V(FIPS)                                                                   \
532     V(CMS)                                                                    \
533     V(TS)                                                                     \
534     V(HMAC)                                                                   \
535     V(CT)                                                                     \
536     V(ASYNC)                                                                  \
537     V(KDF)                                                                    \
538     V(SM2)                                                                    \
539     V(USER)                                                                   \
540 
541 #define V(name) case ERR_LIB_##name: lib = #name "_"; break;
542     const char* lib = "";
543     const char* prefix = "OSSL_";
544     switch (ERR_GET_LIB(err)) { OSSL_ERROR_CODES_MAP(V) }
545 #undef V
546 #undef OSSL_ERROR_CODES_MAP
547     // Don't generate codes like "ERR_OSSL_SSL_".
548     if (lib && strcmp(lib, "SSL_") == 0)
549       prefix = "";
550 
551     // All OpenSSL reason strings fit in a single 80-column macro definition,
552     // all prefix lengths are <= 10, and ERR_OSSL_ is 9, so 128 is more than
553     // sufficient.
554     char code[128];
555     snprintf(code, sizeof(code), "ERR_%s%s%s", prefix, lib, reason.c_str());
556 
557     if (obj->Set(env->isolate()->GetCurrentContext(),
558              env->code_string(),
559              OneByteString(env->isolate(), code)).IsNothing())
560       return Nothing<bool>();
561   }
562 
563   return Just(true);
564 }
565 }  // namespace error
566 
567 void ThrowCryptoError(Environment* env,
568                       unsigned long err,  // NOLINT(runtime/int)
569                       // Default, only used if there is no SSL `err` which can
570                       // be used to create a long-style message string.
571                       const char* message) {
572   char message_buffer[128] = {0};
573   if (err != 0 || message == nullptr) {
574     ERR_error_string_n(err, message_buffer, sizeof(message_buffer));
575     message = message_buffer;
576   }
577   HandleScope scope(env->isolate());
578   Local<String> exception_string;
579   Local<Value> exception;
580   Local<Object> obj;
581   if (!String::NewFromUtf8(env->isolate(), message).ToLocal(&exception_string))
582     return;
583   CryptoErrorStore errors;
584   errors.Capture();
585   if (!errors.ToException(env, exception_string).ToLocal(&exception) ||
586       !exception->ToObject(env->context()).ToLocal(&obj) ||
587       error::Decorate(env, obj, err).IsNothing()) {
588     return;
589   }
590   env->isolate()->ThrowException(exception);
591 }
592 
593 #ifndef OPENSSL_NO_ENGINE
594 EnginePointer LoadEngineById(const char* id, CryptoErrorStore* errors) {
595   MarkPopErrorOnReturn mark_pop_error_on_return;
596 
597   EnginePointer engine(ENGINE_by_id(id));
598   if (!engine) {
599     // Engine not found, try loading dynamically.
600     engine = EnginePointer(ENGINE_by_id("dynamic"));
601     if (engine) {
602       if (!ENGINE_ctrl_cmd_string(engine.get(), "SO_PATH", id, 0) ||
603           !ENGINE_ctrl_cmd_string(engine.get(), "LOAD", nullptr, 0)) {
604         engine.reset();
605       }
606     }
607   }
608 
609   if (!engine && errors != nullptr) {
610     errors->Capture();
611     if (errors->Empty()) {
612       errors->Insert(NodeCryptoError::ENGINE_NOT_FOUND, id);
613     }
614   }
615 
616   return engine;
617 }
618 
619 bool SetEngine(const char* id, uint32_t flags, CryptoErrorStore* errors) {
620   ClearErrorOnReturn clear_error_on_return;
621   EnginePointer engine = LoadEngineById(id, errors);
622   if (!engine)
623     return false;
624 
625   if (!ENGINE_set_default(engine.get(), flags)) {
626     if (errors != nullptr)
627       errors->Capture();
628     return false;
629   }
630 
631   return true;
632 }
633 
634 void SetEngine(const FunctionCallbackInfo<Value>& args) {
635   Environment* env = Environment::GetCurrent(args);
636   CHECK(args.Length() >= 2 && args[0]->IsString());
637   uint32_t flags;
638   if (!args[1]->Uint32Value(env->context()).To(&flags)) return;
639 
640   const node::Utf8Value engine_id(env->isolate(), args[0]);
641 
642   args.GetReturnValue().Set(SetEngine(*engine_id, flags));
643 }
644 #endif  // !OPENSSL_NO_ENGINE
645 
646 MaybeLocal<Value> EncodeBignum(
647     Environment* env,
648     const BIGNUM* bn,
649     int size,
650     Local<Value>* error) {
651   std::vector<uint8_t> buf(size);
652   CHECK_EQ(BN_bn2binpad(bn, buf.data(), size), size);
653   return StringBytes::Encode(
654       env->isolate(),
655       reinterpret_cast<const char*>(buf.data()),
656       buf.size(),
657       BASE64URL,
658       error);
659 }
660 
661 Maybe<bool> SetEncodedValue(
662     Environment* env,
663     Local<Object> target,
664     Local<String> name,
665     const BIGNUM* bn,
666     int size) {
667   Local<Value> value;
668   Local<Value> error;
669   CHECK_NOT_NULL(bn);
670   if (size == 0)
671     size = BN_num_bytes(bn);
672   if (!EncodeBignum(env, bn, size, &error).ToLocal(&value)) {
673     if (!error.IsEmpty())
674       env->isolate()->ThrowException(error);
675     return Nothing<bool>();
676   }
677   return target->Set(env->context(), name, value);
678 }
679 
680 bool SetRsaOaepLabel(const EVPKeyCtxPointer& ctx, const ByteSource& label) {
681   if (label.size() != 0) {
682     // OpenSSL takes ownership of the label, so we need to create a copy.
683     void* label_copy = OPENSSL_memdup(label.data(), label.size());
684     CHECK_NOT_NULL(label_copy);
685     int ret = EVP_PKEY_CTX_set0_rsa_oaep_label(
686         ctx.get(), static_cast<unsigned char*>(label_copy), label.size());
687     if (ret <= 0) {
688       OPENSSL_free(label_copy);
689       return false;
690     }
691   }
692   return true;
693 }
694 
695 CryptoJobMode GetCryptoJobMode(v8::Local<v8::Value> args) {
696   CHECK(args->IsUint32());
697   uint32_t mode = args.As<v8::Uint32>()->Value();
698   CHECK_LE(mode, kCryptoJobSync);
699   return static_cast<CryptoJobMode>(mode);
700 }
701 
702 namespace {
703 // SecureBuffer uses OPENSSL_secure_malloc to allocate a Uint8Array.
704 // Without --secure-heap, OpenSSL's secure heap is disabled,
705 // in which case this has the same semantics as
706 // using OPENSSL_malloc. However, if the secure heap is
707 // initialized, SecureBuffer will automatically use it.
708 void SecureBuffer(const FunctionCallbackInfo<Value>& args) {
709   CHECK(args[0]->IsUint32());
710   Environment* env = Environment::GetCurrent(args);
711   uint32_t len = args[0].As<Uint32>()->Value();
712   void* data = OPENSSL_secure_zalloc(len);
713   if (data == nullptr) {
714     // There's no memory available for the allocation.
715     // Return nothing.
716     return;
717   }
718   std::shared_ptr<BackingStore> store =
719       ArrayBuffer::NewBackingStore(
720           data,
721           len,
722           [](void* data, size_t len, void* deleter_data) {
723             OPENSSL_secure_clear_free(data, len);
724           },
725           data);
726   Local<ArrayBuffer> buffer = ArrayBuffer::New(env->isolate(), store);
727   args.GetReturnValue().Set(Uint8Array::New(buffer, 0, len));
728 }
729 
730 void SecureHeapUsed(const FunctionCallbackInfo<Value>& args) {
731   Environment* env = Environment::GetCurrent(args);
732   if (CRYPTO_secure_malloc_initialized())
733     args.GetReturnValue().Set(
734         BigInt::New(env->isolate(), CRYPTO_secure_used()));
735 }
736 }  // namespace
737 
738 namespace Util {
739 void Initialize(Environment* env, Local<Object> target) {
740   Local<Context> context = env->context();
741 #ifndef OPENSSL_NO_ENGINE
742   SetMethod(context, target, "setEngine", SetEngine);
743 #endif  // !OPENSSL_NO_ENGINE
744 
745   SetMethodNoSideEffect(context, target, "getFipsCrypto", GetFipsCrypto);
746   SetMethod(context, target, "setFipsCrypto", SetFipsCrypto);
747   SetMethodNoSideEffect(context, target, "testFipsCrypto", TestFipsCrypto);
748 
749   NODE_DEFINE_CONSTANT(target, kCryptoJobAsync);
750   NODE_DEFINE_CONSTANT(target, kCryptoJobSync);
751 
752   SetMethod(context, target, "secureBuffer", SecureBuffer);
753   SetMethod(context, target, "secureHeapUsed", SecureHeapUsed);
754 }
755 void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
756 #ifndef OPENSSL_NO_ENGINE
757   registry->Register(SetEngine);
758 #endif  // !OPENSSL_NO_ENGINE
759 
760   registry->Register(GetFipsCrypto);
761   registry->Register(SetFipsCrypto);
762   registry->Register(TestFipsCrypto);
763   registry->Register(SecureBuffer);
764   registry->Register(SecureHeapUsed);
765 }
766 
767 }  // namespace Util
768 
769 }  // namespace crypto
770 }  // namespace node
771