Browse Source

Node 12 Upgrade (5-0-x) (#17752)

* fix: backport boringssl patches for node compat

* refactor: prevent node macros from overriding base (#17178)

* fix: backport boring ssl patch OPENSSL_clear_free

* refactor: load electron builtin modules with process._linkedBinding (#17247)

* refactor: load electron builtin modules with process._linkedBinding

NODE_BUILTING_MODULE_CONTEXT_AWARE and process.binding are
removed in https://github.com/nodejs/node/pull/25829. This changes
uses the alternative available without any functionality change.

* chore: roll node

* fix: add boringssl backport to support node upgrade

* fix: Update node_includes.h, add DCHECK macros

* fix: Update node Debug Options parser usage

* fix: Fix asar setup

* fix: using v8Util in isolated context

* fix: make "process" available in preload scripts

* fix: use proper options parser and remove setting of _breakFirstLine

_breakFirstLine was being set on the process, but that has changed in node 12 and so is no longer needed. Node will handle it properly when --inspect-brk is provided

* fix: process.binding => _linkedBinding in sandboxed isolated preload

* chore: update node dep sha

* fix: make original-fs work with streams
Nitish Sakhawalkar 6 years ago
parent
commit
ffd2224bbe
61 changed files with 945 additions and 82 deletions
  1. 1 1
      DEPS
  2. 1 1
      atom/browser/api/atom_api_app.cc
  3. 1 1
      atom/browser/api/atom_api_auto_updater.cc
  4. 1 1
      atom/browser/api/atom_api_browser_view.cc
  5. 1 1
      atom/browser/api/atom_api_browser_window.cc
  6. 1 1
      atom/browser/api/atom_api_content_tracing.cc
  7. 1 1
      atom/browser/api/atom_api_debugger.cc
  8. 1 1
      atom/browser/api/atom_api_desktop_capturer.cc
  9. 1 1
      atom/browser/api/atom_api_dialog.cc
  10. 1 1
      atom/browser/api/atom_api_download_item.cc
  11. 1 1
      atom/browser/api/atom_api_event.cc
  12. 1 1
      atom/browser/api/atom_api_global_shortcut.cc
  13. 1 1
      atom/browser/api/atom_api_in_app_purchase.cc
  14. 1 1
      atom/browser/api/atom_api_menu.cc
  15. 1 1
      atom/browser/api/atom_api_net.cc
  16. 1 1
      atom/browser/api/atom_api_notification.cc
  17. 1 1
      atom/browser/api/atom_api_power_monitor.cc
  18. 1 1
      atom/browser/api/atom_api_power_save_blocker.cc
  19. 1 1
      atom/browser/api/atom_api_protocol.cc
  20. 2 2
      atom/browser/api/atom_api_render_process_preferences.cc
  21. 1 1
      atom/browser/api/atom_api_screen.cc
  22. 1 1
      atom/browser/api/atom_api_session.cc
  23. 1 1
      atom/browser/api/atom_api_system_preferences.cc
  24. 1 1
      atom/browser/api/atom_api_top_level_window.cc
  25. 1 1
      atom/browser/api/atom_api_tray.cc
  26. 1 1
      atom/browser/api/atom_api_view.cc
  27. 1 1
      atom/browser/api/atom_api_web_contents.cc
  28. 1 1
      atom/browser/api/atom_api_web_contents_view.cc
  29. 1 1
      atom/browser/api/atom_api_web_view_manager.cc
  30. 1 1
      atom/browser/api/views/atom_api_box_layout.cc
  31. 1 1
      atom/browser/api/views/atom_api_button.cc
  32. 1 1
      atom/browser/api/views/atom_api_label_button.cc
  33. 1 1
      atom/browser/api/views/atom_api_layout_manager.cc
  34. 1 1
      atom/browser/api/views/atom_api_md_text_button.cc
  35. 1 1
      atom/browser/api/views/atom_api_resize_area.cc
  36. 1 1
      atom/browser/api/views/atom_api_text_field.cc
  37. 3 10
      atom/browser/node_debugger.cc
  38. 3 8
      atom/common/api/atom_api_asar.cc
  39. 1 1
      atom/common/api/atom_api_clipboard.cc
  40. 1 1
      atom/common/api/atom_api_command_line.cc
  41. 1 1
      atom/common/api/atom_api_crash_reporter.cc
  42. 1 1
      atom/common/api/atom_api_native_image.cc
  43. 1 1
      atom/common/api/atom_api_shell.cc
  44. 1 1
      atom/common/api/atom_api_v8_util.cc
  45. 1 1
      atom/common/api/features.cc
  46. 1 1
      atom/common/node_bindings.cc
  47. 57 3
      atom/common/node_includes.h
  48. 1 1
      atom/renderer/api/atom_api_renderer_ipc.cc
  49. 1 1
      atom/renderer/api/atom_api_web_frame.cc
  50. 2 2
      atom/renderer/atom_sandboxed_renderer_client.cc
  51. 1 1
      lib/common/asar.js
  52. 1 9
      lib/common/asar_init.js
  53. 1 1
      lib/common/init.js
  54. 1 1
      lib/isolated_renderer/init.js
  55. 18 0
      lib/renderer/init.js
  56. 4 0
      patches/common/boringssl/.patches
  57. 397 0
      patches/common/boringssl/add_a_very_roundabout_ec_keygen_api.patch
  58. 179 0
      patches/common/boringssl/add_some_node_compatibility_functions.patch
  59. 40 0
      patches/common/boringssl/silence_unused_variable_warnings_when_using_openssl_clear_free.patch
  60. 187 0
      patches/common/boringssl/support_get_versions_with_get_min_max_proto_version_for_context.patch
  61. 4 0
      spec/asar-spec.js

+ 1 - 1
DEPS

@@ -12,7 +12,7 @@ vars = {
   'chromium_version':
     '73.0.3683.116',
   'node_version':
-    'f807d72614d4b8973d71548328be213532b46b1b',
+    'de2f087468244d2a86e4400803f743c42fa9345a',
 
   'boto_version': 'f7574aa6cc2c819430c1f05e9a1a1a666ef8169b',
   'pyyaml_version': '3.12',

+ 1 - 1
atom/browser/api/atom_api_app.cc

@@ -1413,4 +1413,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_app, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_app, Initialize)

+ 1 - 1
atom/browser/api/atom_api_auto_updater.cc

@@ -154,4 +154,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_auto_updater, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_auto_updater, Initialize)

+ 1 - 1
atom/browser/api/atom_api_browser_view.cc

@@ -172,4 +172,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_browser_view, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_browser_view, Initialize)

+ 1 - 1
atom/browser/api/atom_api_browser_window.cc

@@ -481,4 +481,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_window, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_window, Initialize)

+ 1 - 1
atom/browser/api/atom_api_content_tracing.cc

@@ -140,4 +140,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_content_tracing, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_content_tracing, Initialize)

+ 1 - 1
atom/browser/api/atom_api_debugger.cc

@@ -205,4 +205,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_debugger, Initialize);
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_debugger, Initialize);

+ 1 - 1
atom/browser/api/atom_api_desktop_capturer.cc

@@ -230,4 +230,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_desktop_capturer, Initialize);
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_desktop_capturer, Initialize);

+ 1 - 1
atom/browser/api/atom_api_dialog.cc

@@ -96,4 +96,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_dialog, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_dialog, Initialize)

+ 1 - 1
atom/browser/api/atom_api_download_item.cc

@@ -251,4 +251,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_download_item, Initialize);
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_download_item, Initialize);

+ 1 - 1
atom/browser/api/atom_api_event.cc

@@ -23,4 +23,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_event, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_event, Initialize)

+ 1 - 1
atom/browser/api/atom_api_global_shortcut.cc

@@ -166,4 +166,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_global_shortcut, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_global_shortcut, Initialize)

+ 1 - 1
atom/browser/api/atom_api_in_app_purchase.cc

@@ -140,4 +140,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_in_app_purchase, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_in_app_purchase, Initialize)

+ 1 - 1
atom/browser/api/atom_api_menu.cc

@@ -245,4 +245,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_menu, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_menu, Initialize)

+ 1 - 1
atom/browser/api/atom_api_net.cc

@@ -61,4 +61,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_net, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_net, Initialize)

+ 1 - 1
atom/browser/api/atom_api_notification.cc

@@ -272,4 +272,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_common_notification, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_common_notification, Initialize)

+ 1 - 1
atom/browser/api/atom_api_power_monitor.cc

@@ -148,4 +148,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_power_monitor, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_power_monitor, Initialize)

+ 1 - 1
atom/browser/api/atom_api_power_save_blocker.cc

@@ -151,4 +151,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_power_save_blocker, Initialize);
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_power_save_blocker, Initialize);

+ 1 - 1
atom/browser/api/atom_api_protocol.cc

@@ -317,4 +317,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_protocol, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_protocol, Initialize)

+ 2 - 2
atom/browser/api/atom_api_render_process_preferences.cc

@@ -87,5 +87,5 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_render_process_preferences,
-                                  Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_render_process_preferences,
+                                 Initialize)

+ 1 - 1
atom/browser/api/atom_api_screen.cc

@@ -171,4 +171,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_common_screen, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_common_screen, Initialize)

+ 1 - 1
atom/browser/api/atom_api_session.cc

@@ -819,4 +819,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_session, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_session, Initialize)

+ 1 - 1
atom/browser/api/atom_api_system_preferences.cc

@@ -128,4 +128,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_system_preferences, Initialize);
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_system_preferences, Initialize);

+ 1 - 1
atom/browser/api/atom_api_top_level_window.cc

@@ -1199,4 +1199,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_top_level_window, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_top_level_window, Initialize)

+ 1 - 1
atom/browser/api/atom_api_tray.cc

@@ -261,4 +261,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_tray, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_tray, Initialize)

+ 1 - 1
atom/browser/api/atom_api_view.cc

@@ -86,4 +86,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_view, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_view, Initialize)

+ 1 - 1
atom/browser/api/atom_api_web_contents.cc

@@ -2309,4 +2309,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_web_contents, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_web_contents, Initialize)

+ 1 - 1
atom/browser/api/atom_api_web_contents_view.cc

@@ -131,4 +131,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_web_contents_view, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_web_contents_view, Initialize)

+ 1 - 1
atom/browser/api/atom_api_web_view_manager.cc

@@ -55,4 +55,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_web_view_manager, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_web_view_manager, Initialize)

+ 1 - 1
atom/browser/api/views/atom_api_box_layout.cc

@@ -84,4 +84,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_box_layout, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_box_layout, Initialize)

+ 1 - 1
atom/browser/api/views/atom_api_button.cc

@@ -57,4 +57,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_button, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_button, Initialize)

+ 1 - 1
atom/browser/api/views/atom_api_label_button.cc

@@ -77,4 +77,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_label_button, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_label_button, Initialize)

+ 1 - 1
atom/browser/api/views/atom_api_layout_manager.cc

@@ -60,4 +60,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_layout_manager, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_layout_manager, Initialize)

+ 1 - 1
atom/browser/api/views/atom_api_md_text_button.cc

@@ -54,4 +54,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_md_text_button, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_md_text_button, Initialize)

+ 1 - 1
atom/browser/api/views/atom_api_resize_area.cc

@@ -57,4 +57,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_resize_area, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_resize_area, Initialize)

+ 1 - 1
atom/browser/api/views/atom_api_text_field.cc

@@ -64,4 +64,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_text_field, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_text_field, Initialize)

+ 3 - 10
atom/browser/node_debugger.cc

@@ -38,13 +38,13 @@ void NodeDebugger::Start() {
   }
 
   node::DebugOptions options;
+  node::options_parser::DebugOptionsParser options_parser;
   std::vector<std::string> exec_args;
   std::vector<std::string> v8_args;
   std::vector<std::string> errors;
 
-  node::options_parser::DebugOptionsParser::instance.Parse(
-      &args, &exec_args, &v8_args, &options,
-      node::options_parser::kDisallowedInEnvironment, &errors);
+  options_parser.Parse(&args, &exec_args, &v8_args, &options,
+                       node::options_parser::kDisallowedInEnvironment, &errors);
 
   if (!errors.empty()) {
     // TODO(jeremy): what's the appropriate behaviour here?
@@ -52,13 +52,6 @@ void NodeDebugger::Start() {
                << base::JoinString(errors, " ");
   }
 
-  // Set process._debugWaitConnect if --inspect-brk was specified to stop
-  // the debugger on the first line
-  if (options.wait_for_connect()) {
-    mate::Dictionary process(env_->isolate(), env_->process_object());
-    process.Set("_breakFirstLine", true);
-  }
-
   const char* path = "";
   if (inspector->Start(path, options,
                        std::make_shared<node::HostPort>(options.host_port),

+ 3 - 8
atom/common/api/atom_api_asar.cc

@@ -118,16 +118,11 @@ class Archive : public mate::Wrappable<Archive> {
   DISALLOW_COPY_AND_ASSIGN(Archive);
 };
 
-void InitAsarSupport(v8::Isolate* isolate,
-                     v8::Local<v8::Value> source,
-                     v8::Local<v8::Value> require) {
+void InitAsarSupport(v8::Isolate* isolate, v8::Local<v8::Value> require) {
   // Evaluate asar_init.js.
   std::vector<v8::Local<v8::String>> asar_init_params = {
-      node::FIXED_ONE_BYTE_STRING(isolate, "source"),
       node::FIXED_ONE_BYTE_STRING(isolate, "require")};
-
-  std::vector<v8::Local<v8::Value>> asar_init_args = {source, require};
-
+  std::vector<v8::Local<v8::Value>> asar_init_args = {require};
   node::per_process::native_module_loader.CompileAndCall(
       isolate->GetCurrentContext(), "electron/js2c/asar_init",
       &asar_init_params, &asar_init_args, nullptr);
@@ -144,4 +139,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_common_asar, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_common_asar, Initialize)

+ 1 - 1
atom/common/api/atom_api_clipboard.cc

@@ -227,4 +227,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_common_clipboard, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_common_clipboard, Initialize)

+ 1 - 1
atom/common/api/atom_api_command_line.cc

@@ -58,4 +58,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_common_command_line, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_common_command_line, Initialize)

+ 1 - 1
atom/common/api/atom_api_crash_reporter.cc

@@ -66,4 +66,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_common_crash_reporter, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_common_crash_reporter, Initialize)

+ 1 - 1
atom/common/api/atom_api_native_image.cc

@@ -652,4 +652,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_common_native_image, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_common_native_image, Initialize)

+ 1 - 1
atom/common/api/atom_api_shell.cc

@@ -170,4 +170,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_common_shell, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_common_shell, Initialize)

+ 1 - 1
atom/common/api/atom_api_v8_util.cc

@@ -126,4 +126,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_common_v8_util, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_common_v8_util, Initialize)

+ 1 - 1
atom/common/api/features.cc

@@ -61,4 +61,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_common_features, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_common_features, Initialize)

+ 1 - 1
atom/common/node_bindings.cc

@@ -84,7 +84,7 @@
 // __attribute__((constructor)), we call the _register_<modname>
 // function for each built-in modules explicitly. This is only
 // forward declaration. The definitions are in each module's
-// implementation when calling the NODE_BUILTIN_MODULE_CONTEXT_AWARE.
+// implementation when calling the NODE_LINKED_MODULE_CONTEXT_AWARE.
 #define V(modname) void _register_##modname();
 ELECTRON_BUILTIN_MODULES(V)
 #if BUILDFLAG(ENABLE_VIEW_API)

+ 57 - 3
atom/common/node_includes.h

@@ -17,18 +17,46 @@
 // again. But we still need the tracing functions, so declaring them.
 #define SRC_TRACING_TRACE_EVENT_H_
 
+#pragma push_macro("ASSERT")
+#pragma push_macro("CHECK")
+#pragma push_macro("CHECK_EQ")
+#pragma push_macro("CHECK_GE")
+#pragma push_macro("CHECK_GT")
+#pragma push_macro("CHECK_LE")
+#pragma push_macro("CHECK_LT")
+#pragma push_macro("CHECK_NE")
+#pragma push_macro("DCHECK")
+#pragma push_macro("DCHECK_EQ")
+#pragma push_macro("DCHECK_GE")
+#pragma push_macro("DCHECK_GT")
+#pragma push_macro("DCHECK_LE")
+#pragma push_macro("DCHECK_LT")
+#pragma push_macro("DCHECK_NE")
+#pragma push_macro("DISALLOW_COPY_AND_ASSIGN")
+#pragma push_macro("LIKELY")
+#pragma push_macro("NO_RETURN")
+#pragma push_macro("UNLIKELY")
+
 #undef ASSERT
 #undef CHECK
 #undef CHECK_EQ
-#undef CHECK_NE
 #undef CHECK_GE
 #undef CHECK_GT
 #undef CHECK_LE
 #undef CHECK_LT
-#undef UNLIKELY
+#undef CHECK_NE
+#undef DCHECK
+#undef DCHECK_EQ
+#undef DCHECK_GE
+#undef DCHECK_GT
+#undef DCHECK_LE
+#undef DCHECK_LT
+#undef DCHECK_NE
 #undef DISALLOW_COPY_AND_ASSIGN
-#undef NO_RETURN
 #undef LIKELY
+#undef NO_RETURN
+#undef UNLIKELY
+
 #undef debug_string    // This is defined in macOS SDK in AssertMacros.h.
 #undef require_string  // This is defined in macOS SDK in AssertMacros.h.
 #include "env-inl.h"
@@ -39,6 +67,32 @@
 #include "node_options.h"
 #include "node_platform.h"
 
+// Alternative to NODE_MODULE_CONTEXT_AWARE_X.
+// Allows to explicitly register builtin modules instead of using
+// __attribute__((constructor)).
+#define NODE_LINKED_MODULE_CONTEXT_AWARE(modname, regfunc) \
+  NODE_MODULE_CONTEXT_AWARE_CPP(modname, regfunc, nullptr, NM_F_LINKED)
+
+#pragma pop_macro("ASSERT")
+#pragma pop_macro("CHECK")
+#pragma pop_macro("CHECK_EQ")
+#pragma pop_macro("CHECK_GE")
+#pragma pop_macro("CHECK_GT")
+#pragma pop_macro("CHECK_LE")
+#pragma pop_macro("CHECK_LT")
+#pragma pop_macro("CHECK_NE")
+#pragma pop_macro("DCHECK")
+#pragma pop_macro("DCHECK_EQ")
+#pragma pop_macro("DCHECK_GE")
+#pragma pop_macro("DCHECK_GT")
+#pragma pop_macro("DCHECK_LE")
+#pragma pop_macro("DCHECK_LT")
+#pragma pop_macro("DCHECK_NE")
+#pragma pop_macro("DISALLOW_COPY_AND_ASSIGN")
+#pragma pop_macro("LIKELY")
+#pragma pop_macro("NO_RETURN")
+#pragma pop_macro("UNLIKELY")
+
 namespace node {
 namespace tracing {
 

+ 1 - 1
atom/renderer/api/atom_api_renderer_ipc.cc

@@ -91,4 +91,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_renderer_ipc, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_renderer_ipc, Initialize)

+ 1 - 1
atom/renderer/api/atom_api_web_frame.cc

@@ -548,4 +548,4 @@ void Initialize(v8::Local<v8::Object> exports,
 
 }  // namespace
 
-NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_renderer_web_frame, Initialize)
+NODE_LINKED_MODULE_CONTEXT_AWARE(atom_renderer_web_frame, Initialize)

+ 2 - 2
atom/renderer/atom_sandboxed_renderer_client.cc

@@ -68,7 +68,7 @@ v8::Local<v8::Value> GetBinding(v8::Isolate* isolate,
     return exports;
   }
 
-  auto* mod = node::binding::get_builtin_module(module_key.c_str());
+  auto* mod = node::binding::get_linked_module(module_key.c_str());
 
   if (!mod) {
     char errmsg[1024];
@@ -220,7 +220,7 @@ void AtomSandboxedRendererClient::SetupMainWorldOverrides(
   auto* isolate = context->GetIsolate();
 
   mate::Dictionary process = mate::Dictionary::CreateEmpty(isolate);
-  process.SetMethod("binding", GetBinding);
+  process.SetMethod("_linkedBinding", GetBinding);
 
   std::vector<v8::Local<v8::String>> isolated_bundle_params = {
       node::FIXED_ONE_BYTE_STRING(isolate, "nodeProcess"),

+ 1 - 1
lib/common/asar.js

@@ -1,7 +1,7 @@
 'use strict';
 
 (function () {
-  const asar = process.binding('atom_common_asar')
+  const asar = process._linkedBinding('atom_common_asar')
   const assert = require('assert')
   const { Buffer } = require('buffer')
   const childProcess = require('child_process')

+ 1 - 9
lib/common/asar_init.js

@@ -1,14 +1,6 @@
 'use strict'
 
-/* global source, require */
-
-// Expose fs module without asar support.
-// NB: Node's 'fs' and 'internal/fs/streams' have a lazy-loaded circular
-// dependency. So to expose the unmodified Node 'fs' functionality here,
-// we have to copy both 'fs' *and* 'internal/fs/streams' and modify the
-// copies to depend on each other instead of on our asarified 'fs' code.
-source['original-fs'].replace("require('internal/fs/streams')", "require('original-fs/streams')")
-source['original-fs/streams'].replace("require('fs')", "require('original-fs')")
+/* global require */
 
 // Monkey-patch the fs module.
 require('electron/js2c/asar').wrapFsWithAsar(require('fs'))

+ 1 - 1
lib/common/init.js

@@ -3,7 +3,7 @@
 const timers = require('timers')
 const util = require('util')
 
-process.atomBinding = require('@electron/internal/common/atom-binding-setup')(process.binding, process.type)
+process.atomBinding = require('@electron/internal/common/atom-binding-setup')(process._linkedBinding, process.type)
 
 // setImmediate and process.nextTick makes use of uv_check and uv_prepare to
 // run the callbacks, however since we only run uv loop on requests, the

+ 1 - 1
lib/isolated_renderer/init.js

@@ -2,7 +2,7 @@
 
 /* global nodeProcess, isolatedWorld */
 
-const atomBinding = require('@electron/internal/common/atom-binding-setup')(nodeProcess.binding, 'renderer')
+const atomBinding = require('@electron/internal/common/atom-binding-setup')(nodeProcess._linkedBinding, 'renderer')
 
 const v8Util = atomBinding('v8_util')
 

+ 18 - 0
lib/renderer/init.js

@@ -4,6 +4,24 @@ const { EventEmitter } = require('events')
 const path = require('path')
 const Module = require('module')
 
+// Make sure globals like "process" and "global" are always available in preload
+// scripts even after they are deleted in "loaded" script.
+//
+// Note 1: We rely on a Node patch to actually pass "process" and "global" and
+// other arguments to the wrapper.
+//
+// Note 2: Node introduced a new code path to use native code to wrap module
+// code, which does not work with this hack. However by modifying the
+// "Module.wrapper" we can force Node to use the old code path to wrap module
+// code with JavaScript.
+Module.wrapper = [
+  '(function (exports, require, module, __filename, __dirname, process, global, Buffer) { ' +
+  // By running the code in a new closure, it would be possible for the module
+  // code to override "process" and "Buffer" with local variables.
+  'return function (exports, require, module, __filename, __dirname) { ',
+  '\n}.call(this, exports, require, module, __filename, __dirname); });'
+]
+
 // We modified the original process.argv to let node.js load the
 // init.js, we need to restore it here.
 process.argv.splice(1, 1)

+ 4 - 0
patches/common/boringssl/.patches

@@ -4,3 +4,7 @@ expose_ripemd160.patch
 expose_aes-cfb.patch
 sync_sorted_ciphers.patch
 handle_pub_key_null_in_ec_key_set_public_key.patch
+add_some_node_compatibility_functions.patch
+add_a_very_roundabout_ec_keygen_api.patch
+silence_unused_variable_warnings_when_using_openssl_clear_free.patch
+support_get_versions_with_get_min_max_proto_version_for_context.patch

+ 397 - 0
patches/common/boringssl/add_a_very_roundabout_ec_keygen_api.patch

@@ -0,0 +1,397 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: David Benjamin <[email protected]>
+Date: Fri, 25 Jan 2019 16:36:28 -0600
+Subject: Add a very roundabout EC keygen API.
+
+OpenSSL's EVP-level EC API involves a separate "paramgen" operation,
+which is ultimately just a roundabout way to go from a NID to an
+EC_GROUP. But Node uses this, and it's the pattern used within OpenSSL
+these days, so this appears to be the official upstream recommendation.
+
+Also add a #define for OPENSSL_EC_EXPLICIT_CURVE, because Node uses it,
+but fail attempts to use it. Explicit curve encodings are forbidden by
+RFC 5480 and generally a bad idea. (Parsing such keys back into OpenSSL
+will cause it to lose the optimized path.)
+
+Change-Id: I5e97080e77cf90fc149f6cf6f2cc4900f573fc64
+Reviewed-on: https://boringssl-review.googlesource.com/c/34565
+Commit-Queue: David Benjamin <[email protected]>
+Commit-Queue: Adam Langley <[email protected]>
+Reviewed-by: Adam Langley <[email protected]>
+
+diff --git a/crypto/evp/evp_ctx.c b/crypto/evp/evp_ctx.c
+index 3599f77838731147c4812e85fb8f6145835c77af..daa1954b5e1c2d377660eb6bb36769b84fa39ac5 100644
+--- a/crypto/evp/evp_ctx.c
++++ b/crypto/evp/evp_ctx.c
+@@ -415,7 +415,7 @@ int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx) {
+   return 1;
+ }
+ 
+-int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey) {
++int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **out_pkey) {
+   if (!ctx || !ctx->pmeth || !ctx->pmeth->keygen) {
+     OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+     return 0;
+@@ -425,21 +425,60 @@ int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey) {
+     return 0;
+   }
+ 
+-  if (!ppkey) {
++  if (!out_pkey) {
+     return 0;
+   }
+ 
+-  if (!*ppkey) {
+-    *ppkey = EVP_PKEY_new();
+-    if (!*ppkey) {
++  if (!*out_pkey) {
++    *out_pkey = EVP_PKEY_new();
++    if (!*out_pkey) {
+       OPENSSL_PUT_ERROR(EVP, ERR_LIB_EVP);
+       return 0;
+     }
+   }
+ 
+-  if (!ctx->pmeth->keygen(ctx, *ppkey)) {
+-    EVP_PKEY_free(*ppkey);
+-    *ppkey = NULL;
++  if (!ctx->pmeth->keygen(ctx, *out_pkey)) {
++    EVP_PKEY_free(*out_pkey);
++    *out_pkey = NULL;
++    return 0;
++  }
++  return 1;
++}
++
++int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx) {
++  if (!ctx || !ctx->pmeth || !ctx->pmeth->paramgen) {
++    OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
++    return 0;
++  }
++  ctx->operation = EVP_PKEY_OP_PARAMGEN;
++  return 1;
++}
++
++int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **out_pkey) {
++  if (!ctx || !ctx->pmeth || !ctx->pmeth->paramgen) {
++    OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
++    return 0;
++  }
++  if (ctx->operation != EVP_PKEY_OP_PARAMGEN) {
++    OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATON_NOT_INITIALIZED);
++    return 0;
++  }
++
++  if (!out_pkey) {
++    return 0;
++  }
++
++  if (!*out_pkey) {
++    *out_pkey = EVP_PKEY_new();
++    if (!*out_pkey) {
++      OPENSSL_PUT_ERROR(EVP, ERR_LIB_EVP);
++      return 0;
++    }
++  }
++
++  if (!ctx->pmeth->paramgen(ctx, *out_pkey)) {
++    EVP_PKEY_free(*out_pkey);
++    *out_pkey = NULL;
+     return 0;
+   }
+   return 1;
+diff --git a/crypto/evp/evp_extra_test.cc b/crypto/evp/evp_extra_test.cc
+index f12650ef11f15a4bcd2c4e3a1bc08fb7e3e07abc..1f6a61d35034bae1581277389d779b9f5404fe92 100644
+--- a/crypto/evp/evp_extra_test.cc
++++ b/crypto/evp/evp_extra_test.cc
+@@ -638,3 +638,60 @@ TEST(EVPExtraTest, Ed25519) {
+   EXPECT_FALSE(EVP_DigestVerifyFinal(ctx.get(), nullptr, 0));
+   ERR_clear_error();
+ }
++
++static void ExpectECGroupOnly(const EVP_PKEY *pkey, int nid) {
++  EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey);
++  ASSERT_TRUE(ec);
++  const EC_GROUP *group = EC_KEY_get0_group(ec);
++  ASSERT_TRUE(group);
++  EXPECT_EQ(nid, EC_GROUP_get_curve_name(group));
++  EXPECT_FALSE(EC_KEY_get0_public_key(ec));
++  EXPECT_FALSE(EC_KEY_get0_private_key(ec));
++}
++
++static void ExpectECGroupAndKey(const EVP_PKEY *pkey, int nid) {
++  EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey);
++  ASSERT_TRUE(ec);
++  const EC_GROUP *group = EC_KEY_get0_group(ec);
++  ASSERT_TRUE(group);
++  EXPECT_EQ(nid, EC_GROUP_get_curve_name(group));
++  EXPECT_TRUE(EC_KEY_get0_public_key(ec));
++  EXPECT_TRUE(EC_KEY_get0_private_key(ec));
++}
++
++TEST(EVPExtraTest, ECKeygen) {
++  // |EVP_PKEY_paramgen| may be used as an extremely roundabout way to get an
++  // |EC_GROUP|.
++  bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_EC, nullptr));
++  ASSERT_TRUE(ctx);
++  ASSERT_TRUE(EVP_PKEY_paramgen_init(ctx.get()));
++  ASSERT_TRUE(
++      EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx.get(), NID_X9_62_prime256v1));
++  EVP_PKEY *raw = nullptr;
++  ASSERT_TRUE(EVP_PKEY_paramgen(ctx.get(), &raw));
++  bssl::UniquePtr<EVP_PKEY> pkey(raw);
++  raw = nullptr;
++  ExpectECGroupOnly(pkey.get(), NID_X9_62_prime256v1);
++
++  // That resulting |EVP_PKEY| may be used as a template for key generation.
++  ctx.reset(EVP_PKEY_CTX_new(pkey.get(), nullptr));
++  ASSERT_TRUE(ctx);
++  ASSERT_TRUE(EVP_PKEY_keygen_init(ctx.get()));
++  raw = nullptr;
++  ASSERT_TRUE(EVP_PKEY_keygen(ctx.get(), &raw));
++  pkey.reset(raw);
++  raw = nullptr;
++  ExpectECGroupAndKey(pkey.get(), NID_X9_62_prime256v1);
++
++  // |EVP_PKEY_paramgen| may also be skipped.
++  ctx.reset(EVP_PKEY_CTX_new_id(EVP_PKEY_EC, nullptr));
++  ASSERT_TRUE(ctx);
++  ASSERT_TRUE(EVP_PKEY_keygen_init(ctx.get()));
++  ASSERT_TRUE(
++      EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx.get(), NID_X9_62_prime256v1));
++  raw = nullptr;
++  ASSERT_TRUE(EVP_PKEY_keygen(ctx.get(), &raw));
++  pkey.reset(raw);
++  raw = nullptr;
++  ExpectECGroupAndKey(pkey.get(), NID_X9_62_prime256v1);
++}
+diff --git a/crypto/evp/internal.h b/crypto/evp/internal.h
+index 4aefa3526235b499fe85f55fae4b0ab38ca44dbe..43847ea16655dac1061cbb9f4c9a4d18fc03e777 100644
+--- a/crypto/evp/internal.h
++++ b/crypto/evp/internal.h
+@@ -119,6 +119,7 @@ struct evp_pkey_asn1_method_st {
+ #define EVP_PKEY_OP_ENCRYPT (1 << 6)
+ #define EVP_PKEY_OP_DECRYPT (1 << 7)
+ #define EVP_PKEY_OP_DERIVE (1 << 8)
++#define EVP_PKEY_OP_PARAMGEN (1 << 9)
+ 
+ #define EVP_PKEY_OP_TYPE_SIG \
+   (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY | EVP_PKEY_OP_VERIFYRECOVER)
+@@ -128,7 +129,7 @@ struct evp_pkey_asn1_method_st {
+ #define EVP_PKEY_OP_TYPE_NOGEN \
+   (EVP_PKEY_OP_SIG | EVP_PKEY_OP_CRYPT | EVP_PKEY_OP_DERIVE)
+ 
+-#define EVP_PKEY_OP_TYPE_GEN EVP_PKEY_OP_KEYGEN
++#define EVP_PKEY_OP_TYPE_GEN (EVP_PKEY_OP_KEYGEN | EVP_PKEY_OP_PARAMGEN)
+ 
+ // EVP_PKEY_CTX_ctrl performs |cmd| on |ctx|. The |keytype| and |optype|
+ // arguments can be -1 to specify that any type and operation are acceptable,
+@@ -171,6 +172,7 @@ OPENSSL_EXPORT int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype,
+ #define EVP_PKEY_CTRL_GET_RSA_MGF1_MD (EVP_PKEY_ALG_CTRL + 10)
+ #define EVP_PKEY_CTRL_RSA_OAEP_LABEL (EVP_PKEY_ALG_CTRL + 11)
+ #define EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL (EVP_PKEY_ALG_CTRL + 12)
++#define EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID (EVP_PKEY_ALG_CTRL + 13)
+ 
+ struct evp_pkey_ctx_st {
+   // Method associated with this operation
+@@ -219,6 +221,8 @@ struct evp_pkey_method_st {
+ 
+   int (*derive)(EVP_PKEY_CTX *ctx, uint8_t *key, size_t *keylen);
+ 
++  int (*paramgen)(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey);
++
+   int (*ctrl)(EVP_PKEY_CTX *ctx, int type, int p1, void *p2);
+ } /* EVP_PKEY_METHOD */;
+ 
+diff --git a/crypto/evp/p_ec.c b/crypto/evp/p_ec.c
+index d311d22091150b0f8fd381ba0b1c2b305c0e2f06..9c325ae0cf6683e1bff366e8cf6ed17b6132ca1d 100644
+--- a/crypto/evp/p_ec.c
++++ b/crypto/evp/p_ec.c
+@@ -76,6 +76,7 @@
+ typedef struct {
+   // message digest
+   const EVP_MD *md;
++  EC_GROUP *gen_group;
+ } EC_PKEY_CTX;
+ 
+ 
+@@ -111,6 +112,7 @@ static void pkey_ec_cleanup(EVP_PKEY_CTX *ctx) {
+     return;
+   }
+ 
++  EC_GROUP_free(dctx->gen_group);
+   OPENSSL_free(dctx);
+ }
+ 
+@@ -199,6 +201,16 @@ static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) {
+       // Default behaviour is OK
+       return 1;
+ 
++    case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID: {
++      EC_GROUP *group = EC_GROUP_new_by_curve_name(p1);
++      if (group == NULL) {
++        return 0;
++      }
++      EC_GROUP_free(dctx->gen_group);
++      dctx->gen_group = group;
++      return 1;
++    }
++
+     default:
+       OPENSSL_PUT_ERROR(EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+       return 0;
+@@ -206,14 +218,35 @@ static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) {
+ }
+ 
+ static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) {
+-  if (ctx->pkey == NULL) {
++  EC_PKEY_CTX *dctx = ctx->data;
++  const EC_GROUP *group = dctx->gen_group;
++  if (group == NULL) {
++    if (ctx->pkey == NULL) {
++      OPENSSL_PUT_ERROR(EVP, EVP_R_NO_PARAMETERS_SET);
++      return 0;
++    }
++    group = EC_KEY_get0_group(ctx->pkey->pkey.ec);
++  }
++  EC_KEY *ec = EC_KEY_new();
++  if (ec == NULL ||
++      !EC_KEY_set_group(ec, group) ||
++      !EC_KEY_generate_key(ec)) {
++    EC_KEY_free(ec);
++    return 0;
++  }
++  EVP_PKEY_assign_EC_KEY(pkey, ec);
++  return 1;
++}
++
++static int pkey_ec_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) {
++  EC_PKEY_CTX *dctx = ctx->data;
++  if (dctx->gen_group == NULL) {
+     OPENSSL_PUT_ERROR(EVP, EVP_R_NO_PARAMETERS_SET);
+     return 0;
+   }
+   EC_KEY *ec = EC_KEY_new();
+   if (ec == NULL ||
+-      !EC_KEY_set_group(ec, EC_KEY_get0_group(ctx->pkey->pkey.ec)) ||
+-      !EC_KEY_generate_key(ec)) {
++      !EC_KEY_set_group(ec, dctx->gen_group)) {
+     EC_KEY_free(ec);
+     return 0;
+   }
+@@ -235,5 +268,20 @@ const EVP_PKEY_METHOD ec_pkey_meth = {
+     NULL /* encrypt */,
+     NULL /* decrypt */,
+     pkey_ec_derive,
++    pkey_ec_paramgen,
+     pkey_ec_ctrl,
+ };
++
++int EVP_PKEY_CTX_set_ec_paramgen_curve_nid(EVP_PKEY_CTX *ctx, int nid) {
++  return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_TYPE_GEN,
++                           EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID, nid, NULL);
++}
++
++int EVP_PKEY_CTX_set_ec_param_enc(EVP_PKEY_CTX *ctx, int encoding) {
++  // BoringSSL only supports named curve syntax.
++  if (encoding != OPENSSL_EC_NAMED_CURVE) {
++    OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PARAMETERS);
++    return 0;
++  }
++  return 1;
++}
+diff --git a/crypto/evp/p_ed25519.c b/crypto/evp/p_ed25519.c
+index 554a379c7501dae26b6047e65c061523c0372f08..062ea458819d0dca3e86d5c4d41abac9bb319a9b 100644
+--- a/crypto/evp/p_ed25519.c
++++ b/crypto/evp/p_ed25519.c
+@@ -67,5 +67,6 @@ const EVP_PKEY_METHOD ed25519_pkey_meth = {
+     NULL /* encrypt */,
+     NULL /* decrypt */,
+     NULL /* derive */,
++    NULL /* paramgen */,
+     NULL /* ctrl */,
+ };
+diff --git a/crypto/evp/p_rsa.c b/crypto/evp/p_rsa.c
+index cfc6bea1e29d6b1d9ff1cd7337d07010e51af203..eb59901e3c7fe85e89219d5698ce04325b984a2a 100644
+--- a/crypto/evp/p_rsa.c
++++ b/crypto/evp/p_rsa.c
+@@ -553,7 +553,8 @@ const EVP_PKEY_METHOD rsa_pkey_meth = {
+     pkey_rsa_verify_recover,
+     pkey_rsa_encrypt,
+     pkey_rsa_decrypt,
+-    0 /* derive */,
++    NULL /* derive */,
++    NULL /* paramgen */,
+     pkey_rsa_ctrl,
+ };
+ 
+diff --git a/include/openssl/ec.h b/include/openssl/ec.h
+index 16dadf27a7b31da6ecacd573759d0da7b4ce1372..fcecb62252a97ae5ea703ac16760863de8702316 100644
+--- a/include/openssl/ec.h
++++ b/include/openssl/ec.h
+@@ -325,6 +325,7 @@ OPENSSL_EXPORT int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order,
+ OPENSSL_EXPORT void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag);
+ 
+ #define OPENSSL_EC_NAMED_CURVE 0
++#define OPENSSL_EC_EXPLICIT_CURVE 1
+ 
+ typedef struct ec_method_st EC_METHOD;
+ 
+diff --git a/include/openssl/evp.h b/include/openssl/evp.h
+index cbe93d80f480d2816aaccbb7df02d80e9c1db678..c4469841fd482527bf2ee5c8af1fafccb665af4c 100644
+--- a/include/openssl/evp.h
++++ b/include/openssl/evp.h
+@@ -646,9 +646,23 @@ OPENSSL_EXPORT int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, uint8_t *key,
+ OPENSSL_EXPORT int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx);
+ 
+ // EVP_PKEY_keygen performs a key generation operation using the values from
+-// |ctx| and sets |*ppkey| to a fresh |EVP_PKEY| containing the resulting key.
++// |ctx|. If |*out_pkey| is non-NULL, it overwrites |*out_pkey| with the
++// resulting key. Otherwise, it sets |*out_pkey| to a newly-allocated |EVP_PKEY|
++// containing the result. It returns one on success or zero on error.
++OPENSSL_EXPORT int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **out_pkey);
++
++// EVP_PKEY_paramgen_init initialises an |EVP_PKEY_CTX| for a parameter
++// generation operation. It should be called before |EVP_PKEY_paramgen|.
++//
+ // It returns one on success or zero on error.
+-OPENSSL_EXPORT int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey);
++OPENSSL_EXPORT int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx);
++
++// EVP_PKEY_paramgen performs a parameter generation using the values from
++// |ctx|. If |*out_pkey| is non-NULL, it overwrites |*out_pkey| with the
++// resulting parameters, but no key. Otherwise, it sets |*out_pkey| to a
++// newly-allocated |EVP_PKEY| containing the result. It returns one on success
++// or zero on error.
++OPENSSL_EXPORT int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **out_pkey);
+ 
+ 
+ // Generic control functions.
+@@ -746,6 +760,15 @@ OPENSSL_EXPORT int EVP_PKEY_CTX_get0_rsa_oaep_label(EVP_PKEY_CTX *ctx,
+                                                     const uint8_t **out_label);
+ 
+ 
++// EC specific control functions.
++
++// EVP_PKEY_CTX_set_ec_paramgen_curve_nid sets the curve used for
++// |EVP_PKEY_keygen| or |EVP_PKEY_paramgen| operations to |nid|. It returns one
++// on success and zero on error.
++OPENSSL_EXPORT int EVP_PKEY_CTX_set_ec_paramgen_curve_nid(EVP_PKEY_CTX *ctx,
++                                                          int nid);
++
++
+ // Deprecated functions.
+ 
+ // EVP_PKEY_DH is defined for compatibility, but it is impossible to create an
+@@ -846,6 +869,11 @@ OPENSSL_EXPORT DH *EVP_PKEY_get0_DH(const EVP_PKEY *pkey);
+ // EVP_PKEY_get1_DH returns NULL.
+ OPENSSL_EXPORT DH *EVP_PKEY_get1_DH(const EVP_PKEY *pkey);
+ 
++// EVP_PKEY_CTX_set_ec_param_enc returns one if |encoding| is
++// |OPENSSL_EC_NAMED_CURVE| or zero with an error otherwise.
++OPENSSL_EXPORT int EVP_PKEY_CTX_set_ec_param_enc(EVP_PKEY_CTX *ctx,
++                                                 int encoding);
++
+ 
+ // Preprocessor compatibility section (hidden).
+ //

+ 179 - 0
patches/common/boringssl/add_some_node_compatibility_functions.patch

@@ -0,0 +1,179 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: David Benjamin <[email protected]>
+Date: Fri, 25 Jan 2019 04:44:22 +0000
+Subject: Add some Node compatibility functions.
+
+This doesn't cover all the functions used by Node, but it's the easy
+bits. (EVP_PKEY_paramgen will be done separately as its a non-trivial
+bit of machinery.)
+
+Change-Id: I6501e99f9239ffcdcc57b961ebe85d0ad3965549
+Reviewed-on: https://boringssl-review.googlesource.com/c/34544
+Reviewed-by: Adam Langley <[email protected]>
+Commit-Queue: Adam Langley <[email protected]>
+
+diff --git a/crypto/bn_extra/convert.c b/crypto/bn_extra/convert.c
+index 9a1a69e3360bceaa673da8747b487a56049d10f3..6e930fc69f795f0cb2b2d0cb85d4fa2118c98fc9 100644
+--- a/crypto/bn_extra/convert.c
++++ b/crypto/bn_extra/convert.c
+@@ -460,3 +460,11 @@ BIGNUM *BN_mpi2bn(const uint8_t *in, size_t len, BIGNUM *out) {
+   }
+   return out;
+ }
++
++int BN_bn2binpad(const BIGNUM *in, uint8_t *out, int len) {
++  if (len < 0 ||
++      !BN_bn2bin_padded(out, (size_t)len, in)) {
++    return -1;
++  }
++  return len;
++}
+diff --git a/crypto/evp/evp_asn1.c b/crypto/evp/evp_asn1.c
+index 383e2f9b8136827cdc4d1072b181afefa8fee4d2..d56b93b03891acfcc6a892459f232503b698c04a 100644
+--- a/crypto/evp/evp_asn1.c
++++ b/crypto/evp/evp_asn1.c
+@@ -344,3 +344,44 @@ int i2d_PublicKey(const EVP_PKEY *key, uint8_t **outp) {
+       return -1;
+   }
+ }
++
++EVP_PKEY *d2i_PublicKey(int type, EVP_PKEY **out, const uint8_t **inp,
++                        long len) {
++  EVP_PKEY *ret = EVP_PKEY_new();
++  if (ret == NULL) {
++    return NULL;
++  }
++
++  CBS cbs;
++  CBS_init(&cbs, *inp, len < 0 ? 0 : (size_t)len);
++  switch (type) {
++    case EVP_PKEY_RSA: {
++      RSA *rsa = RSA_parse_public_key(&cbs);
++      if (rsa == NULL || !EVP_PKEY_assign_RSA(ret, rsa)) {
++        RSA_free(rsa);
++        goto err;
++      }
++      break;
++    }
++
++    // Unlike OpenSSL, we do not support EC keys with this API. The raw EC
++    // public key serialization requires knowing the group. In OpenSSL, calling
++    // this function with |EVP_PKEY_EC| and setting |out| to NULL does not work.
++    // It requires |*out| to include a partially-initiazed |EVP_PKEY| to extract
++    // the group.
++    default:
++      OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
++      goto err;
++  }
++
++  *inp = CBS_data(&cbs);
++  if (out != NULL) {
++    EVP_PKEY_free(*out);
++    *out = ret;
++  }
++  return ret;
++
++err:
++  EVP_PKEY_free(ret);
++  return NULL;
++}
+diff --git a/crypto/fipsmodule/ec/ec.c b/crypto/fipsmodule/ec/ec.c
+index 90b9d71f61f8d6d7ddf838c47a59729748d0d0f2..4ea5529bf45566bb454f21ca96637b88de6d4de9 100644
+--- a/crypto/fipsmodule/ec/ec.c
++++ b/crypto/fipsmodule/ec/ec.c
+@@ -660,6 +660,22 @@ const char *EC_curve_nid2nist(int nid) {
+   return NULL;
+ }
+ 
++int EC_curve_nist2nid(const char *name) {
++  if (strcmp(name, "P-224") == 0) {
++    return NID_secp224r1;
++  }
++  if (strcmp(name, "P-256") == 0) {
++    return NID_X9_62_prime256v1;
++  }
++  if (strcmp(name, "P-384") == 0) {
++    return NID_secp384r1;
++  }
++  if (strcmp(name, "P-521") == 0) {
++    return NID_secp521r1;
++  }
++  return NID_undef;
++}
++
+ EC_POINT *EC_POINT_new(const EC_GROUP *group) {
+   if (group == NULL) {
+     OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
+diff --git a/include/openssl/bn.h b/include/openssl/bn.h
+index c198f4df3ca7622e19b4e901213e84253fad0f29..b6b7e9abff979ebba04691a88cbc778cc62609c5 100644
+--- a/include/openssl/bn.h
++++ b/include/openssl/bn.h
+@@ -932,6 +932,12 @@ OPENSSL_EXPORT BN_MONT_CTX *BN_MONT_CTX_new(void);
+ OPENSSL_EXPORT int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod,
+                                    BN_CTX *ctx);
+ 
++// BN_bn2binpad behaves like |BN_bn2bin_padded|, but it returns |len| on success
++// and -1 on error.
++//
++// Use |BN_bn2bin_padded| instead. It is |size_t|-clean.
++OPENSSL_EXPORT int BN_bn2binpad(const BIGNUM *in, uint8_t *out, int len);
++
+ 
+ // Private functions
+ 
+diff --git a/include/openssl/ec.h b/include/openssl/ec.h
+index c65a1a7519fd80b681d1cf899792ee46aaa8bad6..16dadf27a7b31da6ecacd573759d0da7b4ce1372 100644
+--- a/include/openssl/ec.h
++++ b/include/openssl/ec.h
+@@ -162,6 +162,11 @@ OPENSSL_EXPORT unsigned EC_GROUP_get_degree(const EC_GROUP *group);
+ // for |NID_X9_62_prime256v1|.
+ OPENSSL_EXPORT const char *EC_curve_nid2nist(int nid);
+ 
++// EC_curve_nist2nid returns the NID of the elliptic curve specified by the NIST
++// name |name|, or |NID_undef| if |name| is not a recognized name. For example,
++// it returns |NID_X9_62_prime256v1| for "P-256".
++OPENSSL_EXPORT int EC_curve_nist2nid(const char *name);
++
+ 
+ // Points on elliptic curves.
+ 
+diff --git a/include/openssl/evp.h b/include/openssl/evp.h
+index 1d7192daf542ce227135a74914891b0ae39c9bb3..cbe93d80f480d2816aaccbb7df02d80e9c1db678 100644
+--- a/include/openssl/evp.h
++++ b/include/openssl/evp.h
+@@ -826,6 +826,20 @@ OPENSSL_EXPORT EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **out,
+ OPENSSL_EXPORT EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **out, const uint8_t **inp,
+                                             long len);
+ 
++// d2i_PublicKey parse a public key from |len| bytes at |*inp| in a type-
++// specific format specified by |type|. If |out| is not NULL then, on exit, a
++// pointer to the result is in |*out|. Note that, even if |*out| is already non-
++// NULL on entry, it will not be written to. Rather, a fresh |EVP_PKEY| is
++// allocated and the previous one is freed. On successful exit, |*inp| is
++// advanced past the decoded key. It returns the result or NULL on error.
++//
++// RSA keys are parsed as a DER-encoded RSAPublicKey (RFC 3447) structure.
++// Parsing EC keys is not supported by this function.
++//
++// Use |RSA_parse_public_key| instead.
++OPENSSL_EXPORT EVP_PKEY *d2i_PublicKey(int type, EVP_PKEY **out,
++                                       const uint8_t **inp, long len);
++
+ // EVP_PKEY_get0_DH returns NULL.
+ OPENSSL_EXPORT DH *EVP_PKEY_get0_DH(const EVP_PKEY *pkey);
+ 
+diff --git a/include/openssl/mem.h b/include/openssl/mem.h
+index 9f9c00dd547a3f3b55c2af5c1d40a56c0feb83bd..4e1c2ca64dd4225d08cc6ab3c1379baac075d1c6 100644
+--- a/include/openssl/mem.h
++++ b/include/openssl/mem.h
+@@ -136,6 +136,10 @@ OPENSSL_EXPORT int BIO_vsnprintf(char *buf, size_t n, const char *format,
+ #define CRYPTO_realloc OPENSSL_realloc
+ #define CRYPTO_free OPENSSL_free
+ 
++// OPENSSL_clear_free calls |OPENSSL_free|. BoringSSL automatically clears all
++// allocations on free, but we define |OPENSSL_clear_free| for compatibility.
++#define OPENSSL_clear_free(ptr, len) OPENSSL_free(ptr)
++
+ 
+ #if defined(__cplusplus)
+ }  // extern C

+ 40 - 0
patches/common/boringssl/silence_unused_variable_warnings_when_using_openssl_clear_free.patch

@@ -0,0 +1,40 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Jeremy Apthorp <[email protected]>
+Date: Mon, 4 Mar 2019 11:09:13 -0800
+Subject: silence unused variable warnings when using OPENSSL_clear_free
+
+e.g. here: https://github.com/nodejs/node/blob/adbe3b837e8a2285238ec0fcba89c20882eb4cdb/src/node_crypto.cc#L3439
+
+Change-Id: I2d43a3439d6a56c8eee3636b3c1f5ba615b233ba
+Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/35144
+Reviewed-by: Adam Langley <[email protected]>
+Commit-Queue: Adam Langley <[email protected]>
+
+diff --git a/crypto/mem.c b/crypto/mem.c
+index a06061b49a0753aad4c567e94bb1587e2c6d49ea..6af532eee13c0c783122f3bd20d4d7e1eed66333 100644
+--- a/crypto/mem.c
++++ b/crypto/mem.c
+@@ -153,6 +153,10 @@ void OPENSSL_cleanse(void *ptr, size_t len) {
+ #endif  // !OPENSSL_NO_ASM
+ }
+ 
++void OPENSSL_clear_free(void *ptr, size_t unused) {
++  OPENSSL_free(ptr);
++}
++
+ int CRYPTO_memcmp(const void *in_a, const void *in_b, size_t len) {
+   const uint8_t *a = in_a;
+   const uint8_t *b = in_b;
+diff --git a/include/openssl/mem.h b/include/openssl/mem.h
+index 4e1c2ca64dd4225d08cc6ab3c1379baac075d1c6..2e25f52a7fdc4c9973dc9aa4128cbdc47f27e3d7 100644
+--- a/include/openssl/mem.h
++++ b/include/openssl/mem.h
+@@ -138,7 +138,7 @@ OPENSSL_EXPORT int BIO_vsnprintf(char *buf, size_t n, const char *format,
+ 
+ // OPENSSL_clear_free calls |OPENSSL_free|. BoringSSL automatically clears all
+ // allocations on free, but we define |OPENSSL_clear_free| for compatibility.
+-#define OPENSSL_clear_free(ptr, len) OPENSSL_free(ptr)
++OPENSSL_EXPORT void OPENSSL_clear_free(void *ptr, size_t len);
+ 
+ 
+ #if defined(__cplusplus)

+ 187 - 0
patches/common/boringssl/support_get_versions_with_get_min_max_proto_version_for_context.patch

@@ -0,0 +1,187 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Nitish Sakhawalkar <[email protected]>
+Date: Mon, 25 Mar 2019 17:26:59 -0700
+Subject: Support get versions with get_{min,max}_proto_version for context
+
+When building node with boringssl, `SSL_CTX_get_min_proto_version` and
+`SSL_CTX_get_max_proto_version` are used. Openssl exposes those; this
+change adds support for boringssl.
+
+For this to work right in DTLS, we switch conf_{min,max}_version to store wire
+versions, rather than our internal normalized versions.
+
+Change-Id: I282ed224806c41f69e6f166ca97c6cc05ff51f17
+Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/35404
+Reviewed-by: Nitish Sakhawalkar <[email protected]>
+Reviewed-by: David Benjamin <[email protected]>
+Commit-Queue: David Benjamin <[email protected]>
+
+diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
+index d5883950d48d8c1be63bcbca23a455803494a49e..7078c4d3f7d1ffae842d2e715fa1a6ee483cea99 100644
+--- a/include/openssl/ssl.h
++++ b/include/openssl/ssl.h
+@@ -634,6 +634,12 @@ OPENSSL_EXPORT int SSL_CTX_set_min_proto_version(SSL_CTX *ctx,
+ OPENSSL_EXPORT int SSL_CTX_set_max_proto_version(SSL_CTX *ctx,
+                                                  uint16_t version);
+ 
++// SSL_CTX_get_min_proto_version returns the minimum protocol version for |ctx|
++OPENSSL_EXPORT uint16_t SSL_CTX_get_min_proto_version(SSL_CTX *ctx);
++
++// SSL_CTX_get_max_proto_version returns the maximum protocol version for |ctx|
++OPENSSL_EXPORT uint16_t SSL_CTX_get_max_proto_version(SSL_CTX *ctx);
++
+ // SSL_set_min_proto_version sets the minimum protocol version for |ssl| to
+ // |version|. If |version| is zero, the default minimum version is used. It
+ // returns one on success and zero if |version| is invalid.
+diff --git a/ssl/internal.h b/ssl/internal.h
+index bc45b504cfca436349d7c3411322b2497c426bcb..169cbfec78b24c13e259fb9ebc830cb28605a55b 100644
+--- a/ssl/internal.h
++++ b/ssl/internal.h
+@@ -2403,14 +2403,14 @@ struct SSL_CONFIG {
+   // ssl is a non-owning pointer to the parent |SSL| object.
+   SSL *const ssl = nullptr;
+ 
+-  // conf_max_version is the maximum acceptable protocol version configured by
+-  // |SSL_set_max_proto_version|. Note this version is normalized in DTLS and is
+-  // further constrainted by |SSL_OP_NO_*|.
++  // conf_max_version is the maximum acceptable version configured by
++  // |SSL_set_max_proto_version|. Note this version is not normalized in DTLS
++  // and is further constrained by |SSL_OP_NO_*|.
+   uint16_t conf_max_version = 0;
+ 
+-  // conf_min_version is the minimum acceptable protocol version configured by
+-  // |SSL_set_min_proto_version|. Note this version is normalized in DTLS and is
+-  // further constrainted by |SSL_OP_NO_*|.
++  // conf_min_version is the minimum acceptable version configured by
++  // |SSL_set_min_proto_version|. Note this version is not normalized in DTLS
++  // and is further constrained by |SSL_OP_NO_*|.
+   uint16_t conf_min_version = 0;
+ 
+   X509_VERIFY_PARAM *param = nullptr;
+diff --git a/ssl/ssl_test.cc b/ssl/ssl_test.cc
+index 1f09156efa2d449ab84fe10972e32d5c208e0324..d90a466a9aa32e04d239f8edb4fdb170e0a47dd2 100644
+--- a/ssl/ssl_test.cc
++++ b/ssl/ssl_test.cc
+@@ -840,8 +840,8 @@ static void ExpectDefaultVersion(uint16_t min_version, uint16_t max_version,
+                                  const SSL_METHOD *(*method)(void)) {
+   bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(method()));
+   ASSERT_TRUE(ctx);
+-  EXPECT_EQ(min_version, ctx->conf_min_version);
+-  EXPECT_EQ(max_version, ctx->conf_max_version);
++  EXPECT_EQ(min_version, SSL_CTX_get_min_proto_version(ctx.get()));
++  EXPECT_EQ(max_version, SSL_CTX_get_max_proto_version(ctx.get()));
+ }
+ 
+ TEST(SSLTest, DefaultVersion) {
+@@ -850,9 +850,9 @@ TEST(SSLTest, DefaultVersion) {
+   ExpectDefaultVersion(TLS1_VERSION, TLS1_VERSION, &TLSv1_method);
+   ExpectDefaultVersion(TLS1_1_VERSION, TLS1_1_VERSION, &TLSv1_1_method);
+   ExpectDefaultVersion(TLS1_2_VERSION, TLS1_2_VERSION, &TLSv1_2_method);
+-  ExpectDefaultVersion(TLS1_1_VERSION, TLS1_2_VERSION, &DTLS_method);
+-  ExpectDefaultVersion(TLS1_1_VERSION, TLS1_1_VERSION, &DTLSv1_method);
+-  ExpectDefaultVersion(TLS1_2_VERSION, TLS1_2_VERSION, &DTLSv1_2_method);
++  ExpectDefaultVersion(DTLS1_VERSION, DTLS1_2_VERSION, &DTLS_method);
++  ExpectDefaultVersion(DTLS1_VERSION, DTLS1_VERSION, &DTLSv1_method);
++  ExpectDefaultVersion(DTLS1_2_VERSION, DTLS1_2_VERSION, &DTLSv1_2_method);
+ }
+ 
+ TEST(SSLTest, CipherProperties) {
+@@ -2617,13 +2617,13 @@ TEST(SSLTest, SetVersion) {
+ 
+   // Zero is the default version.
+   EXPECT_TRUE(SSL_CTX_set_max_proto_version(ctx.get(), 0));
+-  EXPECT_EQ(TLS1_2_VERSION, ctx->conf_max_version);
++  EXPECT_EQ(TLS1_2_VERSION, SSL_CTX_get_max_proto_version(ctx.get()));
+   EXPECT_TRUE(SSL_CTX_set_min_proto_version(ctx.get(), 0));
+-  EXPECT_EQ(TLS1_VERSION, ctx->conf_min_version);
++  EXPECT_EQ(TLS1_VERSION, SSL_CTX_get_min_proto_version(ctx.get()));
+ 
+   // TLS 1.3 is available, but not by default.
+   EXPECT_TRUE(SSL_CTX_set_max_proto_version(ctx.get(), TLS1_3_VERSION));
+-  EXPECT_EQ(TLS1_3_VERSION, ctx->conf_max_version);
++  EXPECT_EQ(TLS1_3_VERSION, SSL_CTX_get_max_proto_version(ctx.get()));
+ 
+   // SSL 3.0 is not available.
+   EXPECT_FALSE(SSL_CTX_set_min_proto_version(ctx.get(), SSL3_VERSION));
+@@ -2651,9 +2651,9 @@ TEST(SSLTest, SetVersion) {
+   EXPECT_FALSE(SSL_CTX_set_min_proto_version(ctx.get(), 0x1234));
+ 
+   EXPECT_TRUE(SSL_CTX_set_max_proto_version(ctx.get(), 0));
+-  EXPECT_EQ(TLS1_2_VERSION, ctx->conf_max_version);
++  EXPECT_EQ(DTLS1_2_VERSION, SSL_CTX_get_max_proto_version(ctx.get()));
+   EXPECT_TRUE(SSL_CTX_set_min_proto_version(ctx.get(), 0));
+-  EXPECT_EQ(TLS1_1_VERSION, ctx->conf_min_version);
++  EXPECT_EQ(DTLS1_VERSION, SSL_CTX_get_min_proto_version(ctx.get()));
+ }
+ 
+ static const char *GetVersionName(uint16_t version) {
+diff --git a/ssl/ssl_versions.cc b/ssl/ssl_versions.cc
+index 861696762c5ab1eceddde83d2e7062e57677f8b5..2b72aaaf116619e0fc0c8f9447e7a1e275fc2a47 100644
+--- a/ssl/ssl_versions.cc
++++ b/ssl/ssl_versions.cc
+@@ -160,12 +160,12 @@ static bool api_version_to_wire(uint16_t *out, uint16_t version) {
+ static bool set_version_bound(const SSL_PROTOCOL_METHOD *method, uint16_t *out,
+                               uint16_t version) {
+   if (!api_version_to_wire(&version, version) ||
+-      !ssl_method_supports_version(method, version) ||
+-      !ssl_protocol_version_from_wire(out, version)) {
++      !ssl_method_supports_version(method, version)) {
+     OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_SSL_VERSION);
+     return false;
+   }
+ 
++  *out = version;
+   return true;
+ }
+ 
+@@ -173,8 +173,7 @@ static bool set_min_version(const SSL_PROTOCOL_METHOD *method, uint16_t *out,
+                             uint16_t version) {
+   // Zero is interpreted as the default minimum version.
+   if (version == 0) {
+-    // TLS 1.0 does not exist in DTLS.
+-    *out = method->is_dtls ? TLS1_1_VERSION : TLS1_VERSION;
++    *out = method->is_dtls ? DTLS1_VERSION : TLS1_VERSION;
+     return true;
+   }
+ 
+@@ -185,7 +184,7 @@ static bool set_max_version(const SSL_PROTOCOL_METHOD *method, uint16_t *out,
+                             uint16_t version) {
+   // Zero is interpreted as the default maximum version.
+   if (version == 0) {
+-    *out = TLS1_2_VERSION;
++    *out = method->is_dtls ? DTLS1_2_VERSION : TLS1_2_VERSION;
+     return true;
+   }
+ 
+@@ -214,8 +213,14 @@ bool ssl_get_version_range(const SSL_HANDSHAKE *hs, uint16_t *out_min_version,
+     }
+   }
+ 
+-  uint16_t min_version = hs->config->conf_min_version;
+-  uint16_t max_version = hs->config->conf_max_version;
++  uint16_t min_version, max_version;
++  if (!ssl_protocol_version_from_wire(&min_version,
++                                      hs->config->conf_min_version) ||
++      !ssl_protocol_version_from_wire(&max_version,
++                                      hs->config->conf_max_version)) {
++    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
++    return false;
++  }
+ 
+   // QUIC requires TLS 1.3.
+   if (hs->ssl->ctx->quic_method && min_version < TLS1_3_VERSION) {
+@@ -389,6 +394,14 @@ int SSL_CTX_set_max_proto_version(SSL_CTX *ctx, uint16_t version) {
+   return set_max_version(ctx->method, &ctx->conf_max_version, version);
+ }
+ 
++uint16_t SSL_CTX_get_min_proto_version(SSL_CTX *ctx) {
++  return ctx->conf_min_version;
++}
++
++uint16_t SSL_CTX_get_max_proto_version(SSL_CTX *ctx) {
++  return ctx->conf_max_version;
++}
++
+ int SSL_set_min_proto_version(SSL *ssl, uint16_t version) {
+   if (!ssl->config) {
+     return 0;

+ 4 - 0
spec/asar-spec.js

@@ -1231,6 +1231,10 @@ describe('asar package', function () {
       })
       child.send('message')
     })
+
+    it('can be used with streams', () => {
+      originalFs.createReadStream(path.join(fixtures, 'asar', 'a.asar'))
+    })
   })
 
   describe('graceful-fs module', function () {